Laravel 5: Handling Dynamic and Static routes - laravel-5

Is there a way in Laravel5 where I could define routes that handles dynamic routes without conflicting with current static routes? Something similar below:
// Dynamic routes
Route::get('{permalink}', function($permalink) {
//look for matching username on the table (bind perhaps?)
});
// Static routes
Route::get('home', 'HomeController#index');
Route::get('products', 'ProductController#index');
Any ideas, guys? Thanks.

Static and dynamic routes shouldn't conflict with each other. Just put static routes higher than dynamic ones.

Related

Laravel Routing - 404

I tried different routes but I am getting 404 on show,edit,store.
Auth::routes();
Route::get('/', 'IndexController#index')->name('index')->middleware('user');
Route::get('/user/profile', 'HomeController#index')->name('user')->middleware('user');
Route::get('/{product}/show', 'IndexController#show')->name('product')->middleware('user');
Route::prefix('cart')->group(function () {
Route::get('/', 'IndexController#cart')->name('cart')->middleware('auth');
Route::get('/{product}/add', 'IndexController#cartAdd')->name('cartAdd')->middleware('auth');
});
Route::prefix('dashboard')->group(function () {
Route::get('', 'AdminController#index')->name('admin')->middleware('admin');
Route::get('products', 'ProductController#index')->name('productIndex')->middleware('admin');
Route::get('products/create', 'ProductController#create')->name('productCreate')->middleware('admin');
Route::get('products/{product}', 'ProductController#show')->name('productShow')->middleware('admin');
Route::put('products/{product}', 'ProductController#update')->name('productUpdate')->middleware('admin');
Route::post('products', 'ProductController#store')->name('productStore')->middleware('admin');
Route::get('products/{product}/edit', 'ProductController#edit')->name('productEdit')->middleware('admin');
Route::post('products/{product}', 'ProductController#destroy')->name('productDestroy')->middleware('admin');
});
I'm trying to fix the routes by rearranging but didn't have any luck so far.
Route::get('/{product}/show', 'IndexController#show')->name('product')->middleware('user');
Move this route at the end. Using a dynamic value that soon in a route without any prefix is not the best way to go by the way. Maybe you can prefix it with something static.
Run php artisan optimize before testing it, to reconfig cache and routes.
It seems like it is because of the route key name here
public function getRouteKeyName()
{
return 'prod_name';
}
after deleting it all routes are working again.

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

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.

Side By Side Static Routes & Wild Card Routes In Laravel

I have a use case for a Laravel website I am working on to have some static routes sitting at the exact same level as the main wild card route.
EG:
Route: /store/cart Static Route
Route: /store/checkout Static Route
Route: /store/* Dynamic Route
Route: /store// Dynamic Route
Route: /* Dynamic Route
Been trying to figure out how to implement this routing structure in Laravel and while the static routing rules work fine as soon as I add the wild card routes I wind up with the wild card route trying to catch the static routes as well.
How would I be able to add routing rules to support this?
change the conflicting routes to non conflicting.
Route: /store/cart Static Route => this is ok
Route: /store/checkout Static Route => this is ok
Route: /store/* Dynamic Route => /store/id/{id}
Route: /store// Dynamic Route => /store
Route: /* Dynamic Route => remove this and be specific by having more routes for the needs
Us global constraint
Route::pattern('all','.*');
Then define your routes in order
Route::('store/cart', function () {});
Route::('store/checkout', function () {});
Route::('store', function () {});
Route::('store/{all}', function ($all) {});
Route::('{all}', function ($all) {});
Managed to get it working.
The first step was to use global constraint route patterns per #Aboalnaga...
Route::pattern('variableName','.*');
Each variable was defined with this route pattern to make it a wild card pattern.
The next step was to ensure route ordering. It appears as though when handling routing Laravel will work its way through the route list in order. As soon as it finds the first matching route it will stop there and run that route. So in order to handle a route chain in the form of domain.com/store/cat-1/productwhere the request could be for domain.com, domain.com/store, domain.com/store/cat-1, domain.com/store/cat-1/product, or domain.com/some-content-page-from-database the route needed to be defined as...
Route::get('/store/shopping-cart', 'onlineStore#showCart');
Route::get('/store/checkout', 'onlineStore#showCheckout');
Route::get('/store/checkout/payment', 'onlineStore#showPayment');
Route::get('/store/checkout/success', 'onlineStore#showPaymentSuccess');
Route::get('/store/checkout/error', 'onlineStore#showPaymentError');
Route::get('/store/{category}', 'onlineStore#showCategory');
Route::get('/store/{category}/{product}', 'onlineStore#showProductDetails');
Route::get('{article}', 'articles#showArticle');
By defining the routes in order and having the variable route defined as the last route at that level the variable route will only be triggered if the preceding routes don't match.

Laravel routing hide path

I have a route like this
http://localhost:8000/produk/slug-product
I want to my url like this, remove produk in url
http://localhost:8000/slug-product
What should I do ?
Do not use .htaccess to handle this. Define route for slugs without any segment at the end of the routes list in your app:
Route::get('{slug}', 'FrontController#getBySlug');
So, all requests which are not related to any of the routes, will go to the getBySlug method:
public function getBySlug($slug)
{
$data = Model::findBySlug($slug);
....
}

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.

Resources