1

What is the correct way of adding a custom method to a resource controller in Laravel 5.6?

What I have so far is a new method in my ProfileController:

public function approve($id){
    $user = User::find($id);
    $user->state = '1';
    $user->save();
    return redirect('/dashboard')->with('success', 'User approved.');
}

As well as the following lines added to my web.php file:

Route::post('/profile/{$id}/approve', 'ProfileController@approve');
Route::resource('profile', 'ProfileController');

The form in my view is (afaik) correctly rendered to:

<form method="POST" action="http://myurl.com/profile/10/approve" accept-charset="UTF-8">
    <input name="_token" type="hidden" value="v3F1RRhi7iJL2o4egOhcRiuahaGQBwkGkfMal1lh">
    <input name="_method" type="hidden" value="PATCH">
    <input class="btn btn-success" type="submit" value="Approve User">
</form>

Unfortunately nothing happens, except the "Sorry, the page you are looking for could not be found." page to be shown.

What am I missing? And to expand a bit on this question also, is this even a valid way to implement "single field updates" on a db entry?

Thank you for your help!

Quhalix89
  • 129
  • 1
  • 2
  • 10

3 Answers3

2

You would want to remove the $ sign from your route:

Route::post('/profile/{id}/approve', 'ProfileController@approve');

The rest of it is correct.

Ozan Kurt
  • 3,731
  • 4
  • 18
  • 32
  • Once the $ has been removed, I now receive an "Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException No message". Is this related to the method spoofing input field I added? – Quhalix89 Aug 19 '18 at 14:47
  • @Quhalix89 because you are passing `patch` method in form but expecting `post` in routes. – Tpojka Aug 19 '18 at 14:51
2

i see you have two problems: firstly correct the route like that

Route::post('/profile/{id}/approve', 'ProfileController@approve');

secondly you have to delete

<input name="_method" type="hidden" value="PATCH">

or replace your route like that:

Route::patch('/profile/{id}/approve', 'ProfileController@approve');

AG MBALLA
  • 86
  • 4
  • 1
    Changing the route call to `Route::Patch` did the trick for me. However, is this a valid way to go? I could not find to many information about what the hidden input field _method is actually about and in particular, what the PATCH value means...? – Quhalix89 Aug 19 '18 at 15:08
  • PATCH is just rest method like POST, GET, PUT, DELETE, ETC... the input ` – AG MBALLA Aug 20 '18 at 08:17
0

You have written the parameter like var: $id, and you may write it without '$'. But really you can use the Laravel implicit model binding function to do this:

Route::post('/profile/{user}/approve', 'ProfileController@approve');

And then in your controller:

public function approve(User $user){
    // Delete this line--> $user = User::find($id);
    $user->state = '1';
    $user->save();
    return redirect('/dashboard')->with('success', 'User approved.');
}
  • I'd also want to thank you for your comment. Can you briefly describe what the benefit of using the implicit model binding function is? And regarding the form in the view, does it matter what data I provide in the form (currently $user->id)? – Quhalix89 Aug 19 '18 at 16:00
  • 1
    Model binding brings you multiple benefits. The first and most important is the clarification of concepts and the code readability. In your case, the most correct approach would be naming the route: ` Route::post('/profile/{user}/approve', 'ProfileController@approve')->name('user-approve'); ` Then, you can use it in your view in the way: ` action="{{route('user-approve', ['user' => $user])}}" ` Later, in the controller you don't need to do the search, Laraver do for you, and if the user does not exist, it automatically throws a ModelNotFoundException. Enjoy. Its amazing! – Alejandro García Aug 19 '18 at 16:13