Blogブログ

laravel

2022.03.08

Laravel-adminをたんざらし食べながら解説

東中野にたんざらしという牛タンの名店あり

まぁ弊社がやってるんですけどね。

弊社は時々福利厚生で黒毛和牛を仕入れるのですが
仕入れに強い関係でなかなか良いタンが手に入ります。

googleマイビジネスにも登録はしていない上に看板も積極的に出していないため
遠方から来るテイクアウトで来る人はどうやって見つけてるのかなと思っています。(現在、デリバリーとテイクアウトしかやっていません)

厚切り牛タンは自信をもって提供しています。
何回も来てくれる人で偶然IT空間の社員と会話してしまった人は、
ごく稀に奥のカウンタースペースでお茶を飲めたりします。

というわけで、牛タン食べながらlaravel-adminの解説をします。

laravelのプロジェクトを作るところからフレッシュな心でやりましょう。

git@github.com:jazttijaztti/prepare_laravel_docker.git

ここからクローンしてください。

laravelの環境構築までは、5分程度でできるはずです。

まずは公式を見てみましょう。

一発目で、今後laravel-adminが更新されなくなっていくのではないかという不安がでてくる1行がありますが気にせずに続けていきましょう。

(ちなみに私は今初めて公式サイトを見ました。)

まず、composerが入ってる環境で、
公式の通りに実行してみましょう

composer require encore/laravel-admin:1.*

どれどれ…(Dockerfileしくったかな..)

composerのバージョン古かったみたいだし
メモリー足りなくて実行できないとか言われていますね。

二食丼をみて落ち着きましょう。
もう本日はブログを書くのやめようかなという気持ちになってきました。

ただ、警告にここみてアップグレードしてねと書かれているので
一度だけやってみようと思います。
これでできなかったから早食いして帰ります。

ではcomposerをアップデートしてからメモリ不足を無視するオプションつけてインストールします。

できちゃいました。。。

続けるしかないようだな..

では公式に従ってasset等を公開していきましょう。

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

configの下にadmin.phpができていれば成功ですね。

では次のコマンド

php artisan admin:install

そういえばまだDBを作っていなかったのでこれを実行するとエラーになりそうなので、実行する前にDB作ってみます。
docker-compose.ymlと.envと合わせるようにしてください。

では実行してみます。

why……….できない…..あ、わかりました。
mysqlのバージョンを8にしていたのでパスワードの認証方式が変わったんでした。
めんどうなので、今回はdocker-compose.ymlのmysqlのところに
command: –default-authentication-plugin=mysql_native_password

を設定しましょう。これで昔の認証方法でも通ります。
これでもう一度buildからやってみます(できなかったら帰ります。)

く…できてしまった。。

ちなみに、docker-compose exec mysql bash
でmysqlに入った後に、
mysql -uroot -prootでログインし、
use mysqlで
alter user ‘root’@’localhost’ identified with mysql_native_password by ‘root’;
alter user ‘root’@’%’ identified with mysql_native_password by ‘root’;
をやっても認証方法は変わりますが、今はどうでもいいので割愛

では続きをやっていきましょう。

php artisan admin:install

これを実行します。

できちゃいましたね。

デフォルトではadmin / adminでログインもできます。
ログインしてみましょう。

できました。

app/Admin
├── Controllers
│   ├── ExampleController.php
│   └── HomeController.php
├── bootstrap.php
└── routes.php

このようなファイル構成になっていることがわかります。

では、実際の書き方を解説していきます。

話変わって、ラーメン凪のグループが中野駅の近くに住所非公開の会員制焼肉屋を開きましたよね。
1年待ちらしいです。
laravel-adminという中国が作ってるコミュニティはいずれ非活性になるだろうという話もあるので、laravel-adminよりも凪の焼肉の方が気になります。

ここです。
行ってきました。

なかなかおいしいです。
偶然にもキャンセルがでたということで、
来週も日中に予約できてしまっていたため、
ノートPC持参で弊社は3時間貸しオフィスとして利用します(ついでに焼肉も食べます)

HomeControllerを見てみましょう。

homeコントローラーのindexアクションを見てみましょうか。

public function index()
{
    return Admin::content(function (Content $content) {

        // optional
        $content->header('page header');

        // optional
        $content->description('page description');

        // add breadcrumb since v1.5.7
        $content->breadcrumb(
            ['text' => 'Dashboard', 'url' => '/admin'],
            ['text' => 'User management', 'url' => '/admin/users'],
            ['text' => 'Edit user']
        );

        // Fill the page body part, you can put any renderable objects here
        $content->body('hello world');

        // Add another contents into body
        $content->body('foo bar');

        // method `row` is alias for `body`
        $content->row('hello world');

        // Direct rendering view, Since v1.6.12
        $content->view('dashboard', ['data' => 'foo']);
    });
}

laravel-adminの決まり事を理解

理解するために、
順番にコードを実行していこうと思います。

まず、このindexアクションの中身を、削ってみまして、

    public function index(Content $content)
    {
        return $content
            ->title('Dashboard');
    }

だけにしてみてアクセスしてみ見ると。

こんな感じです。
ではdescriptionを入れてみます。

    public function index(Content $content)
    {
        return $content
            ->title('Dashboard')
            ->description('Description...');
   }

こんな感じで、h1の中にさきほどのタイトル、
その中にsmallタグの中に説明がきてることがわかります。

こんな感じでlaravel-adminは$contentの中にいろいろな関数が用意されているので、それを使っていくことになります。
例えばrowという関数があり、レイアウトを決めながら情報を表示したりすることができます。
row(“行決め関数”と覚えるといいかもしれないです)という関数の中で、
どのようにレイアウトを決めていくのかというところが、
大きなポイントとなります。

->row(function (Row $row) { 
この中に書いていくことになります。
}

レイアウトのサンプルを通して理解してみてください

    public function index(Content $content)
    {   
        return $content
            ->title('Dashboard')
            ->description('Description...')
            ->row(function (Row $row) {
             $row->column(12, function (Column $column) {
                $column->row('12あるブロックをそのまま12使うレイアウトつまり1列');
             });

             $row->column(6, function (Column $column) {
                $column->row('12あるブロックのうち6を使う');
             });
             $row->column(6, function (Column $column) {
                $column->row('のこり6あるブロックのうち6使うレイアウトつまり2列');
             });


             $row->column(6, function (Column $column) {
                $column->row('12あるブロックのうち6を使う');
             });
             $row->column(3, function (Column $column) {
                $column->row('のこり6あるブロックのうち3使う');
             });
             $row->column(3, function (Column $column) {
                $column->row('のこり6あるブロックのうち3使うこれで合計12で3列');
             });

             $row->column(4, '4分割して残り8を残す(こういう書き方もできます)');

             $row->column(8, function (Column $column) {
                     $column->row('あまった8の中で1行');
                     $column->row('あまった8の中でまた1行');
                     $column->row('あまった8の中でまた1行');
              });
            });
    }

わりとわかるのではないかと思います。

function(Row $row) {
}
のように、
もともとRowはuseされているLaravel-adminのオブジェクトなので、
それを$rowで使えるようになっている状態で
関数のなかで$rowのもっている関数を使ってレイアウトを表現していると考えると
気持ちが楽になるのではないかと思います。

今俯瞰的に見ると、
$content
->title()
->description()
->row()
というだけと考えると、楽に考えることができます。
他にもheader()やbody()なんかもあります。

こうぞうだけみるとだいぶ理解が深まりますね。
$content
->title(‘xxx’)
->description(‘xxx’)
->header(‘xxx’)
->breadcrumb(
[‘text’ => ‘xx’, ‘url’ => ‘/xx’],
[‘text’ => ‘xx’] )
->row(function(Row $row){
$row->column(12,’xxxx’);
$row->column(12,function(Column $column) use ($request){
$column->row(‘xxxx’);
})
})
->body(‘xxxx’)
->body(view(‘admin::home.home_btn’,[‘key’=>$val]))

直感的にもわかりやすいですね。
ちなみに関数の中で関数外の変数を使うときはuseを使ってください
またviewファイルを読み込むときは、
上の例だとresouceフォルダのadmin/home/home_btn.blade.phpを読み込んでくれます。そのviewに変数を読み込ませたいときは第二引数に配列で渡してください。

次にデータを表示してみます。

データを表示するときは、

    public function index(Request $request)
    {
        $search =  $request->post();
        return XXTABLEXX::content(function (Content $content) use ($request, $search) {
            $content->header(trans('admin.language_path.sample1'))
                ->body(view('admin::adminviewpath.sample',[
                    'search'    => $search
                ]))
                ->body($this->grid($request, $search))
                ->render();
        });
    }

こんな感じの型をもっておくといいかもしれません。
最後テーブル名のクラスから表示するときは、render()で終わることに注意。
一覧表示するテーブルを
XXTABLEXXとしたので、もしこれがUserテーブルなら
return User::content(function (Content $content) use ($request, $search) { }
にしてください。

transというのは言語の辞書を扱うときによく使います。
/resources/lang/ja/admin.phpの中に、配列として
return [adminviewpath => [sample1 => ‘ここのが表示される’]]
というように配列で管理しておき、文言を表示したりします。

bodyの中のgridが一番重要で、ここで持ってくる一覧表示のデータの
形式のsqlを含む設定を行うようなイメージです。

gridは多くの場合、そこだけ切り出して、
書いていきます。

なので、標準的なコードとしてはこんな感じとなります。

    public function grid($request, $search)
    {
        return Admin::grid(targetTable::class, function(Grid $grid) use ($request, $search) {

            //検索部分
            if(isset($search['keyword'])){
                $grid->model()->where(function($query) use ($search) {
                    return $query->where('title', 'LIKE', '%'.$search['keyword'].'%')
                                ->orWhere('sub_title', 'LIKE', '%'.$search['keyword'].'%')
                                ->orWhere('up_description', 'LIKE', '%'.$search['keyword'].'%')
                                ->orWhere('bottom_description', 'LIKE', '%'.$search['keyword'].'%');
                });
            }

            $grid->model()->orderBy('id', 'desc');
            $grid->paginate(20);
            $grid->expandFilter();
            $grid->disableExport();
            $grid->disableFilter();
            $grid->disableCreation();
            $grid->perPages([10, 20]);
            $grid->disableRowSelector();
            $grid->disableColumnSelector();
            $grid->tools(function ($tools) {
                $tools->disableRefreshButton();
            });
            $grid->filter(function($filter) {
                $filter->disableIdFilter();
            });
            $grid->actions(function ($actions){
                $actions->disableView();
                if($actions->row->id == 1){
                    // $actions->disableDelete();
                }
            });

        });
    }

これだけでTargetテーブルがある前提だと
一覧で取得してしまいます。
設定を直感的にわかりやすいですね。
Admin::gridはlaravel-adminの中のgridレイアウトを使いますよという意味で、
grid(TargetTable::class, function(Grid $grid)
これはtargetテーブルに対してGridの設定を適応して取得したり検索したりしますよということです。この設定だけで画面が表示されます。

初めのうちはなぜAdminがいきなり、なぜContentがいきなり?と感じる人もいますが、ファイルの一番上でuseしてるので呼び出せます。