Laravelの管理画面ライブラリ「laravel-encore」の使い方まとめ

Laravelには「laravel-admin:」という管理画面ライブラリがあるので、 今回はそのライブラリの導入と使い方を解説していく。

インストール方法

laravel-encoreからインストールする方法もあるが、先にLaravel本体をインストールした後にlaravel-encore を入れた方が良い。

composer create-project laravel/laravel:^8.0 example-app
composer require encore/laravel-admin

初期設定は以下の様に行う。以下のコマンドの前に.envファイルのデータベースの設定を済ませておくこと。

php artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"
php artisan admin:install

上記のコマンドにより、app/Adminディレクトリが新たに作成されたはず。

CRUDアプリを作る方法

CRUDアプリを作るには、app/Admin/Controllersディレクトリに以下のようなControllerを作成すると良い。

<?php

namespace App\Admin\Controllers;

use App\Models\ExampleModel;
use Encore\Admin\Controllers\AdminController;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Show;

class ExampleController extends AdminController
{
    /**
     * Title for current resource.
     *
     * @var string
     */
    protected $title = 'ここに画面のタイトルを入力する';

    /**
     * これがindexメソッドで使われる
     *
     * @return Grid
     */
    protected function grid()
    {
        $grid = new Grid(new ExampleModel());

        // もし、indexページにある各種ボタンが不要な場合は以下のメソッドで削除できる。
        $grid->disableExport();
        $grid->disableCreateButton();
        $grid->disableActions();

        // デフォルトでは、すべてのexamplesテーブルのデータを取得する。
        // もし、queryを操作したい場合は、$grid->model() から行える。
        $grid->model()->join("posts as p", 'p.id', '=', "examples.id");

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

        $grid->column('is_selected', "選択中")->display(function ($is_selected) {
            if ($is_selected == 1) {
                return "<span class='label label-success'>選択中</span>";
            } else {
                return "<span class='label label-default'>未選択</span>";
            }
        })->sortable();

        $grid->column('user_image', "プロフィール画像")->display(function ($user_image) {
            return "<img src='/storage/{$user_image}' width='50'>";
        });

        $grid->column('username', "ユーザー名")->sortable();

        $grid->column('created_at', __('Created at'))->display(function ($created_at) {
            return date('Y-m-d H:i:s', strtotime($created_at));
        });

        $grid->column('updated_at', __('Updated at'))->display(function ($updated_at) {
            return date('Y-m-d H:i:s', strtotime($updated_at));
        });

        return $grid;
    }

    /**
     * showメソッドを作成するのに使う
     *
     * @param mixed   $id
     * @return Show
     */
    protected function detail($id)
    {
        $show = new Show(ExampleModel::findOrFail($id));

        $show->field('id', __('ID'));

        $show->field('username', "ユーザー名");

        $show->field('created_at', __('Created at'));
        $show->field('updated_at', __('Updated at'));

        return $show;
    }

    /**
     * new, editメソッドのフォーム画面を作成する
     *
     * @return Form
     */
    protected function form()
    {
        $form = new Form(new ExampleModel());

        $form->text('username', "ユーザー名")->rules('required')
            ->help('ユーザー名を入力してください');

        $form->image("user_image", "プロフィール画像")->crop(400, 400)->uniqueName();

        $form->radio("is_selected", "このユーザーを選択中にする")
            ->options(['1' => '選択する', '0' => '選択しない'])
            ->default('0')
            ->help('選択中にするか選んでください');

        // databaseに保存、更新をする直後の処理を書く
        $form->saving(function (Form $form) {
            if (ExampleModel::notSelected()) {
                $form->is_selected = 1;
                return;
            }

            if ($form->is_selected == 1) {
                ExampleModel::unsetAllIsSelected();
            }
        });

        // databaseに保存、更新後の処理を行う。
        $form->saved(function (Form $form) {
            if (ExampleModel::notSelected()) {
                // $form->model()->id とすることで保存、更新を行なった直後のレコードのIDを取得できる。
                ExampleModel::select($form->model()->id);
            }
        });

        // view checkの部分を削除できる
        $form->disableViewCheck();

        // Editingを削除する
        $form->disableEditingCheck();

        // Creating Checkを削除する
        $form->disableCreatingCheck();

        return $form;
    }
}

そして、app/Admin/routes.phpに以下を追加しておく。

<?php

Route::resource("/examples", ExampleController::class);

ポイントは、以下の2つ。

  • AdminControllerを継承すること。
  • grid,detail,formメソッドを作成すること。

gridはindexで、detailはshow,formはnew,editアクションを行う際に使われる。 フォームのcreateやupdate、delete処理はencore-adminがよしなにやってくれる。

indexページだけ表示させたい場合

indexページだけ表示させて、他のeditやshowメソッドはいらないという場合もある。

その時は、routeの処理を以下の様にして、gridメソッドだけを定義してやればよい。

<?php

Route::resource("/examples", ExampleController::class)->only(["index"]);

formだけがある画面を作りたい場合

webアプリを作っていると、CRUD機能を備えたものではなく、設定画面のように、単にformの画面があって、そこでデータの更新ができる機能が作りたい時がある。

その時は、Encore\Admin\Widgets\Formを使うと簡単に作れる。

使い方は簡単で、まずは以下のコマンドを実行する。

php artisan admin:form SettingForm

すると、app/Admin/Forms/SettingForm.phpが作成されるので、以下のように編集する。

<?php

namespace App\Admin\Forms;

use App\Models\Setting;
use Encore\Admin\Widgets\Form;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class SettingForm extends Form
{
    /**
     * The form title.
     *
     * @var string
     */
    public $title = '設定画面のタイトル';

    /**
     * このhandleメソッドでデータの更新やvalidationを行う。
     * 
     * このhandleメソッドのために新たにrouteを追加する必要はなく、
     * encore-adminがよしなにやってくれる。
     *
     * @param Request $request
     *
     */
    public function handle(Request $request)
    {
        $validator = Validator::make(
            $request->all(),
            [
                "delete_log_days" =>  "required|integer",
            ],
            [
                "required" => ":attribute の値は必須です。",
                "integer" => ":attribute は整数の必要があります。",
            ]
        );

        if ($validator->fails()) {
            admin_error($validator->errors()->first());
            return back();
        }

        try {
            DB::beginTransaction();

            $validated = $validator->validated();
            Setting::upsertSetting($validated);

            DB::commit();

            // success時のフラッシュメッセージが出力される
            admin_success('設定の更新が完了しました。');

            return back();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage() . "\n" . $e->getTraceAsString());

            // error時のフラッシュメッセージが出力される
            admin_error($e->getMessage());
            return back();
        }
    }

    /**
     * form画面の設定を行う
     */
    public function form()
    {
        $this->number('delete_log_days', "ログを削除する日数")->rules('required');
    }

    /**
     * form画面に渡すデータを定義する。
     *
     * @return array $data
     */
    public function data()
    {
        $setting = Setting::getCurrentSetting();

        return [
            'delete_log_days'  => $setting->delete_log_days,
        ];
    }
}

上記では3つのメソッドが定義されているが、それぞれの役割は以下の通り。

  • handle update処理時に行う処理を書く。ここではvalidationやデータ更新などを行う。
  • form form画面の設定を行う。
  • date form画面を作成するときに渡すデータを定義する。

そして、適当なコントローラーを作成して以下の様に使う。

<?php

namespace App\Admin\Controllers;

use App\Admin\Forms\SettingForm;
use App\Http\Controllers\Controller;
use Encore\Admin\Layout\Content;

class SettingController extends Controller
{
    public function setting(Content $content)
    {
        return $content
            ->title('設定画面')
            ->body(new SettingForm());
    }
}

最後にroutes.phpに以下を追加する。

<?php

Route::get("setting", "SettingController@setting");

これで設定画面などのフォームだけの画面が作成できる。

画像アップロード機能を作成する方法

画像アップロード機能を追加したい場合は、まずはntervention/imageのライブラリをインストールする。

composer require ntervention/image

そして、config/filesystems.phpdisks配列に以下を追加する。

<?php

'disks' => [

    // 他の設定が記述されている。。。

    'admin' => [
            'driver' => 'local',
            'root' => storage_path('app/public'), 
            'url' => env('APP_URL') . '/storage', 
            'visibility' => 'public',
        ],
 ,

デザインを変更したい場合

encore-adminではbootstrap3を採用しているため、これを基本的に使う。 (どのバージョンのbootstrapを使っているかは、 ライブラリのバージョンによって違う可能性があるので、必ずチェックすること。)

もし、独自のcssやjsファイルを追加したい場合は、app/Admin/bootstrap.phpに以下を追加すること。

<?php

Admin::css('/css/style.css');

上記では、public/css/style.cssを読み込んでくれる様になる。

サイドメニューの項目を追加したい場合

サイドメニューを簡単に追加する方法は、encore-admin側で提供されていない。

なので、encore-admin側のSeederを拝借して、それを元に新しいSeederを作成する方が良い。

laravel-admin/AdminTablesSeeder.php at master · z-song/laravel-admin

例えば、SeederのMenu追加の部分は以下の様になっているので、これを真似して自作のMenuを追加していけば良い。

<?php

[
    'parent_id' => 2,
    'order'     => 6,
    'title'     => 'Menu',
    'icon'      => 'fa-bars',
    'uri'       => 'auth/menu',
],
[
    'parent_id' => 2,
    'order'     => 7,
    'title'     => 'Operation log',
    'icon'      => 'fa-history',
    'uri'       => 'auth/logs',
],

参考文献

encore-adminは中国圏のユーザーにより作成されているため、中国語の公式サイトが存在している。

たまに、中国語のドキュメントには書かれているけど、英語のドキュメントには書かれていない時があるので、 翻訳ソフトを使ってチェックした方が良い。

(GitHubのIssueも中国語で書かれているが辛い...)