Windows用XAMPP+Laravel Blade Templateを使ってみる
- ※XAMPPのインストールフォルダは
D:/dev/xampp
にインストールします。 - ※XAMPPのインストールしていない場合は、WINDOWS XAMPP にて LARAVEL をインストール (XAMPP V1.8.3インストール) →
- ※Composerのインストールしていない場合は、WINDOWS XAMPP にて LARAVEL をインストール (COMPOSER 1.0.0-ALPHA8インストール) →
- ※Laravelのインストールしていない場合は、WINDOWS XAMPP にて LARAVEL をインストール (LARAVEL V4.2インストール) →
- ※Laravelの環境設定していない場合は、Windows XAMPP で Laravel 環境設定 →
- ※LaravelのDB設定していない場合は、Windows用XAMPP+Laravel DB設定 →
- ※Modelを利用するので、Eloquentを読んでいない方は、Windows用XAMPP+Laravel Eloquent →
- ※Bladeを利用するので、Bladeを読んでいない方は、Windows XAMPP で Laravel Blade →
Blade Template
前回Bladeを利用し画面を作成しましたが、今後処理を増やすことを考えると、共通部分はテンプレート化したほうが良いです。
書くソース量も少なくなるし、保守性も上がります。ちゃんと方式設計が出来ているのであれば、機能拡張など簡単に行うことが出来ます。
継承が出来るので、親-子関係となるのですが、どの部分を親に設定し、どの部分を子供(実装プログラム)に定義するかは、方式設計からの外部設計で決定します。
切り分け自体は慣れが必要になる作業なので、まずは作り、そして直すというのを何度か繰り返したほうがよいかと思います。
今回はあまり分割せずに、テンプレートと実装プログラムに分割してみようと思います。
共通部分の洗い出しを行い、親テンプレートを定義します。
共通部分になりやすいものは、大体以下です。
- メタタグ
- 共通スタイルの読み込み
- 共通jsの読み込み
- グローバルメニュー
- サイドメニュー
- フッタ
1.メタタグ
この部分はメタタグに何を設定するのかで共通化の方法が変わってきます。
keywordやdiscriptionなどは、コントローラで共通の文言を生成するのであれば共通化できるし、そうでないのであれば、実装プログラムに個別に書き込むこともできます。
出来れば、方式として $page.keyword
みたいな共通のページ属性のようなものにセットすると表示されると決めたほうがよいと思います。
2.共通スタイルの読み込み
個別のスタイルの読み込みは個別でスーパテンプレートをオーバーライドする形で実現します。
それ以外は、共通のみ読み込むように整理しておくと、あとの設定や拡張が楽になります。
3.共通jsの読み込み
スタイルと同様に個別のjsはスーパーテンプレートをオーバーライドする形で実現します。
読み込みするjsは極力抑えたほうが、ネットワークのトラフィックを考えると早くなります。
キャッシュを利用する観点からCDN(Contents Delivery Network)を利用することをオススメします。
あまり多くのドメインを運用するとDNSの検索に手間取るので、なるべくまとめたほうが良いです。
4.グローバルメニュー
共通化するときに、どこのurlにアクセスするかで、activeなどのclassを追加するなどの共通処理が必要になるこを念頭に置いてください。
5.サイドメニュー
グローバルメニューと同様に共通化するのですが、メニューのオープン/クローズ、アクティブ化などはjsの初期化処理で行うか、Blade側で行うかは方式で決定しておくとプログラマが迷わないで済みます。
6.フッタ
フッタに関しては固定テンプレートになっている場合が多いです。出来れば外部設計時に固定化してテンプレート化することをお勧めします。
前回のBladeをテンプレート化
テンプレートはviewsの下に作成します。
layoutsというホルダーを作成し、テンプレートを入れてみました。
この場合、ホルダー階層は「.」ピリオドで表します。
views/layouts/template.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{{{ $page['title'] }}}</title> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css"> <!--[if lt IE 9]> <script src="//oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="//oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> @yield('css') </head> <body> <div class="navbar navbar-fixed-top navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Dragon</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="#">active</a></li> </ul> </div><!--/.nav-collapse --> </div> </div> @yield('container') <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> @yield('js') </body> </html>
テンプレートの内容
@yield
を指定している部分は3箇所あります。
その他は共通部分として利用することを前提としています。
@yield とは、実装プログラムに @section を要求するところになります。
実装プログラムに指定されない場合は、無視されます。
@yield('css')
実装プログラム側で個別で定義する場合に、<style>タグ込で指定します。
@yield('container')
実装プログラムで内容を決定します。
@yield('js')
実装プログラム側で個別で定義する場合に、<script>タグ込で指定します。
それ以外に title は $page
という変数を作成し、共通で設定するようにしました。
実装プログラム
views/user.blade.php
@extends('layouts.template') @section('css') <style> *{ font-family: "メイリオ"; } body { padding-top: 30px; } </style> @stop @section('container') <div class="container"> <div class="page-header"> <h2> <span class="glyphicon glyphicon-user"></span> ユーザ一覧 </h2> </div> <div class="row"> <div class="col-xs-12 col-lg-12"> <form action="/user/create" method="post" class="form-horizontal"> <div class="form-group"> <label for="name" class="col-xs-2">名前</label> <div class="col-xs-4"> <input type="text" name="name" id="name" class="form-control"> </div> </div> <div class="form-group"> <label for="email" class="col-xs-2">メールアドレス</label> <div class="col-xs-4"> <input type="text" name="email" id="email" class="form-control"> </div> </div> <div class="form-group"> <label for="tel" class="col-xs-2">電話</label> <div class="col-xs-4"> <input type="text" name="tel" id="tel" class="form-control"> </div> </div> <div class="form-group"> <label for="zip" class="col-xs-2">住所</label> <div class="col-xs-10"> <div class="row"> <div class="col-xs-2"> <input type="text" name="zip" id="zip" class="form-control"> </div> <div class="col-xs-7"> <input type="text" name="address" id="address" class="form-control"> </div> </div> </div> </div> <div class="form-group"> <div class="col-xs-offset-2 col-xs-4"> <button type="submit" class="btn btn-success">登録</button> </div> </div> </form> </div> </div> <hr> <div class="row"> <div class="col-xs-12 col-lg-12"> <table class="table"> <thead> <th>切替</th> <th>操作</th> <th>#</th> <th>名前</th> <th>メール</th> <th>電話</th> <th>住所</th> </thead> <tbody> @foreach ($users as $user) <tr> <td> <button type="button" class="btn btn-info action-update">操作切替</button> </td> <td> <form action="/user/delete" method="post"> <input type="hidden" name="id" value="{{{$user->id}}}"> <button type="submit" class="btn btn-default">削除</button> </form> </td> <td>{{{$user->id}}}</td> <td>{{{$user->name}}}</td> <td>{{{$user->email}}}</td> <td>{{{$user->tel}}}</td> <td>{{{$user->zip}}} {{{$user->address}}}</td> </tr> <form action="/user/update" method="post"> <tr class="hidden"> <td> <button type="button" class="btn btn-info action-delete">操作切替</button> </td> <td> <input type="hidden" name="id" value="{{{$user->id}}}"> <button type="submit" class="btn btn-warning">更新</button> </td> <td>{{{$user->id}}}</td> <td><input type="text" class="form-control" name="name" value="{{{$user->name}}}"></td> <td><input type="text" class="form-control" name="email" value="{{{$user->email}}}"></td> <td><input type="text" class="form-control" name="tel" value="{{{$user->tel}}}"></td> <td> <div class="row"> <div class="col-xs-3"> <input type="text" class="form-control" name="zip" value="{{{$user->zip}}}"> </div> <div class="col-xs-9"> <input type="text" class="form-control" name="address" value="{{{$user->address}}}"> </div> </div> </td> </tr> </form> @endforeach </tbody> </table> </div> </div> </div><!-- /container --> @stop @section('js') <script> $(function(){ $('.action-update').on('click', function(){ $(this).parents('tr').hide().next().next().removeClass('hidden').show(); }); $('.action-delete').on('click', function(){ $(this).parents('tr').hide().prev().prev().show(); }); }); </script> @stop
実装プログラムの内容
共通部分がなくなってスッキリしました。と書きたいところですが、以外と変わらない印象です。
ここの部分は、もうちょっと本格的に作成すると随分スッキリしたという印象を持つと思います。
テンプレートで指定されている @yield
部分を @section
で埋めていくという作業を行います。
個別のstyleやjavascriptがない場合は、cssやjsのsection部分は不要になります。
その他の修正箇所
共通部分の変更を行ったので、BaseController.php、UserController.php を修正する必要があります。
controllers/BaseController.php
<?php class BaseController extends Controller { public $page = array( 'title' => 'none.' ); /** * コントローラーにより使用されるレイアウトの設定. * * @return void */ protected function setupLayout(){ if(!is_null($this->layout)){ $this->layout = View::make($this->layout); } } }
共通テンプレートに $page['title'] を利用しているので、共通で BaseController に変数を追加します。
controllers/UserController.php
<?php class UserController extends BaseController { public function getIndex(){ $page['title'] = 'ユーザ管理'; return View::make('user') ->with('users', User::orderBy('name', 'desc')->get()) ->with('page', $page); } public function postCreate(){ $user = Input::only('name', 'email', 'tel', 'zip', 'address'); User::create($user); return Redirect::to('/user'); } public function postUpdate(){ $user = Input::only('name', 'email', 'tel', 'zip', 'address'); $model = User::find(Input::get('id')); $model->update($user); return Redirect::to('/user'); } public function postDelete(){ User::destroy(Input::only('id')); return Redirect::to('/user'); } public function getAddUser(){ return 'getAddUser'; } }
page変数を追加したので、with句を追加しBlade側で参照出来るようにします。
最終的に完成する画面は以下のようになります。