Laravel:Eloquentで1対多リレーションの@foreachで子テーブルの指定カラムで並び替えしたい
Laravel:Eloquentで1対多リレーションの@foreachで子テーブルの指定カラムで並び替えしたい
やり方について少し悩んだので備忘録です。
現在、作成したシステムのマニュアルを作成しているのですが、HTMLを書くのはとても面倒なので「DBに書いて呼び出してHTML合成する」そんな形にしています。
その中で、JOIN先の値を並び替えて取りたいときがありました。
そんな時の対応方法です。
普通にやると子テーブル側はIDの順に取れる
#table:manuals
Schema::create('manuals', function (Blueprint $table) {
$table->increments('id');
$table->string('title')->comment('タイトル');
$table->unsignedInteger('selecter_id')->nullable()->comment('分類');
$table->integer('sortnumber')->comment('並び順');
$table->integer('manualsentence_id')->comment('マニュアル構成パーツID');
$table->softDeletes();
$table->timestamps();
});
#table:manualsources
Schema::create('manualsources', function (Blueprint $table) {
$table->increments('id');
$table->string('subtitle')->comment('サブタイトル');
$table->unsignedInteger('manual_id')->nullable()->comment('親ID');
$table->integer('sortnumber')->comment('並び順');
$table->softDeletes();
$table->timestamps();
});
これをViewで取り出すとき、こんな感じで書くと取り出される $souce->subtitle は manualsources->idの順になっています。
#manualController.editでManualの抽出 $item = Manual::find($id);
#viewで$itemからmanualsourceを取り出す
@foreach($item->manualsouce as $souce)
{{$souce->subtitle}}
@endoforeach
子テーブルのsortnumberで並び替えて取得するときはひと手間必要
@foreach の際にorderbyを付け加えてget() したものを foreach するように指示が出来ます。
@if(!empty($item->manualsouce))
@foreach($item->manualsouce()->orderBy('sortnumber','asc')->get() as $souce)
{{souce->subtitle}}
@endforeach
@endif
これで、想定した動き(子テーブルのsortnumber 順)に取得が可能となります。
ついでにもう一つ
@if(!empty ()) + @foreach() を @forelse に置き換える
@forelse($item->manualsouce()->orderBy('sortnumber','asc')->get() as $souce)
<h4>{{$souce->subtitle}}</h4>
@empty
~~作成中~~
@endforelse
注意点は@emptyの指定が必須である事。値が無くても@emptyを配置していないとエラーが出ます。
まとめ
@forelse、知らなかった。
ここまでif+foreach で書いてきたので「結構悠長な書き方してたんだなぁ~」と見直してみたい気分にもなりますが、まずは公開まで持ってかないとです。
見直し時のチェックポイントとしてメモしておきました。
プログラミングの面白さでもありますが、思った事をやる方法が必ず見つかるってのがうれしいですよね。
さぁ頑張ろ。


