如何在 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 方法更新图像?的主要内容,如果未能解决你的问题,请参考以下文章

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

如何使用 Laravel 5.3 创建 REST 完整 Web 服务的 Api

如何在 Laravel 中为 REST API 创建身份验证

如何在 Lumen/Laravel 中为 REST API 集成 Swagger?

如何在 Laravel Jetstream 上使用 REST API 管理用户

Laravel 7 - 使用 REST API 而不是数据库