管理画面を作る：AdminLTE Laravel応用編


以前、[AdminLTEをLaravelのbladeでテンプレート化する方法](http://qiita.com/zaburo/items/b9e769c7c4a87614b3f9)を書きました。が、実際に管理画面を作るためには階層構造など、もう少し考える点があるので、それをまとめてみます。

##やりたいこと

管理画面でよくあるトップメニュー（横メニュー）に、主メニュがあり、サイドバーメニュー（縦メニュー）にサブメニューがあるという構造において、最適なテンプレート化パターン（わいる分割・階層パターン）が良いかまとめたい。

>なお、これは執筆時点（2015年8月8日）での「最適」なもので、随時更新します。

こんな画面を想定。

![adminlte](http://www.bluecode.jp/qiita/adminlte011.png)

構造としてはTOPメニューとして

* 顧客管理(member)
* 在庫管理(item)

があり、各TOPメニューに対して、

* 新規登録
* 編集

のサブメニューがあるという構成。管理画面ではよくある構成です。

##構造を考える

結論から言うと、下記のような構造にしました。

![adminlte](http://www.bluecode.jp/qiita/adminlte012.png)

まず、全体的な構成としては、

* views以下に管理画面全体を入れるadminフォルダを作成。
* 管理画面全体に共通となる要素はshareフォルダに入れる。
* 各TOPメニュー毎にサブフォルダを作る（ここでは、memberとitem）。

サブフォルダの要素としては、

* sidebarはTOPメニュー毎に違うので各サブフォルダ内に作成。
* sidebarメニューに紐づくファイルをそれぞれ作る（ここではnewとedit）。

その他の特記事項としては、

* メニューの選択状態は各ページにおいてjQueryでaddclass("active")とすることで実現。
* なので、TOPメニューとサイドメニューの各メニューにid（もしくはclass）を設定し制御します。

としました。

##コードを考える

コードの要点を見てみます。
まず、このテンプレート構造の中心となるファイルはviews/admin/share/layoutです。
少し長いですが、重要な構造なので、全部貼り付けます。

```php
<!doctype html>
<head>
    <meta charset="utf-8">
    <title>
        @yield('title')
    </title>
    <!-- for responsive -->
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <!-- bootstrap -->
    <link href="{{asset("bower_components/admin-lte/bootstrap/css/bootstrap.min.css")}}" rel="stylesheet" type="text/css" />
    <!-- font awesome -->
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
    <!-- ionicons -->
    <link href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css" />
    <!-- adminLTE style -->
    <link href="{{asset("bower_components/admin-lte/dist/css/AdminLTE.min.css")}}" rel="stylesheet" type="text/css" />
    <link href="{{asset("bower_components/admin-lte/dist/css/skins/skin-blue.min.css")}}" rel="stylesheet" type="text/css" />
    <style>
        .navbar-nav>li.active>a{
            background-color: #666;
        }
    </style>
</head>
<body class="skin-blue">
    <div class="wrapper">

        <!-- ヘッダー -->
        @include('admin.share.header')


        <!-- サイドバー -->
        {{-- @include('share.sidebar') --}}
        @yield('sidebar')


        <!-- content -->
        <div class="content-wrapper">

            <!-- コンテンツヘッダ -->
            @yield('content')

        </div><!-- end content -->


        <!-- フッター -->
        @include('admin.share.footer')


    </div><!-- end wrapper -->
    <!-- JS -->

    <!-- jquery -->
    <script src="{{asset("bower_components/admin-lte/plugins/jQuery/jQuery-2.1.4.min.js")}}" type="text/javascript"></script>
    <!-- bootstrap -->
    <script src="{{asset("bower_components/admin-lte/bootstrap/js/bootstrap.min.js")}}" type="text/javascript"></script>
    <!-- adminLTE -->
    <script src="{{asset("bower_components/admin-lte/dist/js/app.min.js")}}" type="text/javascript"></script>
    <!-- chart.js -->
    <script src="{{asset("bower_components/admin-lte/plugins/chartjs/Chart.min.js")}}" type="text/javascript"></script>

    <!-- JS記述 -->
    @yield('sctipt')

</body>
</html>
```

要点はおおよそ次の箇所です（行番号打ちたい）。

* @yield('title') タイトルは動的に変更できるようにしました。
* @include('admin.share.header') TOPメニュー部は共通要素なので、共通化しincludeします。
* @yield('sidebar')　サイドバーは動的要素になるのでincludeではなく、@yieldとし、各ファイルで定義。
* @yield('content')　コンテンツは当然動的要素になるので@yieldとして各ファイルで定義。
* @include('admin.share.footer')　フッター部は共通要素なので、共通化しincludeします。
* @yield('sctipt')　各ページで必要となるjsを記述する場所を@yieldで定義。場所は各JSファイルの読み込み後とします。

参照先になっているテンプレートファイルのコードは、[こちらの記事](http://qiita.com/zaburo/items/b9e769c7c4a87614b3f9)を参考にしてください（ここでは長くなるので割愛）。
あと、\<head>...\</head>の最後に、

```html
<style>
	.navbar-nav>li.active>a{
	    background-color: #666;
	}
</style>
```

を追加し、TOPメニューの\<li class="active">記述時のbackground-colorを定義しています（何故か、AdminLTEでは定義されていないため）。

>追記：2.2.3では修正されているようなので不要です。

##各要素を見てみる

では、顧客管理メニュー(member)のファイルを見てみます。
新規作成(new)のファイルです。

```php
@extends('admin.share.layout')

@section('title')
Member Management
@stop

@section('sidebar')
    @include('admin.member.sidebar')
@stop


@section('content')

<section class="content-header">
<h1>Member</h1>
<ol class="breadcrumb">
	<li><a href="">Home</a></li>
	<li>Memeber</li>
	<li>New</li>
</ol>
</section>

<section class="content">
	<div class="box">
		<div class="box-body">
			content
		</div>
	</div>
</section>

@stop

@section('sctipt')
<script>
$(function(){
    $("#member").addClass("active");
    $("#new").addClass("active");
});
</script>
@stop
```

要点としては、

まず、テンプレートの呼び出し、

```php
@extends('admin.share.layout')
```
これはshareで定義したメインのLayoutです。
そして、

```php
@section('sidebar')
    @include('admin.member.sidebar')
@stop
```
の箇所で、同じフォルダにあるsidebar.blade.phpを呼び出している点、

```js
@section('sctipt')
<script>
$(function(){
    $("#member").addClass("active");
    $("#new").addClass("active");
});
</script>
@stop
```
の箇所で、jsを実行し、選択されたTOPメニューと再度メニューにclass="active"を付与しているところです。もちろん、制御されるメニューにはid定義が必要です。

>サイドメニューの方は各機能毎にファイルができるので直接class="active"をハードコーディングしてもいいでしょう。

ちなみに、サイドメニュー(sidebar.blade.php)は、

```html
<!-- サイドバー -->
<aside class="main-sidebar">
    <section class="sidebar">
        <ul class="sidebar-menu">

            <!-- メニューヘッダ -->
            <li class="header">顧客管理機能一覧</li>

            <!-- メニュー項目 -->
            <li id="new"><a href="/admin/member/new">新規登録</a></li>
            <li id="edit"><a href="/admin/member/edit">編集</a></li>

        </ul>
    </section>
</aside><!-- end sidebar -->
```

こんな感じです。

##実務向け

少し発展させたものを、直ぐにLaravelに反映させられるようにしておきます。
自動化してもいいですが、とりあえず手動モード。

###Laravelのインストール

とりあえずtestという名前で作成。

```bash
composer create-project laravel/laravel test
```

###AdminLTEインストール
Laravelのpublicフォルダにadmin-lteをインストールします。

```bash
cd test/public
bower install admin-lte
```
>このとき - を忘れずに。adminlteという別のリポジトリがある。
>下の注意書きも読んで下さい。

###テンプレートインストール（展開）

* [シンプル版](http://www.bluecode.jp/qiita/admin.zip)（このサンプルで使ったもの）
* [少し発展版](http://www.bluecode.jp/qiita/admin_base.zip)（iconとかlogin画面とか加えたもの）

ダウンロードして、展開したadminフォルダをresources/views/以下に展開

###ルートを設定

```php
//member
Route::get('admin/member',function(){
	return view('admin.member.index');
});

Route::get('admin/member/new',function(){
	return view('admin.member.new');
});

Route::get('admin/member/edit',function(){
	return view('admin.member.edit');
});


//item
Route::get('admin/item',function(){
	return view('admin.item.index');
});

Route::get('admin/item/new',function(){
	return view('admin.item.new');
});

Route::get('admin/item/edit',function(){
	return view('admin.item.edit');
});

//login
Route::get('admin/login',function(){
	return view('admin.login');
});
```

###注意
ここでは、bowerで各種ライブラリをインストールしているので、基本的に最新版がインストールされます。その場合、adminテンプレート中（admin/share/layout.blade.php)のCDNのURL等に不整合が発生する可能があります。その際は、ダンロードされたAdminLTEフォルダ(bower_components/admin-lte)の中のstarter.htmlを参考にしながら、CDNのURLやローカルPathを修正するとよいでしょう。

以上です。