laravel-adminで管理画面を速攻で構築する。

これは [日本情報クリエイト Engineers Advent Calendar 2016](/advent-calendar/2016/njc)による1日目の記事になります。
発起人ということで、初日を飾らせていただきました。

今回はタイトル通りに速攻で構築したいので、管理画面用のライブラリを利用して開発していきます。
RailsではActiveAdminという超絶便利Gemが存在するのですが、Laravelは管理画面系のライブラリが多数ありますので、選定から入ります。

※ ちなみに日本情報クリエイトではLaravelで開発してません。布教中です。
※ cakephpでの開発を主としていますので、興味の有る方は是非ご相談下さい！

# ライブラリの選定
選定基準は、
1. 更新が頻繁である
2. githubのstar数
3. 機能数
4. ドキュメントの充実
5. **速攻で出来る！**

を元に選定していきます。

## 調査
2016/11/30の情報です。

|名称|更新頻度|star数|機能数|ドキュメント|速攻で出来る|
|---|---|---|---|---|---|
|[Laravel Administrator](https://github.com/FrozenNode/Laravel-Administrator)|低い|1,863|普通|充実|できそう|
|[SleepingOwlAdmin](https://github.com/LaravelRUS/SleepingOwlAdmin) ([demo](http://demo.sleepingowladmin.ru/))|高い|274|普通|現在はロシア語しか|できそう|
|[LaravelPanel](https://github.com/serverfireteam/panel) ([demo](http://demo.serverfire.net/panel/login))|高い|343|少ない|充実|できる|
|[rapyd-laravel](https://github.com/zofe/rapyd-laravel) ([demo](http://www.rapyd.com/rapyd-demo))|高い|594|多い （ログイン機能が無い）|普通|できそう|
|[Backpack\CRUD](https://github.com/Laravel-Backpack/CRUD)|普通|305|多い|充実|準備するファイルが多い|
|[LaraAdmin](https://github.com/dwijitsolutions/laraadmin)|高い|322|多い|充実|できそう|
|[laravel-admin](https://github.com/z-song/laravel-admin) ([demo](http://120.26.143.106/admin/auth/login))|高い|558|多い|充実|できそう|

LaraAdmin と laravel-admin で悩んだのですが、star数が多い　**laravel-admin**　で管理画面を構築していきたいと思います。

# 準備

[laradock](https://github.com/laradock/laradock)で環境を準備していきます。
laradockとはlaravel用のdockerで、docker-composeで簡単に導入ができます。

## 環境

PHP7、Mysql、Redisで準備します。

## コードを入手する。

```bash
$ mkdir laravel
$ cd laravel
$ git clone https://github.com/LaraDock/laradock.git
$ cd laradock
```

## laravel5.3をインストール。

laravelをインストールするのでworkspaceを起動しコンテナに入ります。
workspaceはPHP7-CLI, Composer, Git, Node, Gulp, SQLite, xDebug, Vimなどが内包されています。

```bash
$ docker-compose up -d workspace
$ docker-compose exec workspace bash
```

ログイン後にcomposerを利用してlaravelの雛形を作成します。

```bash
root@b0546d89a9dd:/var/www# composer create-project laravel/laravel admin
```

一旦ログアウトして、laradoc/docker-compose.ymlを修正します。
`../:/var/www`を`../admin:/var/www`に変更します。

```yaml
version: '2'

services:

### Applications Code Container #############################
    applications:
        image: tianon/true
        volumes:
            - ../admin:/var/www
#            - ../sample/:/var/www/sample

### Workspace Utilities Container ###########################
```

DBが接続できるようにadmin/.envを修正します。
`DB_HOST=127.0.0.1`を`DB_HOST=mysql`に変更します。

```text
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
```

これで、サーバーを起動すれば完了です。

```bash
$ docker-compose up -d nginx mysql redis
```

http://127.0.0.1/ にアクセスして動作確認してみましょう。
以下の画面が表示されていればOKです。

<img width="1452" alt="スクリーンショット 2016-11-30 20.08.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/16194/3d5d0ca6-bb5f-eca6-898d-f41083f309ef.png">

# laravel-adminの導入

admin/composer.jsonに`laravel-admin`を追加します。

``` json
    "require": {
        "php": ">=5.6.4",
        "laravel/framework": "5.3.*",
        "encore/laravel-admin": "1.3.x-dev"
    },
```

workspaceコンテナに入ってlaravel-adminをインストールします。

```bash
$ docker-compose exec workspace bash
root@d87db1cadc44:/var/www# composer update
```

admin/config/app.php の ServiceProvider に追加します。

```php
Encore\Admin\Providers\AdminServiceProvider::class
```

最後にartisanを叩いて完了です。

```bash
root@d87db1cadc44:/var/www# php artisan vendor:publish --tag=laravel-admin
root@d87db1cadc44:/var/www# php artisan admin:install
```

http://127.0.0.1/admin
にアクセスするとログイン画面が表示されます。
username : admin
password : admin

<img width="801" alt="スクリーンショット 2016-11-30 20.29.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/16194/79e137ee-0ed0-09b5-2332-015d8ec81016.png">

これでlaravel-adminの導入は完了です。

# laravel-adminにCRUDを構築する。

## マイグレーション、モデル

まずマイグレーションファイルを作成します。

```bash
root@d87db1cadc44:/var/www# php artisan make:migration create_staffs_table --create=staffs
```

生成されたマイグレーションファイルを修正します。
admin/database/migrations/2016_11_30_135403_create_staffs_table.php

```php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateStaffsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('staffs', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->text('description');
            $table->string('picture');
            $table->string('email');
            $table->boolean('active');
            $table->integer('age');

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('staffs');
    }
}
```

データベースへ反映します。

```bash
root@d87db1cadc44:/var/www# php artisan migrate
```

モデルを作成します。

```bash
root@d87db1cadc44:/var/www# php artisan make:model Staff
```

モデルファイルに1行追加します。
テーブルが複数形であれば本来なら記述しなくてよいのですが、何故か動作しませんでした。
admin/app/Staff.php

```php
protected $table = 'staffs';
```

## コントローラー

管理画面用のコントローラーを作成します。

```bash
root@d87db1cadc44:/var/www# php artisan admin:make StaffController --model=App\\Staff
```

ルーティングを設定します。
admin/app/Admin/routes.php

```php
$router->resource('staffs', StaffController::class);
```

生成されたコントローラーファイルを修正します。

基本的に`grid`と`form`メソッドだけ修正するだけで良いです。
`grid`は一覧画面、`form`は新規、編集画面の設定をすることが出来ます。

どのようなのが設定出来るかは、[grid](https://github.com/z-song/laravel-admin/blob/master/docs/en/model-grid.md)、[form](https://github.com/z-song/laravel-admin/blob/master/docs/en/model-form.md)のドキュメントを参考にすると良いと思います。

Admin/Controllers/StaffController.php　

```php
    protected function grid()
    {
        return Admin::grid(Staff::class, function (Grid $grid) {

            $grid->id('ID')->sortable();
            $grid->column('name');

            $grid->picture('picture')->image();
            $grid->column('email');

            $grid->active()->value(function ($active) {
                return $active ?
                    "<i class='fa fa-check' style='color:green'></i>" :
                    "<i class='fa fa-close' style='color:red'></i>";
            });

            $grid->column('age');

            $grid->created_at();
            $grid->updated_at();
        });
    }


    protected function form()
    {
        return Admin::form(Staff::class, function (Form $form) {

            $form->display('id', 'ID');

            $form->text('name');
            $form->textarea('description');
            $form->image('picture');
            $form->text('email');
            $form->switch('active');
            $form->slider('age')->options(['max' => 100, 'min' => 1, 'step' => 1, 'postfix' => 'years old']);

            $form->display('created_at', 'Created At');
            $form->display('updated_at', 'Updated At');
        });
    }

```

## 画像

このままだと画像部分がうまく表示されないので、設定を変更していきます。
admin/config/admin.php

```php
    'upload'  => [

        // adminをlocalに変更します。
        // adminのままであれば、admin/config/filesystems.php にadminを追加しても問題ないです。
        'disk' => 'local',

        'directory'  => [
            'image'  => 'image',
            'file'   => 'file',
        ],

        // ローカルに保存するので削除する。
        //'host' => 'http://localhost:8000/upload/',
    ],
```

ルートに追加します。

```php
Route::get('image/{filename}', function ($filename)
{
    $path = storage_path() . '/app/image/' . $filename;

    if(!File::exists($path)) abort(404);

    $file = File::get($path);
    $type = File::mimeType($path);

    $response = Response::make($file, 200);
    $response->header("Content-Type", $type);

    return $response;
});
```

これで一通り動くようになります。

# 作成されたページ

以下が生成される画面です。

gird部分
http://127.0.0.1/admin/staffs

<img width="1673" alt="スクリーンショット 2016-12-01 10.19.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/16194/4b0d8cdd-6602-f72c-53c4-c871659e6f7e.png">

form部分
http://127.0.0.1/admin/staffs/create

<img width="1674" alt="スクリーンショット 2016-12-01 10.20.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/16194/ea888097-50e6-66e6-d2f0-9830dd3e51b6.png">

# メニューバーにリンクを追加する。

laravel-adminは権限周りの設定ができるので、メニューバーへの追加は管理画面から追加します。

http://127.0.0.1/admin/auth/menu

<img width="1673" alt="スクリーンショット 2016-12-01 10.35.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/16194/e793bb43-dc4e-357d-8c57-e98854611faa.png">

# まとめ

laravel-adminは他にも、一覧で編集機能を追加したり、レイアウトを変更できたり、権限を設定できたり、他のライブラリより多くの機能があります。
多機能である分、設定する箇所がおおく、railsのactiveadminに比べるとCRUDの追加に時間がかかるイメージでした。
また、個人的にはメニューへの追加は管理画面からではなく、ファイルで設定出来たほうが良かったです。

laravelの管理画面を生成するライブラリは絶対的なものが無いので、時間があったら別のライブラリも触れていきたいと思います。
（activeadminみたいなのでてこないかなぁー）

2日目は[ushibondi](http://qiita.com/ushibondi)が担当します。