Laravel开发:如何获取当前产品ID实现附件关联存储
问题背景
我目前在产品列表页为每个产品配置了add attachment按钮,点击按钮后会跳转至附件添加表单页。需要从产品表中获取当前产品ID,将附件数据存储到附件表中。
现有代码参考
路由
Route::post('/store/{product}', 'AttachmentController@store')->name('attachment.store');
Product模型
public function attachment() { return $this->hasMany(Attachment::class, 'product_id', 'id'); }
Attachment模型
public function product() { return $this->belongsTo(Product::class, 'product_id'); }
控制器原有代码
public function create() { return view('document.create', ['prod' => Product::select('id', 'name')->get()]); } public function store(Request $request, Product $product) { $data['product_id'] = $product->id; $data = $request->validate([ 'file' => 'required', 'file.*' => 'mimes:csv,xlsx,pdf,docx', ]); $attachmentData = []; if($request->hasFile('file')) { foreach($request->file('file') as $file) { $path = public_path('storage/attachments/'.$request->product_id); $fileName = time().'-'.$file->getClientOriginalName(); $file->move($path, $fileName); $attachmentData[] = $fileName; } $data['file'] = json_encode($attachmentData); } $attachment = Attachment::create($data); return redirect()->route('product.index')->with('success','Attachment added successfully'); }
原有Blade视图
<form method="POST" action="{{route('attachment.store')}}" enctype="multipart/form-data"> @csrf <h3><b>Add Attachment</b></h3> <input type="submit" class="btn btn-primary mr-2" value="Save"> <div class="row"> <h4 class="card-title">General</h4> <input type="text" name="product_id" value="{{ $product->id ?? '' }}" hidden> <div class="form-group"> <label for="name">Name</label> <input type="text" id="name" class="form-control" name="name" required> </div> <div class="form-group"> <label>Attachment </label> <div class="input-group-append"> <label for="attachment" class="btn btn-info">Upload</label> <input id="attachment" type="file" name="file[]" multiple required> </div> </div> </div> </form>
解决方案
1. 新增附件创建页路由
补充带产品ID参数的create路由,用来接收从列表页传过来的当前产品ID
Route::get('/create/{product}', 'AttachmentController@create')->name('attachment.create');
2. 修改产品列表页的跳转按钮
遍历产品列表时,给每个add attachment按钮绑定当前产品ID作为跳转参数
<a href="{{ route('attachment.create', $product->id) }}" class="btn btn-success">add attachment</a>
3. 修改控制器create方法
接收路由传过来的产品实例,直接传到视图即可,不需要查询所有产品
public function create(Product $product) { return view('document.create', compact('product')); }
4. 修改Blade表单提交地址
给路由补充产品ID参数,表单提交时会自动把产品ID带到请求中
<form method="POST" action="{{route('attachment.store', $product->id)}}" enctype="multipart/form-data"> @csrf <h3><b>Add Attachment</b></h3> <input type="submit" class="btn btn-primary mr-2" value="Save"> <div class="row"> <h4 class="card-title">General</h4> <!-- 隐藏域可保留也可删除,路由参数已经携带了产品ID --> <input type="text" name="product_id" value="{{ $product->id }}" hidden> <div class="form-group"> <label for="name">Name</label> <input type="text" id="name" class="form-control" name="name" required> </div> <div class="form-group"> <label>Attachment </label> <div class="input-group-append"> <label for="attachment" class="btn btn-info">Upload</label> <input id="attachment" type="file" name="file[]" multiple required> </div> </div> </div> </form>
5. 修复store方法逻辑bug
原有代码先给$data赋值产品ID后又被验证结果覆盖,会导致产品ID丢失,调整逻辑顺序即可
public function store(Request $request, Product $product) { // 先做参数验证,补充name字段的验证规则 $validated = $request->validate([ 'name' => 'required|string|max:255', 'file' => 'required', 'file.*' => 'mimes:csv,xlsx,pdf,docx', ]); $attachmentData = []; if($request->hasFile('file')) { // 自动创建存储目录,避免目录不存在报错 $path = public_path('storage/attachments/'.$product->id); if (!file_exists($path)) { mkdir($path, 0777, true); } foreach($request->file('file') as $file) { $fileName = time().'-'.$file->getClientOriginalName(); $file->move($path, $fileName); $attachmentData[] = $fileName; } $validated['file'] = json_encode($attachmentData); } // 把产品ID加入待存储数据 $validated['product_id'] = $product->id; $attachment = Attachment::create($validated); return redirect()->route('product.index')->with('success','Attachment added successfully'); }
内容的提问来源于stack exchange,提问作者xyz
相关产品推荐
相关产品推荐

