laravel8でRestfulなCRUDメモアプリAPIを改良。複数のファイルアップロードに対応してみる。
memosレコードに対して、複数の写真を紐付けないと駄目だから、1:nのリレーションを張る
1 2 3 4 5 |
# アップロードしたファイルの管理モデル一群 php artisan make:model Upload -a # テーブルのリレーションは、migrateの作成順の関係で、親テーブルを先に作る必要がある。 # 順番を間違えたら手動でファイルを削除して composer dump-autoload でクラス名をリセットする必要がある。 |
1 2 3 4 5 6 7 8 |
// 子テーブル Schema::create('uploads', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('memo_id')->nullable()->comment('親メモID'); $table->string('file_path')->comment('アップロードされたファイルのパス'); $table->string('file_name')->comment('ハッシュ化される前のファイル名'); $table->timestamps(); }); |
モデルにリレーションを記述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// App\Models/Memo.php class Memo extends Model { use HasFactory; // id以外のカラムは自由にinsert/updateしてOK! protected $guarded = ['id']; // このメモに紐付いたアップロードファイル public function upload_files() { return $this->hasMany('App\Models\Upload'); } } // App\Models/Upload.php class Upload extends Model { use HasFactory; // id以外のカラムは自由にinsert/updateしてOK! protected $guarded = ['id']; // アップロードファイルの親メモ public function parent_memo() { return $this->belongsTo('App\Models\Memo'); } } |
createの処理。updateも同じ感じで修正する
app/Http/Controllers/MemoController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public function store(Request $request) { //バリデーションルールを設定 $validator = \Validator::make($request->all(), [ 'title' => 'required|max:255', 'content' => 'required|max:255', ]); //バリデーションルールにでエラーの場合 if ($validator->fails()) { return response()->json([ 'success' => false, 'message' => 'Insert Failed', 'details' => $validator->errors() ]); } // 問題なければDB登録 $memo = Memo::create($request->all()); // アップロードしたファイル(複数) if ($request->has('file')) { $files = $request->file('file'); foreach ($files as $file) { // ファイル名はハッシュ化されて保存される。 $file_name = $file->getClientOriginalName(); //オリジナルのファイル名のままにしたければ第2引数に指定 //$path = $file->storeAS('public',$file_name); $path = $file->store('public'); // 返り値はpublic/ファイル名だが、URL的にはstorage/ファイル名なので変換して格納する $file_path = preg_replace('/^public\/(.*?)/', 'storage/$1', $path ); // DBにも格納 Upload::create([ 'memo_id' => $memo->id, 'file_path' => $file_path, 'file_name' => $file_name, ]); } } // jsonで結果を返す return response()->json([ 'success' => true, 'message' => 'Insert Success!', // 生成したレコードの値を返す 'details' => Memo::with(['upload_files'])->where('id', $memo->id)->get() ]); } |
postmanかcreate.blade.phpでアップロードしてみる。
1 2 3 4 5 6 |
<form method="post" action="{{url('api/memo/')}}" enctype="multipart/form-data"> <input type="text" name="title" placeholder="title"> <input type="text" name="content" placeholder="content"> <input type="file" name="file[]" class="form-control" multiple> <input type="submit"> </form> |
メモに紐付いたアップロードされた写真を表示。
Memo::with([‘HasManyのメソッド名’])->get() みたいにしないと子テーブルの値を持ってきてくれない。
1 2 3 4 5 6 7 8 9 10 11 |
// 全レコード表示 public function index() { // 問題なければjsonで結果を返す return response()->json([ 'success' => true, 'message' => 'List Success!', //'data' => Memo::all() 'data' => Memo::with(['upload_files'])->get() ]); } |
storage\app/publicに格納されたファイルは、public\storage以下からアクセス出来るようにする
1 |
php artisan storage:link |