Laravel Route::resource naming - php

I have the following in my routes.php
Route::resource('g', 'GameController');
I link to these generated routes via HTML::linkRoute('g.index', 'Title', $slug) which produces a link to http://domain/g/demo-slug
What I am looking to do is verify if it is possible to have the prefix be declared in one place so I'm not hunting for links if a URL structure were to change.
For example, I would want to change http://domain/g/demo-slug to http://domain/video-games/demo-slug
I was hoping to use the similar functionality with the standard routes, but that does not seem to be available to resource routes.
Route::get('/', array('as' => 'home', 'uses' => 'HomeController#getUpdated'));

Route::group() takes a 'prefix'. If you put the Route::resource() inside, that should work.
Tangent, I find this reads better:
Route::get('/', array('uses' => 'HomeController#getUpdated', 'as' => 'home'));

As far as I know it's true you can't have named routes for a resource controllers (sitation needed) but you can contain them in a common space using Route::group() with a prefix. You can even supply a namespace, meaning you can swap out an entire api with another quickly.
Route::group(array(
'prefix' => 'video-games',
'before' => 'auth|otherFilters',
'namespace' => '' // Namespace of all classes used in closure
), function() {
Route::resource('g', 'GameController');
});
Update
It looks like resource controllers are given names internally, which would make sense as they are referred to internally by names not urls. (php artisan routes and you'll see the names given to resource routes).
This would explain why you can't name or as it turns out is actually the case, rename resource routes.
I guess you're probably not looking for this but Route:group is your best bet to keep collections of resources together with a common shared prefix, however your urls will need to remain hard coded.

You can give custom names to resource routes using the following syntax
Resource::route('g', 'GameController', ['names' => [
'index' => 'games.index',
'create' => 'games.create',
...
]])
This means you can use {!! route('games.index') !!} in your views even if you decided to change the URL pattern to something else.
Documented here under Named resource routes

Related

Laravel 5.5 Route Controller [ Page not found ]

I have a program that uses $router->resource([]). I use laravel-admin.
here my routes.php
$router->resources([
'programs' => ProgramController::class,
'programs/categories' => ProgramCategoryController::class,
]);
on my programs its work well with all the crud operation.
but on my programs/categories its not working, said not found. did route controller must use different url?...
i mean my category can't be child from my programs with different controller?...
Try changing "programs/categories" to "programs.categories"
You want to add "programs" prefix to categories resource routes. You can do it by changing you code as follows:
$router->resources([
'programs' => ProgramController::class,
]);
// to add programs prefix to categories routes
Route::group(['prefix' => 'programs'], function () use ($router) {
$router->resource('categories', ProgramCategoryController::class);
// here you can add more routes and all those routes will have
// "programs" prefix in there url
});
refer to https://laravel.com/docs/5.5/controllers#resource-controllers
Supplementing Resource Controllers
If you need to add additional routes to a resource controller beyond the default set of resource routes, you should define those routes before your call to Route::resource; otherwise, the routes defined by the resource method may unintentionally take precedence over your supplemental routes:
Route::get('photos/popular', 'PhotoController#method');
Route::resource('photos', 'PhotoController');
So on my case above, just simply change this:
$router->resources([
'programs' => ProgramController::class,
'programs/categories' => ProgramCategoryController::class,
]);
to this :
$router->resources([
'programs/categories' => ProgramCategoryController::class,
'programs' => ProgramController::class,
]);
and it's working well now, also both crud operations.
it's not an optimal solution but its working for me.

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.

Laravel define a put/patch route as the same route name

In Laravel it's quite handy to quickly generate a load of routes by using a route resource:
Route::resource('things'ThingsController');
This will produce all the necessary RESTful routes for CRUD operations. One of these is the PUT/PATCH route which might be defined as follows:
PUT/PATCH things/{id} ThingsController#update things.update
I've read around that it's better to explicitly define each of your routes rather than use a route resource but how would I define the PUT/PATCH route above. I understand that I can do
Route::put('thing/{id}', ['as' => 'things.update']);
or
Route::patch('thing/{id}', ['as' => 'things.update']);
But the second would overwrite or conflict with the first allowing the things.update route name to only refer to either a PUT or PATCH request. How can I explicitly create the combined PUT/PATCH route as created by the resource route?
After tedious searching, try the following;
Route::match(array('PUT', 'PATCH'), "/things/{id}", array(
'uses' => 'ThingsController#update',
'as' => 'things.update'
));
This allows you to restrict request via an array of Verbs.
Or you can limit the resource as so;
Route::resource('things', 'ThingsController',
array(
'only' => array('update'),
'names' => array('update' => 'things.update')
));
Both should provide the same result, but please note they are not tested.
This work for me
Route::match(['put', 'patch'],'thing/{id}', 'ThingsController#update');

Laravel URL Generation Not Including Parameters

I'm seeing an issue with Laravel 4 when I have two routes pointing to the same action, one within a group and one just "loose" in the routes.php file.
<?php
// Routes.php
Route::group(array('domain' => '{subdomain}.domain.com'), function()
{
Route::get('profile/{id}/{name}', 'ProfileController#index');
});
Route::get('profile/{id}/{name}', 'ProfileController#index');
// Template.blade.php
Jim Smith
The template links to: currentsubdomain.domain.com/profile/%7Bid%7D/%7Bname%7D instead of the expected behaviour of swapping the ID and name for 123 and JimSmith respectively.
If I comment out, the first route (the one within the group), the code works as expected. Why does adding this additional route break the URL generation? Is there a way to work around this? Am I missing something obvious?
P.s. For those wondering why I need this route in two places it's so I can optionally generate the url with the subdomain using URL::action('ProfileController#index' array('subdomain' => 'james', 'id' => 123, 'name' => 'JimSmith');
The problem is that you don't have names/aliases for the routes so it's defaulting to the first one it comes across.
Consider this an alternate route structure:
Route::group(array('domain' => '{subdomain}.domain.com'), function() {
Route::get('profile/{id}/{name}', [
'as' => 'tenant.profile.index',
'uses' => 'ProfileController#index'
]);
});
Route::get('profile/{id}/{name}', [
'as' => 'profile.index',
'uses' => 'ProfileController#index'
]);
Now that you have these routes named, you can do:
{{ URL::route('profile.index', [123, 'jSmith']) }}
Or alternatively:
{{ URL::route('tenant.profile.index', ['subdomain', 123, 'jSmith']) }}
As just an added extra, you could only have this route defined once, then in all the controller methods you'd have something like:
public function index($subdomain = null, $id, $name) { }
Then you can just simply pass www through as the subdomain and have some code somewhere that discounts the www.domain.com domain from certain actions.
Multi-tenancy (if that is indeed what you're after) isn't easy and straight forward but there are some methods used to tackle certain parts. I'm actually planning on writing a tutorial regarding it, but for now I hope this helps somewhat.

Required order for specifying restful routes in Laravel 4?

I'm trying to understand routing in Laravel 4. I read a good post here on StackOverflow and a link to beware the route to evil, a post about manually specifying routes. I like the idea of specifying my routes manually and having the routes.php act as documentation. But it seems like I need to be cautious about the order of my Routes if I'm going to specify my own instead of using Route::resource() If I have the new or create route before the show then I won't be routed to the show because of the variable in URI? The order in which the routes are defined is important right?
// This will not work if I try and browse to dogs/new
Route::get('dogs', array('as' => 'dogs', 'uses' => 'DogsController#index'));
Route::get('dogs/{dogs}', array('as' => 'dog', 'uses' => 'DogsController#show'));
Route::get('dogs/new', array('as' => 'new_dog', 'uses' => 'DogsController#create'));
It seems I need to make sure that the dogs/new comes before the dogs/{dogs} for new to return correctly. I'm not clear on what {dogs} does or that's different from (:any) or {any} I've seen a few different uses in examples and pseudo code. I see that /new is the same as {...} when the route is before the more specific is the {} like a wildcard in Laravel 4? Is the (:...) the old way?
As an aside I've noticed a different naming convention from some of the examples I've seen when I run php artisan routes with a resource route like Route::resource('photos', 'PhotosController'); The method and named route for post to index to a create a new resource is named photos.store and #store. The method and named route for a link to a form to create a new resource is photos.create and #create. Is that Laravel 4 thing or conventions in other frameworks?
Route::get('dogs/{dogs}', array('as' => 'dog', 'uses' => 'DogsController#show'));
The above url expecting a parameter after dogs segment.
for example: http://laravel.com/dogs/xyz, http://laravel.com/dogs/new
after dogs url segment, Laravel will accept anything. So, your another routing will never executed for the route parameter.
Route::get('dogs/new', array('as' => 'new_dog', 'uses' => 'DogsController#create'));
More about route parameters:
http://laravel.com/docs/routing#route-parameters
Resource Controllers
Laravel and Ruby on rails support resource full routing. I think, Tailor borrow the resource full routing idea from Ruby on rails.
The following routes will generate if you use resource controller:
index
create
store
update
show
edit
destroy
http://guides.rubyonrails.org/routing.html
http://laravel.com/docs/controllers#resource-controllers

Categories