Laravel: is there a way to organize routes into hierarchical tree - laravel

My user model has different roles which have inheritance relationship between each other, for example: admin is a child of superadmin.
I am trying to drop this relationship on my routes in order to organize them and avoid routes like:
Route::group(['namespace' => 'Admin\MultiDispatch', 'middleware' => ['auth.jwt:superadmin|admin']], function () {
});
I moved every role routes into files Admin.php & SuperAdmin.php
and required the files in routes.php:
/*ADMIN ROLES*/
Route::group(['middleware' => ['auth.jwt:admin']], function () {
require base_path('routes/roles/Admin.php');
});
/*SUPERADMIN ROLES */
Route::group(['middleware' => ['auth.jwt:superadmin']], function () {
require base_path('routes/roles/SuperAdmin.php');
});
and in superadmin.php I required Admin.php file again as superadmin should extend all admin routes:
<?php
require base_path('routes/roles/Admin.php');
But it seems that the endpoints that exist in Admin.php are only available to superadmin access.
is there another way to implement the inheritance concept in routes file except mention superadmin in admin routes?
/*ADMIN ROLES*/
Route::group(['middleware' => ['auth.jwt:admin,superadmin']], function () {
require base_path('routes/roles/Admin.php');
});
especially my tree is long and there are so many roles under admin

Yes you can totally separate them by creating new route files in routes folder then map them.
Create admin.php and superadmin.php routes in your /routes folder.
Go to app/Providers/RouteServiceProvider.php
If you want to have separate controllers for them, create separate Namespaces for them:
public function map()
{
...
$this->mapAdminRoutes();
$this->mapSuperAdminRoutes();
...
}
protected function mapAdminRoutes()
{
Route::prefix('admin')
->middleware(['web', 'auth.jwt:admin'])
->namespace('App\Http\Controllers\Admin')
->name('admin.')
->group(base_path('routes/admin.php'));
}
protected function mapSuperAdminRoutes()
{
Route::middleware('web', 'auth.jwt:superadmin')
->namespace('App\Http\Controllers\SuperAdmin')
->name('superadmin.')
->group(base_path('routes/superadmin.php'));
}
Check the namespace, that means you can put different controllers in different folders, eg. the admin controllers in App\Http\Controllers\Admin, so you can create a folder in app/Http/Controllers called Admin. Then in the controllers you change your namespace to namespace App\Http\Controllers\Admin; then use App\Http\Controllers\Controller; to find the BaseController you are extending from.
prefix: /{prefix}/your-routes-here
name: Naming your route group, eg. route('superadmin.users.add')
namespace: Where your controllers are
group: Where your routes file is
In the route file you can add routes like you would for normal guest/web routes. Just add them one by one or even group them again. But the above will already be grouped by prefix: /admin or /superadmin, and named admin. or superadmin., and middleware attached, and in different folders for conveniency.
Type php artisan route:list in your console/terminal and see the results!
With the above I always separate my /admin or /dashboard from / (guest) routes. Much cleaner this way! :)

Middleware Groups
You can group midleware together in a way that I think will suit your needs;
Route::middleware(['auth.jwt:admin'])->group(function(){
// Routes that need admin middleware access go here
Route::middleware([''auth.jwt:superadmin''])->group(function(){
// Routes that need admin AND superadmin middleware access go here
});
});
That should allow you to just nest middleware groups inside one another to provide a hierarchical list of routes.

Related

How to use web route for auth controller in laravel 8

I wanted to use multi step registration. But got trouble at route. This is my first route.
Route::get('register-step2', [Auth\RegisterStep2Controller::class,'showForm']);
Route::post('register-step2', [Auth\RegisterStep2Controller::class, 'postForm'])
->name('register.step2');
but it got error
Target class [Auth\RegisterStep2Controller] does not exist.
so I change and mix with this code.
Route::group(['middleware' => ['auth']], function() {
Route::resource('roles', RoleController::class);
Route::resource('users', UserController::class);
Route::resource('products', ProductController::class);
Route::get('register-step2', [RegisterStep2Controller::class,'showForm']);
Route::post('register-step2', [RegisterStep2Controller::class, 'postForm'])
->name('register.step2');
But it says that: Target class [RegisterStep2Controller] does not exist.
How to use controller in auth in laravel 8 or 9.
I wanted to use registerstep2 controller in auth folder.
Make changes in your routes/web.php as per below
use App\Http\Controllers\Auth\RegisterStep2Controller;
...
Route::get('register-step2', [RegisterStep2Controller::class,'showForm']);
Route::post('register-step2', [RegisterStep2Controller::class, 'postForm'])->name('register.step2');

Crud Generator with Laravel

Since 2 weeks I work in a projet of devlopment of a application. I must creat many CRUD and it may take many times. Now I want to know if I can use a free crud generator laravel.If yes, which generator?
Need your Help please.
Command:
php artisan make:model User -mrc
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
RESTful Resource Controller documentation
Implicit controller
An Implicit controller is more flexible. You get routed to your controller methods based on the HTTP request type and name. However, you don't have route names defined for you and it will catch all subfolders for the same route.
Route::controller('users', 'UserController');
Would lead you to set up the controller with a sort of RESTful naming scheme:
class UserController extends BaseController {
public function getIndex()
{
// GET request to index
}
public function getShow($id)
{
// get request to 'users/show/{id}'
}
public function postStore()
{
// POST request to 'users/store'
}
}
Implicit Controller documentation
It is good practice to use what you need, as per your preference. I personally don't like the Implicit controllers, because they can be messy, don't provide names and can be confusing when using php artisan routes. I typically use RESTful Resource controllers in combination with explicit routes.
Laravel already provides CRUD operation see: laravel.com/docs/5.8/controllers#resource-controllers
Laravel resource routing assigns the typical "CRUD" routes to a controller with a single line of code. For example, you may wish to create a controller that handles all HTTP requests for "photos" stored by your application. Using the make:controller Artisan command, we can quickly create such a controller:
php artisan make:controller PhotoController --resource
[EDIT 1]
Or you can choose for example: Laravel-Backpack/CRUD which comes with an Admin panel and others things like that.
[EDIT 2]
Also you can refer this Laravel blog to choose a generator:
https://laravel-news.com/13-laravel-admin-panel-generators
[EDIT 3]
Again on Laravel Blog you can see that Laravel is constantly evolving a new Artisan command have been added see:
laravel-news.com/laravel-resources-artisan-command

Route User Role Laravel 5.4

I'm very confused on this situation. I have two routes with on resource name.
Route::resource('product', 'Product\AreaManagerProductController');
Route::resource('product', 'Product\SystemAdminProductController');
I need to make it as one because I have a contextual binding.
$this->app->when(AreaManagerProductController::class)
->needs(ProductInterface::class)
->give(AreaManagerProductRepository::class);
$this->app->when(SystemAdminProductController::class)
->needs(ProductInterface::class)
->give(SystemAdminProductRepository::class);
The contextual binding works fine... but I need to change my route like this.
Route::resource('product_area_manager', 'Product\AreaManagerProductController');
Route::resource('product_system_admin', 'Product\SystemAdminProductController');
I created ProductController and some kind of weird solution.
public function index(){
//Create a conditional statement base on user
return app('App\Http\Controllers\Product\AreaManagerProductController')->index();
}
It may work but it doesn't trigger the middleware... What could be the best practice on this situation. TY
You can have your Route like this
Route::group(['prefix' => 'product', 'namespace' => 'Product', 'middleware' => '<your middleware>'], function() {
Route::resource('area_manager', 'AreaManagerController');
Route::resource('system_admin', 'SystemAdminController');
});
The reason I grouped the route is to reduce redundancy, and the reason i removed Product from the controller name is, as there is a namespace Product already, there is no need of long Class names.
If you wan to access some methods in the AreaManagerController and SystemAdminController just extend the ProductController to these Controllers.
If you want to add some specific middleware for the actions inside these controllers, I have added a middleware clause in the route group which will affect to these controllers, if not needed just remove it.
Hope this helps you.

Workflow of role/permission based content filtering using Entrust Laravel

I am using laravel 5 and added Entrust for roles and permissions.
I don't know how to use the permissions. If I have a permission create-post means what will it do?
create option in the Post controller will be permit? Or we need to assign a permission name to the page?
Please suggest an example. Even I don't know where to check permissions...
The workflow of Entrust is as follows
Create roles
Role::create(['name' => $role]);
e.g admin, reader etc
Create permissions
Permission::create($permission);
e.g can_read_post, can_edit_post, can_delete_post
Assign permissions to roles
$role = Role::where('admin)->first();
$role->perms()->sync($ids); //here the ids are ids of permissons which you want to assign
e.g admin has permissions (can_read_post, ca_edit_post, can_delete_post) and reader has permissions (ca_read_post)
Assign roles to users
You can assign a role to many users.
$user->roles()->attach($roleId);
Filter content based on Role or Permission
The basic setup has been completed. Now you can filter the content of your website using different methods. Here I will discuss a few
Define a filter in filters.php and apply on route
filters.php
Route::filter('admin', function()
{
if(!Entrust::hasRole('Administrator'))
{
return Redirect::to('/');
}
});
routes.php
Route::group(['before' => ['admin']], function(){
//add some routes which will require admin role
//any user which has not admin role will be redirected to home page
}
In your views
#if(Entrust::can('can_edit_post'))
//add some html which will only be visible to users who has such a role which has this permission
#endif
In your controllers/models/repos
Similarly you can filter content in models/controllers/repos etc.
So I guess you have got the basic idea. Now you can use Entrust functions almost anywhere. Hope this helps.
Briefly what we need to done to implement Entrust Laravel Package for role based permission is as below.
Install the package as per per the instructions given in
https://github.com/Zizaco/entrust
After all, done with the above Package(GitHub) like database table creation, Middleware, Controllers and all.
When a user login in the system, then there is an array provided by Auth, that contains all the actions user can (actions ability logged in user can) take.
Let a suppose we have a Controller named as CategoryController as below.
class CategoryController extends Controller
{
public function __construct()
{
$this->middleware('permission:category_index', ['only' => ['index']]);
$this->middleware('permission:category_create', ['only' => ['create', 'store']]);
$this->middleware('permission:category_edit', ['only' => ['edit', 'update']]);
$this->middleware('permission:category_delete', ['only' => ['delete']]);
$this->middleware('permission:category_view', ['only' => ['show']]);
}
}
We generally have 5 actions in a Controller, If we have a single route (called as resource route) in our routers/web.php file for all CRUD actions of single controller.
In this example, suppose we have all these 5 methods. So we also have entry in permission for these in permission table.. like I have
Permission Table
id display_name name
5 Delete Category category_delete
4 Edit Category category_edit
3 Create Category category_create
2 List Category category_index
We just need to add these permission names in our controllers as I have done in the CategoryController, If you use hyphon in permission table's name filed, then use like
$this->middleware('permission:category-create', ['only' => ['create', 'store']]);
Write all permissions in the controller constructor.
that' it!!
It will automatically check the logged-in user ability and according to the database entry in permission_role (relation table of role and permission), It will either show the page or access denied for that user.
Hope this works !!

Laravel - Route::resource vs Route::controller

I read the docs on the Laravel website, Stack Overflow, and Google but still don't understand the difference between Route::resource and Route::controller.
One of the answers said Route::resource was for crud. However, with Route::controller we can accomplish the same thing as with Route::resource and we can specify only the needed actions.
They appear to be like siblings:
Route::controller('post','PostController');
Route::resource('post','PostController');
How we can choose what to use? What is good practice?
RESTful Resource controller
A RESTful resource controller sets up some default routes for you and even names them.
Route::resource('users', 'UsersController');
Gives you these named routes:
Verb Path Action Route Name
GET /users index users.index
GET /users/create create users.create
POST /users store users.store
GET /users/{user} show users.show
GET /users/{user}/edit edit users.edit
PUT|PATCH /users/{user} update users.update
DELETE /users/{user} destroy users.destroy
And you would set up your controller something like this (actions = methods)
class UsersController extends BaseController {
public function index() {}
public function show($id) {}
public function store() {}
}
You can also choose what actions are included or excluded like this:
Route::resource('users', 'UsersController', [
'only' => ['index', 'show']
]);
Route::resource('monkeys', 'MonkeysController', [
'except' => ['edit', 'create']
]);
API Resource controller
Laravel 5.5 added another method for dealing with routes for resource controllers. API Resource Controller acts exactly like shown above, but does not register create and edit routes. It is meant to be used for ease of mapping routes used in RESTful APIs - where you typically do not have any kind of data located in create nor edit methods.
Route::apiResource('users', 'UsersController');
RESTful Resource Controller documentation
Implicit controller
An Implicit controller is more flexible. You get routed to your controller methods based on the HTTP request type and name. However, you don't have route names defined for you and it will catch all subfolders for the same route.
Route::controller('users', 'UserController');
Would lead you to set up the controller with a sort of RESTful naming scheme:
class UserController extends BaseController {
public function getIndex()
{
// GET request to index
}
public function getShow($id)
{
// get request to 'users/show/{id}'
}
public function postStore()
{
// POST request to 'users/store'
}
}
Implicit Controller documentation
It is good practice to use what you need, as per your preference. I personally don't like the Implicit controllers, because they can be messy, don't provide names and can be confusing when using php artisan routes. I typically use RESTful Resource controllers in combination with explicit routes.
For route controller method we have to define only one route. In get or post method we have to define the route separately.
And the resources method is used to creates multiple routes to handle a variety of Restful actions.
Here the Laravel documentation about this.
i'm using Laravel 8 in my project
and in my route file web.php
i add this route
Route::controller(SitesController::class)->group(function() {
Route::get('index', 'index')->name('index');
}
in the Route::controller group we pass controller name we will use
inside the group we define the route we'll use as below syntax
Route::method-used('prefix in the URL', 'function used in the specified controller ')->name(); if the name not used in your code just delete it

Resources