Route is not working, it responds with "404 NOT FOUND" - laravel

I have a route which has two parameters.
Route::delete('/org/{org-id}/delete/user/{user-id}', 'App\Http\Controllers\OrganizationController#deleteUserFromOrg')
->name('delete-user-from-org');
i call it in view
<td><button class="btn btn-danger">Удалить</button></td>
i think this should work because it substitutes the data correctly and redirects to the page http://localhost:8000/org/11/delete/user/2. REturn 404 error.
It's does not see the controller, I tried some function in the route itself, this does not work either.

Route::delete('/org/{org-id}/delete/user/{user-id}', 'App\Http\Controllers\OrganizationController#deleteUserFromOrg')
->name('delete-user-from-org');
look at the Route::delete() part. In order to invoke that route i.e. delete-user-from-org, you will require a DELETE request method (or create a form with a hidden input via #method('delete')
When you create a link with <a></a>, the request will be a GET (by default unless manipulated by js) which is why you are getting a 404 Not Found Error. You have two solutions.
First Solution (via form):
<form action="{{route('delete-user-from-org',['org-id'=>$data->id, 'user-id' => $el->id ])}}" method="POST">
#method('DELETE')
...
</form>
Second solution (via ajax):
fetch("{{route('delete-user-from-org',['org-id'=>$data->id, 'user-id' => $el->id ])}}", {
method: 'DELETE',
})
.then(res => res.text()) // or res.json()
.then(res => console.log(res))
Third Solution (change the method): Not recommended. Avoid it.
Route::get('/org/{org-id}/delete/user/{user-id}', 'App\Http\Controllers\OrganizationController#deleteUserFromOrg')
->name('delete-user-from-org');
from Route::delete() to Route::get()

Route params should consist of alphabetic characters or _
Please fix your route params name
For example:
Route::delete('/org/{org_id}/delete/user/{user_id}', 'App\Http\Controllers\OrganizationController#deleteUserFromOrg')
->name('delete-user-from-org');
And your view blade
<td><button class="btn btn-danger">Удалить</button></td>

Related

Why is record not deleting and response is 303 in Laravel 9, Inertia and Vue3?

I have following code in route web.php file.
Route::resource('dailyrevenue', DailyRevenueController::class)->middleware('auth');
Then in my DailyRevenueController.php
public function destroy(DailyRevenue $revenue)
{
$revenue->delete();
return redirect()->back();
}
And in my vue3 code:
const submit = function (id) {
const check = confirm("Are you sure to delete ?")
if (check) {
Inertia.delete(route('dailyrevenue.destroy',id), {
id: id,
method: 'delete',
forceFormData: true
})
}
}
Finally in the template:
<template #cell(actions)="{item: tax}">
<form method="delete" #submit.prevent="submit(tax.id)">
<input type="hidden" name="_method" value="delete"/>
<button type="submit">Delete</button>
</form>
</template>
Now request reaches to the method. But nothing is deleted. The request sent is DELETE request. Instead of 302 response it sends back 303 (See others).
Community help is appreciated.
Thanks.
I found the solution. The reson behind it was the variable name. In url endpoint the variable name was decleared as dailyrevenue and in the method as $revenue.
You can find your url variable by typing php artisan route:list.
I found that the url variable name must match with variable name in method.
Hope this helps others too.

Laravel 9 - Submitting a form to a route leads to /null and doesn't do anything

I'm using soft deletes and trying to make a function to restore the deleted row. Really everything to do with submitting the form doesn't work, even deleting...
My tags are within a forelse loop, maybe that's the cause??
Route is (this is above my resource route):
Route::post('/post/restore/{id}', [PostController::class, 'restore'])
->name('post.restore');
Controller is:
public function restore($id)
{
dd($id);
}
Form/view is:
<form action="{{route('post.restore', $post->id)}}" method="POST">
#csrf
<button type="submit" class="dropdown-item popup" data-confirm="Would you like to restore?">Restore</button>
</form>
After submitting, it just takes me to:
domainURL/post/null
and gives a 404 error
Any advice?? I also tried it without the {id} at the end of the route, same results
I think you are using the wrong syntax for route function, instead of this:
route('post.restore', $post->id)
you should use it like this:
route('post.restore', ['id' => $post->id])
you can read more here as well.
I figured it out... my "would you like to restore?" javascript function was breaking the form. I was using javascript to popup a confirmation message before submitting and during that process it lost the ID
I got rid of that and it works fine
Thank you!

Laravel redirecting problem when submitting form

I have following routes
Route::get('videos/{video}/edit', 'VideoController#edit');
Route::put('videos/{video}/update2', 'VideoController#update2');
first route loads the following stripped view
<form action='/videos/{{$video->uid}}/update2' method='post'>
<button class='btn btn-default' type='submit'>Update</button>
{{csrf_field()}}
{{method_field('PUT')}}
</form>
from the controller code listed below
class VideoController extends Controller{
public function edit(\App\Models\Video $video){
return view('video.edit',[
'video' => $video,
]);
}
public function update2(VideoUpdateRequest $request,\App\Models\Video $video){
echo "ok";
}
}
according to this code, expected behavior should be to see "ok", instead of that I get HTTP 302 Redirect as shown below in Dev Console.
This is a weird behavior, which is not expected. How to get the expected behavior of displaying "OK" after submitting the form? How to debug this?
SOLVED
Problem was with HTML elements in the form are not having 'name' attributes thus Laravel Form Request Validation redirects back. after adding those missing attributes, form works as expected.
SOLVED
Problem was with HTML elements in the form are not having 'name' attributes thus Laravel Form Request Validation redirects back. after adding those missing attributes, form works as expected.

Laravel - route("resource.destroy") calls "resource.show"

This is the web.php
Route::group(['middleware' => 'auth'],
function () {
Route::get('letters/getRows', 'LetterController#getRows')->name('letters.getRows');
Route::get('letters/{letter}/A4', 'LetterController#A4')->name('letters.A4');
Route::get('letters/{letter}/A5', 'LetterController#A5')->name('letters.A5');
Route::resource('letters', 'LetterController');
}
);
I created a link as follow
"<a class='mx-2 h5' href='".route('letters.destroy', $entity->id)."'><i class='icon-remove-circle'></i></a>".
where the $entity->id is the id of the letter. The problem is, it links to show method not the destroy method. What can I do?
Using a form like this
{{ Form::open(array('route' => array('letters.destroy', $entity->id), 'method' => 'delete')) }}
<button type="submit" >Delete Account</button>
{{ Form::close() }}
may solve the problem but I want to use a tag not a form.
update
In the php artisan route:list, the url of destroy and show are the same
thanks
When you use the Route::resource method it will create, among others, a route to DESTROY a resource like this: /letters/:id/ and another route to EDIT the resource: /letters/:id, and one more to SHOW /letters/:id
They all look the same. However, the difference is in the HTTP method/verb used to reach each route.
If you look to the output if php artisan route:list, you will find the list of HTTP methods used. Something like:
GET|HEAD | letters/{letter} | letters.show
PUT|PATCH | letters/{letter} | letters.update
DELETE | letters/{letter} | letters.destroy
Therefore, to show a letter, you use a GET method, to edit a letter, use PUT method, and to destroy/delete, you use a DELETE method.
When you use an a tag, the browser will use the GET method, thus will reach the letters.show route. Html forms, can use POST or GET. Finally to use the DELETE http method, you need a form with hidden input named _method and the value="delete inside the form. Check the docs for more details.
There is also a note about this in LaravelCollective package documentations
Note: Since HTML forms only support POST and GET, PUT and DELETE methods will be spoofed by automatically adding a _method hidden field to your form.
Finally, if you must use an anchor tag <a>, you could use javascript to listen to the click event and submit a form with DELETE method.
Update to add an example:
You can find an example of using an anchor tag to submit the form, in the default app layout in the framework here
And this is a modified version to submit a delete request:
<a class="dropdown-item" href="#"
onclick="event.preventDefault();
document.getElementById('destroy-form').submit();">
{{ __('DELETE') }}
</a>
<form id="destroy-form" action="{{ route('letters.destroy', $entity) }}" method="POST" style="display: none;">
#method('DELETE')
#csrf
</form>
You cant. If you want to make a DELETE request you need to spoof it via a form (method POST, _method DELETE) or use Javascript.
Hyperlinks will cause new requests which will be GET requests. That is just how the web works.

How does Laravel handle PUT requests from browsers?

I know browsers only support POST and GET requests, and Laravel supports PUT requests using the following code:
<?= Form::open('/path/', 'PUT'); ?>
... form stuff ...
<?= Form::close(); ?>
This produces the following HTML
<form method="POST" action="http://example.com/home/" accept-charset="UTF-8">
<input type="hidden" name="_method" value="PUT" />
... form stuff ...
</form>
How does the framework handle this? Does it capture the POST request before deciding which route to send the request off to? Does it use ajax to send an actual PUT to the framework?
It inserts a hidden field, and that field mentions it is a PUT or DELETE request
See here:
echo Form::open('user/profile', 'PUT');
results in:
<input type="hidden" name="_method" value="PUT">
Then it looks for _method when routing in the request.php core file (look for 'spoofing' in the code) - and if it detects it - will use that value to route to the correct restful controller.
It is still using "POST" to achieve this. There is no ajax used.
Laravel uses the symfony Http Foundation which checks for this _method variable and changes the request to either PUT or DELETE based on its contents. Yes, this happens before routing takes place.
You can also use an array within your form open like so:
{{ Form::open( array('route' => array('equipment.update', $item->id ),
'role' => 'form',
'method' => 'put')) }}
Simply change the method to what you want.
While a late answer, I feel it is important to add this for anyone else who finds this and can't get their API to work.
When using Laravel's resource routes like this:
Route::resource('myRoute','MyController');
It will expect a PUT in order to call the update() method. For this to work normally (outside of a form submission), you need to make sure you pass the ContentType as x-www-form-urlencoded. This is default for forms, but making requests with cURL or using a tool like Postman will not work unless you set this.
PUT usually refers to update request.
When you open a form inside laravel blade template using,
{{ Form::open('/path/', 'PUT') }}
It would create a hidden field inside the form as follows,
<input type="hidden" name="_method" value="PUT" />
In order for you to process the PUT request inside your controller, you would need to create a method with a put prefix,
for example, putMethodName()
so if you specify,
{{ Form::open('controller/methodName/', 'PUT') }}
inside Form:open. Then you would need to create a controller method as follows,
class Controller extends BaseController {
public function putMethodName()
{
// put - usual update code logic goes here
}
}

Resources