ahoi's avatar
Level 5

Use PATCH to update a single field - reuse update-method in controller?

Hi there,

I am using POST/PUT to store or update my Models using routes/api.php. That works fine.

Now sometimes I get to update only one field - e.g. if I want to reorder a list of items using drag & drop and storing the updated position in the database.

At the moment I am using a new PUT-route to something like /api/item/updatePosition which calls a positionUpdate-method in the controller:

 /*UpdatePosition*/
        Route::middleware('auth:api')->put('/updatePosition', 'CategoryApiController@positionUpdate')
            ->name('api.category.position.update');

Now I was thinking about using PATCH instead of PUT and reuse the controller's update-method:

<?php

/**
 * @param \App\Http\Requests\CategoryRequest $request
 *
 * @return \Illuminate\Http\JsonResponse
 */
public function update(CategoryRequest $request): JsonResponse
{
    /*Get category*/
    $category = Category::findOrFail($request->input('category.id'));
    
    $category->update([
        'name'           => $request->input('category.name'),
        'slug'              => $request->input('category.slug'),
        'description' => $request->input('category.description'),
        // many more
    ]);
    
    /*Update status*/
    $category->setStatus($request->input('category.status'));
    
    return response()->json(['message' => 'success']);
}

So I thought about that I could determine whether the request is PUT or PATCH and update the fields accordingly. So my POST request would update all fields and the PUT request would expect a field-name that should be patched.

So I'd use something like

public function update(CategoryRequest $request, $field_to_patch = null): JsonResponse
{

// ...  if request's method is PATCH: 
 $category->update([
        $field_to_patch           => $request->input('category.'.$field_to_patch)
    ]);
}

//...
// ... if not, update all fields:

 $category->update([
        'name'           => $request->input('category.name'),
        'slug'              => $request->input('category.slug'),
        'description' => $request->input('category.description'),
        // many more
    ]);

This should work - but I just wonder if there's a more elegant way, as I'd somehow repeat myself here. I googled around and saw an interesting approach using request()->intersect (https://dyrynda.com.au/blog/partial-model-updates-in-laravel) but this got removed from Laravel.

Any good ideas how to elegantly handle this?

Thanks in advance for your input :-)

0 likes
1 reply
jlrdw's avatar

Just an opinion here, but I'd stick with using put. That way you are staying with normal HTTP.

Please or to participate in this conversation.