Laravel possible routing issue, getting 404 - php

Laravel route returning 404 error. I added a new route and action to my controller and a previous route that was working is now not working. I'm not really sure where I'm going wrong, but I've been working on this so long I'm probably blind to the actual issue.
Here is my new route
Route::get('rental_agreements/{rentalAgreement}/generate_from_quote', 'RentalAgreementController#generateFromQuote');
Here are all my POST routes for that controller:
Route::post('rental_agreements/quick_link', 'RentalAgreementController#quickLink');
Route::post('rental_agreements/{customer}/store', 'RentalAgreementController#store');
Route::post('rental_agreements/{customer}/generate', 'RentalAgreementController#generate');
Route::post('rental_agreements/{rentalAgreement}/email', 'RentalAgreementController#email');
Route::post('rental_agreements/{rentalAgreement}/store_site_contact', 'RentalAgreementController#storeSiteContact');
The new route works fine, the route that is now giving the 404 error is for the store. Previously I did not have /store at the end and it worked fine, but I added this in an attempt to make sure it was not conflicting with something else.
I'm not sure that it's an issue in the routes but I'm not sure where else to look. In my controller, the code runs through the request but gives the 404 as soon as it gets back to the controller. If I remove the request parameter then it works up until saving the resource.
Currently, when I run the code I'm not getting any errors in my log file, which is strange because before I was getting.
local.ERROR: Class App\Http\Controllers\RentalAgreement does not exist
I have tried clearing the route cache, dumping autoload, and just about everything else I can think of.
Controller - I'm only showing the relevant code.hopefully, I'm not leaving something important out.
<?php
namespace App\Http\Controllers;
use App\Customer;
use App\Location;
use App\RentalAgreement;
use App\Http\Requests\RentalAgreementRequest;
use DB;
use Illuminate\Http\Request;
class RentalAgreementController extends Controller
{
public function store(RentalAgreementRequest $rentalAgreementRequest, Customer $customer)
{
$rentalAgreement = RentalAgreement::create($rentalAgreementRequest->request->all());
return redirect()->action('RentalAgreementController#edit', ['customer' => $customer, 'rentalAgreement' => $rentalAgreement])
->with('alert', 'Rental agreement created.');
}
}
Form tag - note $rentalAgreement is not set in this scenario
<form method='POST' action="/rental_agreements/{{ isset($rentalAgreement) ? $rentalAgreement->customer->id.'/'.$rentalAgreement->id.'/update' : (isset($customer) ? $customer->id.'/store' : '') }}">
Here is the General section from the Chrome Networking tab
Request URL: http://localhost:8000/rental_agreements/34/store
Request Method: POST
Status Code: 302 Found
Remote Address: 127.0.0.1:8000
Referrer Policy: no-referrer-when-downgrade
I'm not really sure where I;m going wrong. Any help is appreciated!

Related

Method not allowed - redirect using incorrect method

I have been working on a simple Laravel Inertia Vue3 application. It has one resource route.
Route::resource('contact', \App\Http\Controllers\ContactController::class);
This provides the named routes contact.index .store .create .show .update .destroy and .edit
Nice and simple so far.
I have a useForm form variable in my Vue component with some assigned variables
let form = useForm({ ... });
I have a submit method in the same component
let submit = () => {
if(props.edit) {
form.patch(`/contact/${props.contact.id}`);
} else {
form.post(`/contact`);
}
}
Again nothing complex. The post method fires off correctly and redirects
Contact::query()->create($request->all());
return redirect()->to(route('contact.index'));
For full disclosure of the update method, please see below:
public function update(Request $request, Contact $contact): \Illuminate\Http\RedirectResponse
{
$contact->fill($request->all())->save();
return redirect()->to(route('contact.show', ['contact' => $contact]));
}
This works in the same way as store. Simple and then redirects... but it doesn't.
What happens is that it runs the patch and then calls redirect
The redirect carries the patch method through ending up with a 405 if I use the index route (declared as get). If I use back() I get the same thing. If I use the show route, it redirects in a loop because the patch route uses the same URL /contact/{contact}
I have built Laravel applications for the last 5 years and have not had an issue like this before when using a named route. Have I missed something basic? If not its possibly a configuration issue although I am not sure what.
I am running Laravel 9.19 with webpack manually installed as its been changed to Vite on the current release. I have no Vue errors or warnings and no Laravel logs.
there is a difference between PUT and PATCH requests on laravel-level.
Please run php artisan route:list - and see which one is used in your case, There is a big chance that you using PUT, not patch :)
So good ol' Laravel got me again.
Alexander Dyriavin got me on the right course with his answer about put and patch, however, it wasn't really the solution.
The solution:
form.transform((data) => ({
...data,
_method: 'PUT' //spoof added to request
})).post(`/contact/${props.contact.id}`); //sent as a post instead
The Laravel docs allow you to spoof methods https://laravel.com/docs/5.0/routing#method-spoofing by posting them with a _method field.
Simply put, a patch or put request would have always failed with a redirect from Laravel. In the past I would have used them with Axios and handled a JSON response directly.
This time I really am answering my own question.
I was a total idiot and missed a step when setting up inertia js. I was attempting to retrieve errors with the useform method and what happened was I received nothing.
So I though I would double check the docs.
Turns out I missed adding this middleware to the web middleware group in the kernel!
\App\Http\Middleware\HandleInertiaRequests::class,
I can now use the .patch method I had before and no need for any additional code

Laravel PHPUnit returning 404

For laravel API I have write the test cases. But whenever I am running the test cases it always failed with below error,
1) Tests\Feature\CompanyTest::orgTest
Expected status code 200 but received 404.
Failed asserting that 200 is identical to 404.
After adding the $this->withoutExceptionHandling(); to testcase code it return the below error,
1) Tests\Feature\CompanyTest::orgTest
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: POST domainname/index.php/api/company
/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithExceptionHandling.php:126
/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:415
/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:113
/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:507
/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:473
/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:332
/tests/Feature/CompanyTest.php:21
My Code in Test File is,
public function orgTest()
{
$requestData = ["organizationId" => 10,"offset"=>1,"limit"=>10,"notificationId"=>""];
$response = $this->withoutExceptionHandling();
$response->postJson('/index.php/api/company',$requestData);
$response->assertStatus(200);
}
I have googled the error and tried many solutions but unable to succeed. Anyone please let me know whats the issue.
It is a 404 error, so your webpage is not found :
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: POST domainname/index.php/api/company
Bad way to go, post to /api/company or with /index.php/api/company but not with "domainname" !
If it is not working, check your route config for that api route. Are your controller and action declared well ?
By default, laravel's routing does not explicitly show that it is a php file rather than it has dedicated endpoints which you decide on the routing file. So index.php shouldn't be a valid route for laravel.
A 404 error status code refers to a Not Found Error. Maybe the api url that you are trying to access does not match the one inside the routes file whether you are using web.php or api.php.
I suggest using php artisan route:list on the base path of the project to properly see that the route you wanted is registered and match it from there.
It seems to me that PHPUnit can't find not only this URL but the whole website. You could check it by request to "/" in your test.
If I'm right, first of all, I'll suggest checking the param APP_URL in your .env.testing. Usually, I set it as APP_URL=http://localhost, and it works for me.
A 404 code means there was nothing found at the specified route. It could be the route you specified index.php/api/company. Try routing to [host:port]/api/company

Laravel getting 404 error when creating new route

it appears that when I created a new route, I receive the 404 error when trying to access the url, which is funny,. because all of my other routes are working just fine.
My web.php looks like so:
Auth::routes();
Route::post('follow/{user}', 'FollowsController#store');
Route::get('/acasa', 'HomeController#index')->name('acasa');
Route::get('/{user}', 'ProfilesController#index')->name('profil');
Route::get('/profil/{user}/edit', 'ProfilesController#edit')->name('editareprofil');
Route::patch('/profil/{user}', 'ProfilesController#update')->name('updateprofil');
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
Route::get('/alerte/url/{user}', 'UrlsController#index')->name('editurl');
Route::post('/alerte/url/{user}', 'UrlsController#store')->name('updateurl');
Route::get('/alerte/url/{del_id}/delete','UrlsController#destroy')->name('deleteurl');
The one that is NOT working when I am visiting http://127.0.0.1:8000/alerte is:
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
The controller looks like so:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Auth;
class PaginaAlerte extends Controller
{
public function __construct() {
$this->middleware('auth');
}
public function index(User $user)
{
return view('alerte');
}
}
I am banging my head around as I cannot see which is the problem. It is not a live website yet, I am just developing on my Windows 10 pc using WAMP.
Moved my comment to a little bit explained answer.
So, in your route collection, you have two conflicting routes
Route::get('/{user}', 'ProfilesController#index')->name('profil');
and
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
Imagine that Laravel is reading all routings from top to bottom and it stops to reading next one after the first match.
In your case, Laravel is thinking that alerte is a username and going to the ProfilesController#index controller. Then it tries to find a user with alerte username and returning 404 because for now, you don't have a user with this username.
So to fix 404 error and handle /alerte route, you just need to move the corresponding route before /{username} one.
But here is the dilemma that you got now. What if you will have a user with alerte username? In this case, the user can't see his profile page because now alerte is handling by another route.
And I'm suggesting to use a bit more friendly URL structure for your project. Like /user/{username} to handle some actions with users and still use /alerte to handle alert routes.
The following route catches the url /alerte as well
Route::get('/{user}', 'ProfilesController#index')->name('profil');
Since this one is specified before
Route::get('/alerte', 'PaginaAlerte#index')->name('alerte');
The /alerte will go the the ProfilesController instead.
To fix this change the order of the url definitions or change either of the urls to have nesting e.g. /alerte/home or /user/{user}
Well.
Maybe this is too late, but I have all week dealing with this problem.
I made my own custom.php file and add it in the routes path of my Laravel project, and none of the routes were working at all.
This is how I solved it:
You must remember to edit the RouteServiceProvider.php file located in app\Providers path. In the map() function, you must add your .php file. That should work fine!
To avoid unexpected behaviors, map your custom routes first. Some Laravel based systems can "stop" processing routes if no one of the expected routes rules were satisfied. I face that problem, and was driving me crazy!
I would wish suggest to you declare your URL without the "/", like your first "post" route, because sometimes, I have been got this kind of errors (404).
So, my first recomendation is change the declaration of the route. After that, you should test your middleware, try without the construct, and try again.
Good luck!

Laravel Authorize() confusion

I'm currently migrating a project from CodeIgniter to Laravel5.
I saw in Laracasts that you can use the Request::authorize() method to authorize access before the controller is called, and it returns true or false.
This would (I think) be the ideal solution as I can contain permission checks within the request, rather than pollute the controller with permission checks and redirections / responses.
The only problem is, when I return false from authorize(), it simply loads an empty white page with forbidden written, and I can't find any documentation on laravel.com on how to template it (either there is no documentation, or I'm overlooking it)
I know I can edit the 404 page in errors/404.blade.php, but I can't work out how to customize the 403 page, which I've tried to add a custom 403.blade.php page, which doesn't get displayed. ( https://mattstauffer.co/blog/laravel-5.0-custom-error-pages )
Is placing these permission checks in the Request a good idea? Or am I missing something?
Update
I ran a backtrace from authorize(), and it looks like it throws an UnauthorizedException, which extends RuntimeException. I've tried catching both in the routes.php file, which doesn't work either.
I've also tried to create middleware, and call the middleware from a method, which doesn't work either, since the middleware's not even called at all.
Update 2
Ok, so I found out that I can only call $this->middleware() from the constructor, not individual methods, which is progress, I guess.
What i do is add a forbiddenResponse() method to Request abstract class. You can return a response object from that method to render a human readable error.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\JsonResponse;
abstract class Request extends FormRequest {
public function forbiddenResponse()
{
return new JsonResponse('Unauthorized', 403);
// or return Response::make('Unauthorized', 403);
}
}
Check the app\Exceptions\Handler.php file. That's where you can customize your exception handling.
The 403 error launches a HttpException. By default, Laravel will look under your resources\views\errors\ directory and try to find a view that corresponds to the same status code. Since you already said that you've created a file called 403.blade.php inside that folder, it should render this page for 403 errors.
One last thing, remember to check inside your web server config file (httpd.conf for Apache, sites-available\your-host for Nginx), if you have a default behavior for any error. If you're using Homestead, you can check the Nginx config file for anything like error_page 404 /index.php;, comment the line and restart the service. That's not the ideal scenario but usually works.
Override the method within your form request object
class CreateUserRequest extends FormRequest {
public function forbiddenResponse(){
return abort(403);
}
}

laravel 4 route not found - defaults to show method

I've had this working but now a route is no longer found and I can't see why.
In a javascript function I am making an ajax post to the function with this url:
url: '/customers/storeajax',
In my routes.php file I have the following routes:
Route::post('customers/storeajax', array('as'=>'storeajax', 'uses' => 'CustomersController#storeAjax'));
Route::post('customers/updateajax/{id}', array('as'=>'updateajax','uses' => 'CustomersController#updateAjax'));
Route::resource('customers', 'CustomersController');
Now when I try to POST to the storeajax route I get a ModelNotFoundException which to me means the route could not be found so it defaults to the default customers controller show method - in the error log I can see the following entry:
#1 [internal function]: CustomersController->show('storeajax')
confirming its treating the storeajax as a parameter.
I've placed my additional routes above the default resource route
I've had this working before I can't see where I've gone wrong.
In addition these routes are placed in a group:
Route::group(array('before' => 'sentryAuth'), function () {}
which simply ensures user is logged on. To test though I've removed outside the group and at the top of the file but still they don't work.
The url in my browser is coming up correctly as: http://greenfees.loc/customers/storeajax (which I can see in firebug console
I'm using POST as the ajax method - just to confirm
Can anyone see why this route doesn't work and what I've missed?
Update:
Here's the method inside the controller:
public function storeAjax()
{
$input = Input::all();
$validation = Validator::make($input, Customer::$rules);
if ($validation->passes())
{
$customer = $this->customer->create($input);
return $customer;
}
return Redirect::route('customers.create')->withInput()
->withErrors(validation)
->with('message', 'There were validation errors.');
}
I'm 99% certain though that my route is not reaching this method (i've tested with a vardump inside the method) and the issue relates to my route customer/storeajax cannot be found.
What I think is happening is as customer/storeajax is not found in the list of routes starting with customer it is then defaulting to the resource route that appears on the list and thinks this is a restful request and translating it as customer route which defualts to the show method and using the storeajax as the parameter which then throws the error modelnotfoundexception because it cant find a customer with an id of 'storeajax'
This is evidence by the log detailing a call to the show method as above.
So for some reason my route for '/customers/storeajax' cannot be found even though it appears to be valid and appears before the customers resource. The modelnotfoundexception is a red herring as the cause is because of the routes defaulting to the resource constroller of customers when it cant find a route.
A route not being found raises a NotFoundHttpException.
If you are getting a ModelNotFoundException is because your route is firing and your logic is trying to find a Model, wich it can't somehow, and it is raising a not found error.
Are you using FindOrFail()? This is an example of method that raises this exception. BelongsToMany() is another one that might raise it.
I solved this by renaming the method in the controller to 'newAjax' and also updating the route to:
Route::post('customers/new', array('as'=>'newajax','uses' => 'CustomersController#newAjax'));
the terms store I assume is used by the system (restful?) and creating unexpected behaviour. I tested it in a number of other functions in my controller - adding the term store as a prefix to the method then updating the route and each time it failed.
Something learned.

Categories