laravel-admin リレーション 1対多 のサンプルアプリを作る

目次
1対多のリレーション間のlaravel-admin画面表示パターン
参考サイト
はじめに
以下のようにテーブルを作成します。
author テーブル

booksテーブル。author_id が外部キー

Model 作成
Modelをそれぞれ作成します。
Models>Author.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Author extends Model
{
use HasFactory;
protected $fillable = [
'first_name',
'last_name',
];
public function books() {
return $this->hasMany(Book::class,'author_id')->orderBy('id','asc');
}
}
Models>Book.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
use HasFactory;
protected $fillable = [
'title',
'author_id',
'page',
'subtitle',
'price'
];
public function author() {
return $this->belongsToMany(Author::class,'author_id');
}
}
作成したModelより、それぞれControllerを自動生成します。
php artisan admin:make AuthorController --model=App\Models\Author
php artisan admin:make BookController --model=App\Models\Book
Author 画面デフォルトは下記のような画面
app>Admin>Controllers>AuthorController.php
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
$form = new Form(new Author());
$form->text('first_name', __('名前'));
$form->text('last_name', __('氏名'));
return $form;
}


これをリレーション対応した画面
通常モード
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
$form = new Form(new Author());
// $form->text('first_name', __('名前'));
// $form->text('last_name', __('氏名'));
// 通常モード
$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;
}
タブ切り替えで、Author画面でこちらは 1対多の「1側」。

本タブをクリックし、通常モードの表示のBook画面でこちらは 1対多の「多側」。

タブモード
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
$form = new Form(new Author());
// $form->text('first_name', __('名前'));
// $form->text('last_name', __('氏名'));
// // 通常モード
// $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','価格');
// });
// });
// タブモード
$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;
}
氏名タブは同じ。本タブをクリックした状態、タブモードではタブでbooksレコードを切り替え表示する。

テーブルモード
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
$form = new Form(new Author());
// $form->text('first_name', __('名前'));
// $form->text('last_name', __('氏名'));
// // 通常モード
// $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','価格');
// });
// });
// // タブモード
// $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();
// });
// デーブルモード
$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;
}
こちらも氏名タブは同じ。本タブをクリックした状態、テーブルモードの表示です。

laravel-adminの次の調査としては、
- リレーション1(例:カテゴリ→商品マスタの画面。子画面、プルダウンなど)の機能の実装
- リレーション2(例:見積入力→商品や得意先マスタの画面。子画面、プルダウン選択など)の機能の実装
- PDFやExcel出力する機能の実装
-
前の記事
laravel-admin 検索画面について 条件追加 カスタマイズ grid/filter 2023.08.24
-
次の記事
laravel-admin Controller grid、detail、form でリレーション → エクスポート機能どうなるか、その他Quick search機能 2023.08.28