Laravel localization package throws MethodNotAllowedHttpException on POST request - php

I use this package for localization https://github.com/mcamara/laravel-localization and it works fine in most cases except with one POST request.
When I try to access:
Route::group(
[
'prefix' => LaravelLocalization::setLocale(),
'middleware' => ['localeSessionRedirect', 'localizationRedirect', 'auth'],
],
function () {
Route::post('bsSearch', 'BrandSpendingsController#search')->middleware('premium');
}
I get an MethodNotAllowedHttpException ... When I switch it to GET it works fine... However it works for english language. If I switch the url to http://localhost/de/bsSearch, it throws an error.
Route::get('bsSearch', 'BrandSpendingsController#search')->middleware('premium');
I am really not sure why because this one works fine and it is a POST method as well:
Route::post('editUserProfile/{id}', 'UserController#edit');
I use Laravel 5.3.
EDIT
The english url works because I've set 'hideDefaultLocaleInURL' => true, in laravellocalization.php and when it hides the "en" prefix in URL. If i set it to false, it throws an error for English as well.

Here is an answer
it is better to localize only GET routes by puting them to localized group and don't put there another routes
if you need to localize another methods like POST, PUT, PATCH, DELETE, you should localize your url as described here

Related

Laravel 5.2 Localization , auth::user value not showing up when switching language

Using Laravel 5.2.41
Using following translation package: mcamara/laravel-localization
Link inside my view :
Edit Link
routes.php files inside Lang/fr & Lang/nl
<?php
return [
'account-edit' => "account/wijzig-gegevens/{id}",
];
<?php
return [
'account-edit' => "donnees/modifier-donnees/{id}",
];
Laravel routes file:
Route::group([
'prefix' => LaravelLocalization::setLocale(),
'middleware' => ['localize','localeSessionRedirect', 'localizationRedirect' ]
], function()
{
Route::get(LaravelLocalization::transRoute('routes.account-edit'),'AccountController#edit');
});
When i look at the link in my default language (nl) i get the correct link like so:
Edit Link
But when i change my language to french i get following link:
Edit Link
Can't figure out why this is happening
I was looking into the code of that package.
It seems to me if I'm not mistaken, that the logic regarding the translation of URL's is based on the route name, not the route path.
You are using the route path here:
LaravelLocalization::getLocalizedURL(null, trans('routes.account-edit'), ["id" => Auth::user()->id])
But it seems like you should actually use the route name instead, meaning 'account-edit' in this case.

Laravel 5.1 - Overloaded routes

I have a homegrown, Laravel 5.1 base application on top of which I build specific applications. The base application uses a named route for login, naturally called "login", which listens for GET /login.
In one of my specific applications, I attempted to overload that route to send the requests to a different controller. It seemed to work for a while, but then it started going to the base application's controller again. I'm sure I changed something to break it, but the problem is that I can't figure out how to fix it again.
My base application routes are all defined in app/Http/Routes/core.php. The relevant route:
Route::get('login', [
'as' => 'login',
'uses' => '\MyVendor\Core\Http\Controllers\AuthController#getLogin'
]);
My specific application routes are defined in app/Http/Routes/app1.php. The relevant route:
Route::get('login', [
'as' => 'login',
'uses' => 'App1\AuthController#getLogin'
]);
App2 and App3 are defined similarly. My app/Http/routes.php adds these routes like this:
require 'Routes/core.php';
Route::group(['domain' => 'app1.com'], function() {
require 'Routes/app1.php';
});
Route::group(['domain' => 'app2.com', function() {
require 'Routes/app2.php';
});
Route::group(['domain' => 'app3.com', function() {
require 'Routes/app3.php';
});
The problem I am seeing is that visiting app1.com/login, app2.com/login, and app3.com/login all result in the execution of \MyVendor\Core\Http\Controllers\AuthController#getLogin rather than App1\AuthController#getLogin.
EDIT: I have changed the problem description since I was describing it incorrectly as a problem with calls to route('login').
The index of the routes in Laravel follows a "$domain$uri" format, therefore routes with a domain won't overwrite those without. A fallback route without a domain should be declared after the domain group, so it is later in the route collection and won't match before a route with a matching domain.
"the most recent definition for a route is the effective route"
This is not a bug, this is the expected behaviour, a simple example would be setting a variable to value 1 then setting it to value 2, of course the (most) recent value takes place.

Laravel 5.2 Codeception functional test issue with PUT / PATCH requests

I have a problem on the update treatment processed into my functional tests on Codeception : I systematically have a 404 error. Here are the details.
Everything is going well for every other simulated http requests but when codeception tries to execute the update method on a put HTTP request (POST request with a "_method" param having the value "PUT") is never executed by my controller, which lead codeception on the update url without the redirection that should happen after the treatment in this update method. I tried to redirect to my home page on top of my update method to test that fact and the redirection never happens.
For information, I use the Laravel5 module. Here is my functional.suite.yml file content :
class_name: FunctionalTester
modules:
enabled:
- Asserts
- \Helper\Functional
- MailCatcher
- Laravel5:
environment_file: .env.testing
config:
MailCatcher:
url: 'http://192.168.10.10'
port: '1080'
I tried to replace the "PUT" value of the "_method" param by "PATCH" to see if any change could be seen but the problem persists and the behaviour is still the same.
Codeception includes the Laravel5 app to test it. The only clue I have is that the testing environment has a problem to interpret the PUT or PATCH request. There is no problem for a simple POST request (creation doesn't cause any problem).
I precise that the HTML form is correct, the update happens correctly in my local environment and the http request contains correct params. Here is what I have when I execute it the with the --debug option :
[Uri] http://project/en/permissions/update
[Method] POST
[Parameters] {"_token":"RUx7DjU3b6GEjodnpwXvJJYJIcmQJGbabj23q0yK","_method":"PATCH","_id":"1","name_en":"Administrator","name_fr":"Administrateur","slug":"admin"}
[Page] http://project/en/permissions/update
[Response] 200
[Request Cookies] {"XSRF-TOKEN":"eyJpdiI6InZQV2NVcTRoZHVONXYzZzNLTnBWU1E9PSIsInZhbHVlIjoiWWhWa0kyUGxJNkJRTXIyaEhVcDdHR0tRcklHZStpVWdlTjlDdmRKVmEyVDFPWkxBVmhLc1lra05zeWh1ZWtKMENCc29lWFZTN2lSd3dIbjZyNEo5eWc9PSIsIm1hYyI6ImEzMDNmOWM5OGQzNzE4ZWI5MDg0MTI0ZmQwMTI1ZTk0OTM1OTY4NjA5ZTZjMGFhYTI0MTdlMzMzM2QyMWQ4MzUifQ==","laravel_session":"eyJpdiI6ImF4cVFYYVNUU3J0WUd2VzNRZlhSc3c9PSIsInZhbHVlIjoibDdPd3ZEZVZOdDJwRlBjMVZtc2dNM0I3WUw0REEzK25NVFVWT1FIRjEzR05tRGZLXC9SYUZkRmhEdXlyQVdybURHTWVQVUtucnBkZEwwaTN4NWF6XC9YQT09IiwibWFjIjoiMzliODY4ZWUwYmZjODI1OTVkMTBiYjA4ODY2OWNiODc3ZTI1NzAzZmJhMjg4OTY4Y2MzM2VkMjYyYTkwOTQ2MyJ9"}
[Response Headers] {"cache-control":["no-cache"],"Set-Cookie":[{},{}]}
As you can see, the process end on a 200 response and that is all.. I tested it with a few pages and the problem is the same everywhere.
I'm blocked on this problem for weeks now without finding any solution. If someone has a clue, I am listening !.
EDIT 1 : 26/01/2015
As it has been asked to me, here is my routes file.
As you can see, I use LaravelLocalization, this is a multilingual app.
I only show you the permissions routes but they are all managed this way.
Route::group([
'prefix' => LaravelLocalization::setLocale(),
'middleware' => [
'auth',
'localize',
'localeSessionRedirect',
'localizationRedirect',
]], function () {
// permissions
Route::get(LaravelLocalization::transRoute('routes.permissions.index'), ['as' => 'permissions.index', 'uses' => 'User\PermissionsController#index']);
Route::get(LaravelLocalization::transRoute('routes.permissions.create'), ['as' => 'permissions.create', 'uses' => 'User\PermissionsController#create']);
Route::post(LaravelLocalization::transRoute('routes.permissions.store'), ['as' => 'permissions.store', 'uses' => 'User\PermissionsController#store']);
Route::get(LaravelLocalization::transRoute('routes.permissions.edit'), ['as' => 'permissions.edit', 'uses' => 'User\PermissionsController#edit']);
Route::put(LaravelLocalization::transRoute('routes.permissions.update'), ['as' => 'permissions.update', 'uses' => 'User\PermissionsController#update']);
Route::delete(LaravelLocalization::transRoute('routes.permissions.destroy'), ['as' => 'permissions.destroy', 'uses' => 'User\PermissionsController#destroy']);
});
EDIT 2 : 29/01/2015
Following the Lerzenit solution explained here, I tried to place the following code into the file tests/_bootstrap.php :
Request::enableHttpMethodParameterOverride();
It had no effect, I still have a 200 response and the update method from my controller is never reached.
I checked if the $httpMethodParameterOverride param was passed to true just after the method execution and could verify that is has been successful set to true.
I am still looking for a solution.
EDIT 3 : 05/02/2015
I have a clue on an investigation way : I succeeded to execute an update on a entity named 'District' and this is the only one on my project to have the same route in english and in french. As I specified earlier, I use the LaravelLocalization plugin and the routes translation may be the cause of the bad interpretation of the _method param with the PUTvalue that should redirect toward the update method of my controller.
I would be grateful if someone could help me on this.
I finally found the solution !
The update method was never reached because, on my POST requests, I sometimes passed the id of the resource into the request by using hidden variables as _id for example.
Laravel expect an id to be given on the post UPDATEor DELETErequests after a slash, that is why the UPDATE / DELETE methods were never reached. In fact, this is a bad practice to pass params in the request on PUT / PATCH / DELETE requests because the targeted resource must be explicitly shown in the url.
So, if you encounter the same problem, be sure you precise a correct POST route in your form as route('users.update', ['id' => $user->id])for example.
Pfiuuu, I now can write my tests in order to have a 100% tested app. That was a painful investigation ;)

laravel malforming URLs on prod environment

I have a controller function that gets called and returns a redirect_url to an AJAX request.
This is created using this call:
URL::to('model/configuration/'. $data->id )
In both production and local, there is a "prefix" url before the "model/" part of the URL. For example, the final url may look like part1/part2/model/configuration/8.
On production, the "part1/part2" part is not being generated by the URL::to() call.
Any idea why this is occurring and how to fix it?
full route definitions:
Route::post('model/configuration/{order_id}', ModelController#configUpdate');
Route::get('model/configuration/{order_id}', 'ModelController#model');
You mention a 'prefix' in your question, but I didn't see any in your route definitions. Regardless, I don't think URL::to() actually verifies that a route exists, and you can use it to make non-existent links to within your application (for whatever good that will do you).
I would suggest for you to instead name your route, and then you can leverage the URL::route() method instead:
Route::group(['prefix' => 'test'], function() {
Route::get('test2', [ 'as' => 'testing', function() {
var_dump(URL::route('testing'));
}]);
});
This will output the following URL:
string 'http://server.com/test/test2' (length=28)

Laravel says "Route not defined"

In my routes.php I have:
Route::patch('/preferences/{id}', 'UserController#update');
And in the view file (account/preferences.blade.php) I have:
{!! Form::model(Auth::user(), ['method' => 'PATCH', 'route' => '/preferences/' . Auth::user()->id]) !!}
But I'm getting this error:
Route [/preferences/1] not defined
A similar error occurs when calling the route() helper directly:
route('/preferences/' . Auth::user()->id');
I think I'm misunderstanding the docs on this topic but I've defined a route for PATCH requests with a given parameter, and set this in the view correctly. What am I overlooking here?
The route() method, which is called when you do ['route' => 'someroute'] in a form opening, wants what's called a named route. You give a route a name like this:
Route::patch('/preferences/{id}',[
'as' => 'user.preferences.update',
'uses' => 'UserController#update'
]);
That is, you make the second argument of the route into an array, where you specify both the route name (the as), and also what to do when the route is hit (the uses).
Then, when you open the form, you call the route:
{!! Form::model(Auth::user(), [
'method' => 'PATCH',
'route' => ['user.preferences.update', Auth::user()->id]
]) !!}
Now, for a route without parameters, you could just do 'route' => 'routename', but since you have a parameter, you make an array instead and supply the parameters in order.
All that said, since you appear to be updating the current user's preferences, I would advise you to let the handling controller check the id of the currently logged-in user, and base the updating on that - there's no need to send in the id in the url and the route unless your users should need to update the preferences of other users as well. :)
This thread is old but was the first one to come up so I thought id share my solution too. Apart from having named routes in your routes.php file. This error can also occur when you have duplicate URLs in your routes file, but with different names, the error can be misleading in this scenario. Example:
Route::any('official/form/reject-form', 'FormStatus#rejectForm')
->name('reject-form');
Route::any('official/form/accept-form', 'FormStatus#acceptForm')
->name('accept-form');
Changing one of the names solves the problem. Copy, pasting, & fatigue can lead you to this problem :).
If route is not defined, then check web.php routing file.
Route::get('/map', 'NavigationController#map')->name('map'); // note the name() method.
Then you can use this method in the views:
<a class="nav-link" href="{{ route('map') }}">{{ __('Map') }}</a>
PS: the __('Map') is to translate "Map" to the current language.
And the list of names for routes you can see with artisan command:
php artisan route:list
I'm using Laravel 5.7 and tried all of the above answers but nothing seemed to be hitting the spot.
For me, it was a rather simple fix by removing the cache files created by Laravel.
It seemed that my changes were not being reflected, and therefore my application wasn't seeing the routes.
A bit overkill, but I decided to reset all my cache at the same time using the following commands:
php artisan route:clear
php artisan view:clear
php artisan cache:clear
The main one here is the first command which will delete the bootstrap/cache/routes.php file.
The second command will remove the cached files for the views that are stored in the storage/framework/cache folder.
Finally, the last command will clear the application cache.
when you execute the command
php artisan route:list
You will see all your registered routes in there in table format .
Well there you see many columns like Method , URI , Name , Action .. etc.
So basically if you are using route() method that means it will accept only name column values and if you want to use URI column values you should go with url() method of laravel.
One more cause for this:
If the routes are overridden with the same URI (Unknowingly), it causes this error:
Eg:
Route::get('dashboard', ['uses' => 'SomeController#index', 'as' => 'my.dashboard']);
Route::get('dashboard/', ['uses' => 'SomeController#dashboard', 'as' => 'my.home_dashboard']);
In this case route 'my.dashboard' is invalidate as the both routes has same URI ('dashboard', 'dashboard/')
Solution: You should change the URI for either one
Eg:
Route::get('dashboard', ['uses' => 'SomeController#index', 'as' => 'my.dashboard']);
Route::get('home-dashboard', ['uses' => 'SomeController#dashboard', 'as' => 'my.home_dashboard']);
// See the URI changed for this 'home-dashboard'
Hope it helps some once.
My case is a bit different, since it is not a form but to return a view. Add method ->name('route').
MyView.blade.php looks like this:
CATEGORIES
And web.php routes file is defined like this:
Route::view('admin', 'admin.index')->name('admin');
i had the same issue and find the solution lately.
you should check if your route is rather inside a route::group
like here:
Route::group(['prefix' => 'Auth', 'as' => 'Auth.', 'namespace' => 'Auth', 'middleware' => 'Auth']
if so you should use it in the view file. like here:
!! Form::model(Auth::user(), ['method' => 'PATCH', 'route' => 'Auth.preferences/' . Auth::user()->id]) !!}
In my case the solution was simple:
I have defined the route at the very start of the route.php file.
After moving the named route to the bottom, my app finally saw it.
It means that somehow the route was defined too early.
On a side note:
I had the similar issues where many times I get the error Action method not found, but clearly it is define in controller.
The issue is not in controller, but rather how routes.php file is setup
Lets say you have Controller class set as a resource in route.php file
Route::resource('example', 'ExampleController');
then '/example' will have all RESTful Resource listed here:
http://laravel.com/docs/5.0/controllers#restful-resource-controllers
but now you want to have some definition in form e.g: 'action'=>'ExampleController#postStore' then you have to change this route (in route.php file) to:
Route::controller('example', 'ExampleController');
Please note that the command
php artisan route:list
Or to get more filter down list
php artisan route:list | grep your_route|your_controller
the forth column tells you the names of routes that are registered (usually generated by Route::resource)
In my case, I was using a duplicate method. I was trying to update like this:
Route::get('/preferences/{id}', 'UserController#edit');
Route::get('/preferences/{id}', 'UserController#update');
When what I meant to do was something similar to this:
Route::get('/preferences/{id}', 'UserController#edit');
Route::post('/preferences/{id}', 'UserController#update');
Notice the get and post methods are different but the URLs are the same.

Categories