Laravel 画像管理画面のindex作成

imageテーブル作成
リレーション

<?php
public function shop()
    {
        return $this->hasOne(Shop::class);
    }

    public function image()
    {
        //imageを複数もてる1対多の関係なのでhasManyとする
        return $this->hasMany(Image::class);
    }
<?php
class Image extends Model
{
    use HasFactory;
    protected $fillable = [
        'owner_id',
        'filename'
    ];
public function owner()
    {
        return $this->belongsTo(Owner::class);
    }
}
モデル、リソースコントローラの作成

<?php
public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->id();
            //Owner->Shop->Image と 外部キー制約を設定しているため 追加設定が必要。
            $table->foreignId('owner_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
            $table->string('filename');
            //nullableで空でも登録できる
            $table->string('title')->nullable();
            $table->timestamps();
        });
    }
ルーティング(resource)

<?php
use App\Http\Controllers\Owner\ImageController;

//imageのルート(resource)
Route::resource('images', ImageController::class)
//adminで認証していたらで表示
->middleware('auth:owners')->except('show');
Controller

コンストラクタ→ログインしているownerだけが見れるように設定→コントローラミドルウェア

と同じ
where('owner_id', Auth::id()でログインしているIDで検索
画像数が多くなるので、orderBy desc 降順で表示させる。

<?php
public function __construct()
    {
        $this->middleware('auth:owners'); 

        $this->middleware(function ($request, $next) {
            $id = $request->route()->parameter('image');
            if(!is_null($id)){
            $imagesOwnerId = Image::findOrFail($id)->owner->id;
              $imageId = (int)$imagesOwnerId;
              if($imageId !== Auth::id()){
              abort(404);
              }
            }
            return $next($request);
        });
    }

    public function index()
    {
        $this->viewData['images'] = Image::where('owner_id', Auth::id())
        ->orderBy('updated_at','desc')
        ->paginate(20);
        return view('owner.images.index', $this->viewData);
    }
view

店舗情報から画像アップロードした場合は、storage/shops/へ保存。
画像管理からの場合はstorage/products/に保存したいので、コンポーネントをまとめる。
imageのindex.blade.php

{{-- productsフォルダの中に保存するのでtypeで属性をつける --}}
<x-thumbnail :filename= "$shop->filename" type= "products" />

shopのindexとedit.blade.php

{{-- shopsフォルダの中に保存するのでtypeで属性をつける --}}
<x-thumbnail :filename="$shop->filename" type="shops" />
@php
// 呼び出し元のコンポーネントのtype属性を判定し、画像アップロードさきのPATHをかえる
if($type === 'shops'){
  $path = 'storage/shops/';
}
if($type === 'products'){
  $path = 'storage/products/';
}
@endphp

<div>
  @if(empty($filename))
    <img src="{{ asset('images/no_images.jpg')}}">
  @else
  {{-- 画像アップロード先PATH --}}
    <img src="{{ asset($path . $filename)}}">
  @endif
</div>