如何在 Laravel REST API 中使用 PUT 方法更新图像?

Posted

技术标签:

【中文标题】如何在 Laravel REST API 中使用 PUT 方法更新图像?【英文标题】:How to update image with PUT method in Laravel REST API? 【发布时间】:2021-03-01 09:57:42 【问题描述】:

我正在尝试使用 Laravel 构建一个 REST API,用户需要在其中更新他们的图像。但是,如果我在邮递员中使用 PUT 方法,它不会更新图像或将图像存储在指定文件夹中。如果我改用 POST,它会更新图像并保存在文件夹中。但它不会将文件保存在数据库中,因为我自定义了要存储在数据库中的名称。可能是什么原因。帮助真的很必要。 TIA。

更新代码

public function update(Request $request, $id)

    $found = Partner::find($id);
    if (!$found) 
        return Response::json(['message' => 'Id not found'], 404);
    
    $validatedData = Validator::make($request->all(), [
        'company_logo' => 'sometimes|mimes:jpg,png,jpeg|max:3048',
        'company_name' => 'sometimes|max:130',
        'company_email' => 'sometimes|email',
        'password'  =>  'sometimes|min:6',
        'phone'  =>  'sometimes|min:6|max:11',
        'address'  =>  'sometimes',
        'city'  =>  'sometimes|string',
        'country' =>  'sometimes|string' ,
        'business_category'  =>  'sometimes|string',
        'website_link' =>  'nullable|string',
        'facebook_page' =>  'nullable|string'
    ]);
    if ($validatedData->fails()) 
        return Response::json(['success' => false, 'message' => $validatedData->errors()], 400);
    

    if ($request->hasFile('company_logo')) 
        $logo = $request->company_logo;
        $fileName = date('Y') . $logo->getClientOriginalName();
        $request->company_logo->storeAs('company_logo', $fileName, 'public');
        $found['company_logo'] = $fileName;
    
    
    $found->update($request->all());

    return Response::json(['success' => true, 'message' => 'Partner updated successfully!', 
                           'updated_data' => $found], 200);

我的路线

Route::group(['prefix' => 'partner'], function () 
Route::post('store', [APIMemberController::class, 'store']);
Route::post('update/id', [APIPartnerController::class, 'update']); // This works
// Route::put('update/id', [APIPartnerController::class, 'update']); // This don't why?
);

存储伙伴

public function store(Request $request)

    $validatedData = Validator::make($request->all(), [
        'company_logo' => 'required|mimes:jpg,png,jpeg|max:3048',
        'company_name' => 'required|max:130',
        'company_email' => 'required|email|unique:partners',
        'password'  =>  'required|min:6',
        'phone'  =>  'required|min:6|max:11',
        'address'  =>  'required',
        'city'  =>  'required|string',
        'country' =>  'required|string' ,
        'business_category'  =>  'required|string',
        'website_link' =>  'nullable|string',
        'facebook_page' =>  'nullable|string'
    ]);

    if ($validatedData->fails()) 
        return Response::json(['success' => false, 'message' => $validatedData->errors()], 400);
    

    // $saved = Partner::create($request->all());

    if ($request->hasFile('company_logo')) 
        $logo = $request->file('company_logo');
        $fileName = date('Y') . $logo->getClientOriginalName();
        $request->company_logo->storeAs('company_logo', $fileName, 'public');
    

    $partner = new Partner();
    
    $partner->company_logo = $request->company_logo->getClientOriginalName();
    $partner->company_name = $request->company_name;
    $partner->company_email = $request->company_email;
    $partner->password = $request->password;
    $partner->phone = $request->phone;
    $partner->address = $request->address;
    $partner->city = $request->city;
    $partner->country = $request->country;
    $partner->business_category = $request->business_category;
    $partner->website_link = $request->website_link;
    $partner->facebook_page = $request->facebook_page;
    $partner->save();
    return Response::json(['success' => 'Partner created successfully!', 'created_partner' => $partner], 201);



【问题讨论】:

邮政编码在哪里? @miken32 更新方式为发帖码! 不,接收帖子。你发帖怎么样? 你在做 $found->update($request->all()); $request['company_logo'] 是一个文件,它替换了 if($request->hasFile('company_logo') 中 $found['company_logo'] 的效果,因此文件名在 db 中没有数据 @JakariaRidoy 我不记得确切的原因。但是,解决方法是您应该在表单数据中使用带有 _method="PUT" 的 POST 请求来上传文件。 【参考方案1】:

我可以看到两个更改,它们应该可以通过更新功能为您提供所需的结果

public function update(Request $request, $id)

    $found = Partner::find($id);
    if (!$found) 
        return Response::json(['message' => 'Id not found'], 404);
    
    $validatedData = Validator::make($request->all(), [
        'company_logo' => 'sometimes|mimes:jpg,png,jpeg|max:3048',
        'company_name' => 'sometimes|max:130',
        'company_email' => 'sometimes|email',
        'password'  =>  'sometimes|min:6',
        'phone'  =>  'sometimes|min:6|max:11',
        'address'  =>  'sometimes',
        'city'  =>  'sometimes|string',
        'country' =>  'sometimes|string' ,
        'business_category'  =>  'sometimes|string',
        'website_link' =>  'nullable|string',
        'facebook_page' =>  'nullable|string'
    ]);
    if ($validatedData->fails()) 
        return Response::json(['success' => false, 'message' => $validatedData->errors()], 400);
    

    if ($request->hasFile('company_logo')) 
        $logo = $request->company_logo;
        $fileName = date('Y') . $logo->getClientOriginalName();

    //Get the path to the folder where the image is stored 
    //and then save the path in database
        $path = $request->company_logo->storeAs('company_logo', $fileName, 'public');
        $found['company_logo'] = $path;
    
    
    //update with all fields from $request except 'company_logo'

    $found->update($request->except('company_logo'));

    return Response::json(['success' => true, 'message' => 'Partner updated successfully!', 
                           'updated_data' => $found], 200);

只是在这里的答案中包含它:

如果有人想对包含文件上传的表单使用 PUT 或 PATCH 请求

<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form>

通过任何 javascript 框架,例如 vue

let data = new FormData;
data.append("_method", "PUT")

axios.post("some/url", data)

我已经做到了。但我现在的问题是为什么 PUT 在更新方法中不适用于 Laravel?

这不是因为 Laravel,而是 php 的事情/限制。在 PUT 请求期间,PHP 不会像在 POST 请求期间那样填充超级全局 $_FILES

要通过 PHP 中的 Put/ 方法访问文件上传,请参阅 features.file-upload.put-method

因此,为文件上传发出 POST 请求并使用方法欺骗让 Laravel 知道该请求是针对与 PUT 方法对应的路由可能更容易

【讨论】:

我已经做到了。但我现在的问题是为什么 PUT 在更新方法中不适用于 Laravel? 虽然非常感谢您的回答 如果给定的更改有助于您获得所需的输出,您可以将其标记为已接受的答案或为后续访问者的利益投票。 带有 put 方法的帖子必须包含数据的 id 否则它会引发方法不允许 axios.post("some/url/id", data) @Nurkartiko 如果 PUT 路由定义为 Route::put('some/url/id', [SomeController::class, 'update']);& POST 请求是通过 axios 发出的,其数据包含 _method=PUT,如 axios.post('some/url', data)。当 Laravel 尝试推断传入请求时,它将评估 url 并尝试与声明的路由匹配,将匹配存储的 POST 路由,然后读取_method=PUT 键并尝试使用给定的 url 找到一个 put 路由没有找到。所以它会给出错误,即没有id的给定url“some/url”不允许PUT方法

以上是关于如何在 Laravel REST API 中使用 PUT 方法更新图像?的主要内容,如果未能解决你的问题,请参考以下文章