LoginSignup
18
20

More than 3 years have passed since last update.

Laravel-adminで1対多を色々な形で表示してみる

Last updated at Posted at 2019-06-07

概要

Laravel-adminの1対多で結びついているデータを色々な形で表示してみました.

環境

Laravel 5.3 , Laravel-admin 1.6.9

モデル

Author.php
class Author extends Model
{
    public function books() {
        return $this->hasMany(Book::class,'author_id')->orderBy('id','asc');
    }
}
Book.php
class Book extends Model
{
    protected $fillable=['title','author_id','page','subtitle','price'];

    public function author() {
        return $this->belongTo(Author::class,'author_id');
    }
}

通常の使用

公式ドキュメントなどにあるように実装するとこのような画面が出来上がります.
子のテーブルのカラムが少ない場合はこれで十分使えると思います.

ノーマルモード.PNG

AuthorController.php
protected function form()
{
    $form = new Form(new Author);

    $form->tab('氏名',function($form) {
        $form->hidden('id');
        $form->text('first_name', '名');
        $form->text('last_name', '氏');
    })->tab('本',function($form) {
        $form->hasMany('books','BOOK',function(Form\NestedForm $nestedForm) {
            $nestedForm->hidden('id');
            $nestedForm->text('title','タイトル');
            $nestedForm->text('subtitle','サブタイトル');
            $nestedForm->number('page','ページ数');
            $nestedForm->currency('price','価格');
        });
    });

    return $form;
}

タブモード

ノーマルモードのフォーム1つ1つをタブに入れて表示しています.子のカラムが増えても1ページに1つのレコードが表示されるため,ノーマルモードに比べて下に伸びにくくなっています.
一方で,親が子を多く持つとタブの数が増加するため,このようなときには使いづらくなります.また,目的のレコードが探しづらいという短点もあります.

タブモード.PNG

AuthorController.php
protected function form()
{
    $form = new Form(new Author);

    $form->tab('氏名',function($form) {
        $form->hidden('id');
        $form->text('first_name', '名');
        $form->text('last_name', '氏');
    })->tab('本',function($form) {
        $form->hasMany('books','BOOK',function(Form\NestedForm $nestedForm) {
            $nestedForm->hidden('id');
            $nestedForm->text('title','タイトル');
            $nestedForm->text('subtitle','サブタイトル');
            $nestedForm->number('page','ページ数');
            $nestedForm->currency('price','価格');
        })->useTab();
    });

    return $form;
}

デーブルモード

laravel-admin 1.6.10にて追加された機能.上記の2つに比べてスッキリとしたデザインで使いやすいと思います.
しかし,子のカラムが増えると横幅が足りなくなり,入力フォームが非常に小さくなることがあります.

テーブルモード.PNG

AuthorController.php
protected function form()
{
    $form = new Form(new Author);

    $form->tab('氏名',function($form) {
        $form->hidden('id');
        $form->text('first_name', '名');
        $form->text('last_name', '氏');
    })->tab('本',function($form) {
        $form->hasMany('books','BOOK',function(Form\NestedForm $nestedForm) {
            $nestedForm->hidden('id');
            $nestedForm->text('title','タイトル');
            $nestedForm->text('subtitle','サブタイトル');
            $nestedForm->number('page','ページ数');
            $nestedForm->currency('price','価格');
        })->useTable();
    });

    return $form;
}

index画面の埋めこみ

index画面にあるgridをそのままフォームに埋め込んだものとなっています.
index画面を埋め込んでいるため動作はindex画面に準じたもので,他のフォームとは独立した編集画面として動作します.
例えばindex画面と同様に編集を行うと,送信ボタンを押さずともデータベースが更新され,新規ボタンを押すとBookControllerのcreateメソッドに飛びます.
あくまで表示だけにとどめて,新規・編集機能は上記の3つのどれかで実装するのが良いと思われます.

grid埋めこみ.PNG

AuthorController.php
protected function form($id = null)
{
    if($id) {
        //Bookのgird画面のHTMLレンダリングを先に行う
        $html = '';

        //Book用のgridを作成する
        $grid = new Grid(new Book);
        $grid->setName('BOOK')
            ->setTitle('本')
            ->setRelation(Author::find($id)->books())
            ->resource('/admin/books');

        $grid->title('タイトル')->editable();
        $grid->subtitle('サブタイトル')->editable();
        $grid->page('ページ数')->editable();
        $grid->price('価格')->editable();

        //ボタンを無効
        $grid->disableExport();
        $grid->disableFilter();
        $grid->disablePagination();
        $grid->disableRowSelector();
        $grid->tools(function ($tools) {
            $tools->disableRefreshButton();
        });

        //操作を無効化
        $grid->actions(function ($actions) {
            $actions->disableView();
            $actions->disableEdit();
            });

        $html = $grid->render();
    }

    $form = new Form(new Author);

    $form->tab('氏名',function($form) {
        $form->hidden('id');
        $form->text('first_name', '名');
        $form->text('last_name', '氏');
    })->tab('本',function($form) use ($html) {
        $form->html(function() use ($html) {
            return $html;
        })->setWidth(12, 0);
    });

    return $form;
}

まとめ

4つの表示方法を紹介しましたが,いずれも一長一短で状況に応じて使い分けるのが良いと思います.
また,index画面の埋めこみはかなりトリッキーな実装をしているので,ここまでするなら素直にbladeを書いたほうが良い気もします.

18
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
20