Is there a different way I should be naming my Laravel routes? - laravel

I currently have these routes in my API:
Route::group(['prefix' => 'v1'], function() {
Route::get('feed', [FeedController::class, 'index']);
Route::get('feed/{page}', [FeedController::class, 'index']);
});
I wanted to create another route that looked like this, only protected by some middleware:
Route::group(['prefix' => 'v1', 'middleware' => ['jwt.verify']], function() {
Route::get('feed/following', [FeedController::class, 'following']);
Route::get('feed/following/{page}', [FeedController::class, 'following']);
});
However, it appears that the v1/feed/following route is actually being routed to the v1/feed/{page} route.
Is there a way to fix this without my route names?

You can introduce another group in your v1 Api path and set feed/following before feed/{page}:
Route::group(['prefix' => 'v1'], function() {
Route::group(function() {
Route::get('feed/following', [FeedController::class, 'following']);
Route::get('feed/following/{page}', [FeedController::class, 'following']);
})->middleware('jwt.verify');
Route::get('feed', [FeedController::class, 'index']);
Route::get('feed/{page}', [FeedController::class, 'show']);
});

The rule for 'feed/{page}' will also match 'feed/following', you will wind up with page = following
Maybe create the route for 'feed/following' before the route for 'feed/{page}'

Related

How can I add one route to 2 different middleware (auth) without having to duplicate it in Laravel?

I know this is a basic laravel question but don't know how do it. How can I add one route to 2 different middleware (auth) without having to duplicate it?
// =admin
Route::group(['middleware' => ['auth']], function() {
Route::get('/dashboard', 'App\Http\Controllers\DashboardController#index')->name('dashboard');
Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
});
// =cashier
Route::group(['middleware' => ['auth', 'role:cashier']], function() {
Route::get('/dashboard/cashier/profile', 'App\Http\Controllers\DashboardController#showCashierProfile')->name('dashboard.cashier.profile');
Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
});
I have this route and I don't want to repeat calling this per auth middleware: Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
You can't have two routes with the same url.
Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
This route is inside both groups and since the url they will produce will be the same, only the second will remain.
Route::group(['middleware' => ['auth']], function() {
Route::get('/dashboard', 'App\Http\Controllers\DashboardController#index')->name('dashboard');
//Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
// this route will be ignored because the other one has the same url
});
Route::group(['middleware' => ['auth', 'role:cashier']], function() {
Route::get('/dashboard/cashier/profile', 'App\Http\Controllers\DashboardController#showCashierProfile')->name('dashboard.cashier.profile');
Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
});
If you want Laravel to handle these two routes differently, you have to add a prefix:
Route::group(['prefix' => 'admin', 'as' => 'admin.', 'middleware' => ['auth']], function() {
Route::get('/dashboard', 'App\Http\Controllers\DashboardController#index')->name('dashboard');
//Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
// this route will be ignored because the other one has the same url
});
Route::group(['prefix' => 'cashier', 'as' => 'cashier.', 'middleware' => ['auth', 'role:cashier']], function() {
Route::get('/dashboard/cashier/profile', 'App\Http\Controllers\DashboardController#showCashierProfile')->name('dashboard.cashier.profile');
Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
});
This way, when the url will be prefixed with admin, the first route will be called (without the role:cashier middleware).
Notice that I added a route name prefix ('as' => 'admin.' / 'as' => 'cashier.') so you can call each one by name, using:
route('admin.make-a-sale.index'); // admin/make-a-sale
//or
route('cashier.make-a-sale.index'); // cashier/make-a-sale
Just to add, if someone wants to fix the Laravel blade error below whenever you clear your browser cache and was automatically logout:
*Attempt to read property "name" ...*
You need to add all your routes inside the:
Route::group(['middleware' => ['auth']], function () {
// routes here
});
This will redirect you to login once that happens.

Is there another, more efficient way to nest prefix and name prefix in laravel 8 that doesn't need to use so many groups?

I saw a good way to nest prefix and name prefix, but this is so verbose. In addition, for few requests, it's acceptable, but when there is a lot of requests, creating groups can be problematic. This is a toy example.
Route::prefix('auth')->group(function () {
Route::name('auth.')->group(function () {
Route::get('login', [MainController::class, 'login'])->name('login');
Route::get('register', [MainController::class, 'register'])->name('register');
});
});
I try this, but it failed.
Route::name('auth.')->group(['prefix'=>'auth'], function () {
Route::get('login', [MainController::class, 'login'])->name('login');
Route::get('register', [MainController::class, 'register'])->name('register');
});
Is there another, more efficient way to nest prefix and name prefix in laravel 8 that doesn't need to use so many groups?
I'm using the Laravel 8 Documentation's route group section.
You can combine your prefixes, names and middlewares in the group function which will tidy things up somewhat:
Route::group(['prefix' => 'auth', 'as' => 'auth.'], function () {
Route::get('login', [MainController::class, 'login'])->name('login');
Route::get('register', [MainController::class, 'register'])->name('register')
});
If you want to specify middleware on the group, just add it to the array in the first argument for the group function.
Route::group(['prefix' => 'auth', 'as' => 'auth.', 'middleware' => [...]], function () {
...
});

Laravel route duplication

I am working on building my first API. Currently, I have the following.
Route::group(['namespace' => 'Api', 'prefix' => 'api'], function () {
Route::get('/', 'AuthController#showLogin');
Route::post('login', 'AuthController#login');
Route::post('register', 'AuthController#register');
Route::group(['middleware' => ['jwt.auth']], function () {
Route::resource('account', 'AccountController');
Route::resource('notifications', 'NotificationController');
Route::resource('contacts', 'ContactController');
});
});
How can I make it that all requests to /api/v1 go to the API?
For future use, when I upgrade/add new features to an API going to /api, it's always the latest version. However, if a user goes to api/v1/, they use only version 1 of the API.

Multi domain routing in Laravel 5.2

I have setup multi-domain routing in my laravel 5.2 app. What I want to achieve is if a user hits, membership.app, he should be served different homepage as compared to user who hits, erp.app domain.
Route::pattern('erp', 'erp.app|erp.domain.com');
Route::pattern('membership', 'membership.app|membership.domain.com');
Route::group(['middleware' => ['web', 'auth'], 'domain' => '{erp}'], function() {
Route::get('/', 'HomeController#getIndex');
Route::controller('members', 'MembersController');
Route::controller('users', 'UsersController');
Route::controller('settings', 'SettingsController');
});
Route::group(['middleware' => 'web', 'domain' => '{erp}'], function () {
Route::controller('auth', 'Auth\AuthController');
});
Route::group(['middleware' => 'web', 'domain' => '{membership}'], function () {
Route::controller('/', 'BecomeMemberController');
});
Route::group(['middleware' => 'web'], function () {
Route::controller('ajax', 'AjaxController');
});
I tried this setup, but it breaks the code with first param in each controller method being the url instead of intended value.
Suppose I have a method hello in members controller.
public function hello($param1, $param2)
{
....
}
If I access erp.app/members/hello/1/2 url and try to print out $param1 of controller method, it returns erp.app instead of intended 1 in this case.
Please help.
I don't know why aren't you seperating the routes to different controllers as you say the output will be quite different...
A quick example of to use that:
Route::group(['domain' => '{type}.myapp.com'], function () {
Route::get('members/hello/{id1}/{id2}', function ($type, $id1, $id2) {
// when you enter --> members.myapp.com/hello/12/45
var_dump($type); //memebers
var_dump($id1); //12
var_dump($id2); //45
});
});

route group prefixed for admin

How do you have a the start of the route to have admin at the begining of the route like '/admin/attributes/1/edit in the routes group collection instead of just /attributes/1/edit
Route::group(array('before' => 'Admin'), function() {
Route::resource('attributes', 'AttributesController');
Route::resource('brands', 'BrandsController');
Route::resource('products', 'ProductsController');
Route::resource('tags', 'TagsController');
Route::resource('roles', 'RolesController');
Route::resource('suppliers', 'SuppliersController');
});
You need to use a prefix
Route::group(array('prefix' => 'admin'), function()
{
// routes here
});
See Laravel Documentation

Resources