I want to pretty-up my routes, ie, I have such entries:
// DataTable
Route::get('dt/reservations/{room_id]', 'DataTablesController#reservations')->where(['room_id', '[0-9]+']);
Route::get('dt/rooms/{area_id]', 'DataTablesController#rooms')->where(['area_id', '[0-9]+']);
Route::get('dt/departments', 'DataTablesController#departments');
Route::get('dt/addresses', 'DataTablesController#areas');
Route::get('dt/areas', 'DataTablesController#areas');
I would like to make it more understandable. I can add prefix what would give me:
// DataTable
Route::group(['prefix' => 'dt'], function () {
Route::get('reservations/{room_id]', 'DataTablesController#reservations')->where(['room_id', '[0-9]+']);
Route::get('rooms/{area_id]', 'DataTablesController#rooms')->where(['area_id', '[0-9]+']);
Route::get('departments', 'DataTablesController#departments');
Route::get('addresses', 'DataTablesController#areas');
Route::get('areas', 'DataTablesController#areas');
});
But can I somehow make the rest too? The route name and method name will always be the same.
Is it possible to make something like:
// DataTable
Route::group(['prefix' => 'dt'], function () {
Controller => DataTablesController,
Methods => [
'reservations',
'rooms',
'departments',
'addresses',
'areas'
];
});
Although a very good feature. But it can't be done in Laravel
All your routes must be explicit, Laravel won't/can't assume that you
are using same controller for all the routes.
So you will have to define all the routes explicitly.
Only Resource Controllers can have implicit routing in Laravel
Take a look here....
Route use the same controller
Related
I have two kind of routes, admin routes and frontend routes.
The frontend routes
Route::get('{locale?}/', ['uses' => '\App\Http\Controllers\loadViewController#home']);
Route::get('{locale?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#index']);
Route::get('{locale?}/{template?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#detail']);
The backend routes
Route::prefix('admin/dashboard')->group(function () {
Route::get('/', 'DashboardController#index')->name('dashboard');
});
Now when i type admin/dashboard or api/admin, laravel uses the frontend routes to load the views, while i want the backend views to be loaded.
So to filter out the backend routes i tried this
Route::group(['where' => ['page' => '^(?!admin|api)$', 'template' => '^(?!admin|api)$']], function ({
Route::get('{locale?}/', ['uses' => '\App\Http\Controllers\loadViewController#home']);
Route::get('{locale?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#index']);
Route::get('{locale?}/{template?}/{page}', ['uses' => '\App\Http\Controllers\loadViewController#detail']);
});
which obviously did not work
Also the frontend routes should not have something like /website, they should all start with /
My question is: How can i load the backend and frontend routes separately without interfering when called, even if they have the same url length in terms of parameters, keep in mind that the admin routes always start with /admin or /api.
Note: i can't put the backend routes before the frontend routes
Thanks in advance!
If you want to you could put a constraint on the locale route parameter:
Route::pattern('locale', '^(?!(api|admin)$)(\w*)');
You can put this in the boot method of you RouteServiceProvider and it will now not allow the locale route parameter to match for 'api' or 'admin'.
You can register seperate routes in RouteServiceProvider. Following is how you can do it.
Inside RouteServiceProvider.php do:
public function map()
{
$this->mapFrontendRoutes();
$this->mapAdminRoutes();
}
Definition of mapFrontendRoutes():
protected function mapFrontendRoutes()
{
Route::prefix('{locales?}')
->middleware('frontend')
->namespace($this->namespace.'\Frontend')
->group(base_path('routes/frontend.php'));
}
Definition of mapAdminRoutes():
protected function mapAdminRoutes()
{
Route::prefix('admin')
->middleware('admin')
->namespace($this->namespace.'\Admin')
->group(base_path('routes/admin.php'));
}
I personally find this very useful, helps to declare interference free and logical routes. Open to feedback.
The simple way is to group both url's as separate groups. Example as follows :
Route::group(['prefix' => 'admin', 'as' => 'admin'], function () {
Route::post('/dashboard', 'AdminController#dashboard');
});
Route::group(['prefix' => 'home', 'as' => 'home'], function () {
Route::get('/record/{id}', 'HomeController#getRecord');
});
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.
I'm using this package in my project and there have default package routes.
Like this:
I want use this route in my controller. I'm trying to use with name but it did not work this way.
Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
Voyager::routes();
});
And
Route::group(['prefix' => 'admin'], function () {
Voyager::routes();
})->name('admin');
I'm trying to use like this:
I want to give access like this, as if I'm trying to access 'admin' route then I could access all routes under these route group. I don't know how I will do that?
Please help me.
You cannot redirect to route with name admin. because such route doesn't exist.
When you use:
Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
Voyager::routes();
});
it means all routes created by Voager::routes() will have name starting with admin. but it doesn't mean admin. route exist.
So I assume you should instead use rather admin.voyager.dashboard instead, so you should rather use:
return redirect()->route('admin.voyager.dashboard');
instead of:
return redirect()->route('admin.');
I was reading laravel 5.1 documentation. I didn't understand how laravel route group working and what's the difference between following route groups.
Route Groups & Named Routes
If you are using route groups, you may specify an as keyword in the route group attribute array, allowing you to set a common route name prefix for all routes within the group:
Route::group(['as' => 'admin::'], function () {
Route::get('dashboard', ['as' => 'dashboard', function () {
// Route named "admin::dashboard"
}]);
});
Middleware
To assign middleware to all routes within a group, you may use the middleware key in the group attribute array. Middleware will be executed in the order you define this array:
Route::group(['middleware' => 'auth'], function () {
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
Namespaces
Another common use-case for route groups is assigning the same PHP namespace to a group of controllers. You may use the namespace parameter in your group attribute array to specify the namespace for all controllers within the group:
Route::group(['namespace' => 'Admin'], function()
{
// Controllers Within The "App\Http\Controllers\Admin" Namespace
Route::group(['namespace' => 'User'], function()
{
// Controllers Within The "App\Http\Controllers\Admin\User" Namespace
});
});
Sub-Domain Routing
Route groups may also be used to route wildcard sub-domains. Sub-domains may be assigned route parameters just like route URIs, allowing you to capture a portion of the sub-domain for usage in your route or controller. The sub-domain may be specified using the domain key on the group attribute array:
Route::group(['domain' => '{account}.myapp.com'], function () {
Route::get('user/{id}', function ($account, $id) {
//
});
});
Route Prefixes
The prefix group array attribute may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with admin:
Route::group(['prefix' => 'admin'], function () {
Route::get('users', function () {
// Matches The "/admin/users" URL
});
});
You may also use the prefix parameter to specify common parameters for your grouped routes:
Route::group(['prefix' => 'accounts/{account_id}'], function () {
Route::get('detail', function ($account_id) {
// Matches The accounts/{account_id}/detail URL
});
});
Ref: http://laravel.com/docs/5.1/routing
Route groups allow you to group together routes that share common attributes without having to redefine said attributes for each route.
Example
As an example lets use the namespace array attribute.
Say we have a controller called NewsController that contains all the Admin logic for your apps news section. You may place this file within the 'App/Http/Controllers/Admin` directory.
Laravel 5 follows PSR-4 autoloading conventions, so the application expcets the namespace to be identical to the path of the file, so our class might look something like this:
<?php
namespace App\Http\Controllers\Admin;
class NewsController
{
}
We could write a route to this class like so:
Route::get('admin/news', [
'uses' => 'Admin\NewsController#index'
]);
Note: Laravel automatically assumes all your controllers will be in the App/Http/Controllers directory so we can leave this out of any controller declarations in the routes file.
The above should work fine, but maybe you also have a dozen or so other class files that deal with Admin logic all within the same namespace. We can use the namespace option to group these together.
Route::group(['namespace' => 'Admin'], function()
{
Route::get('admin/news', [
'uses' => 'NewsController#index'
]);
Route::get('admin/users', [
'uses' => 'UserController#index'
]);
...
});
Notice how I no longer define the Admin namespace for the controller for each route.
The same process can be applied to middleware, subdomains, and url prefixes.
Further Example
Lets take the first example and build on it. As you can see from the above route declarations all our admin routes share a common url prefix.
http://example.com/admin/news
http://example.com/admin/users
We can use the prefix array attribute to define the common url for our routes. In our case this is admin.
Our updated Route declarations would look like so.
Route::group(['namespace' => 'Admin', 'prefix' => 'admin'], function()
{
Route::get('news', [
'uses' => 'NewsController#index'
]);
Route::get('users', [
'uses' => 'UserController#index'
]);
...
});
Your probably wondering why would this be useful? Well imagine you have developed a large application with tens if not hundreds of routes. Then one day your boss comes to you and says "Hey Mr. tester, we need to change the admin url from /admin to /cms, how long will this take?".
If you've declared all your routes using groups with the prefix array attribute like above, this is going to be an easy and painless process for you.
In my Laravel app I have a resource route where I want to control access to individual routes based on a filter. I do this by declaring the resource with only the "view" routes and then declaring it again with only the "edit/create" routes in a nested filtered group. The filter is a custom one that check the logged-in user's capabilities.
My routes looks like this:
Route::group(['before' => 'auth'], function()
{
$edit_routes = ['create', 'store', 'destroy', 'edit', 'update'];
Route::resource('things', 'ThingsController', ['except' => $edit_routes]);
// We'll filter the routes that involve editing resources
Route::group(['before' => 'edit_resource'], function() use ($edit_routes)
{
Route::resource('things', 'ThingsController', ['only' => $edit_routes]);
});
}
Is this correct? It seems not to work, although no errors are thrown. When I visit a route in the nested filter (e.g. things/create) I just get a blank page.
Is there a better way of achieving this?
Is this correct?
No
Is there a better way of achieving this?
Yes. Here is a great blog post by Phil Sturgeon that explains why you should just define each route manually.
If you really want to continue using the Resource Controller, you can apply the edit_resource inside the controller constructor like this:
Route::resource('things', 'ThingsController', ['before' => 'auth']);
Then in your resource controller
public function __construct()
{
$this->beforeFilter('edit_resource', array('only' => ['create', 'store', 'destroy', 'edit', 'update']);
}