Laravel 7 - Use Middleware and except in route file - php

I use Laravel 7 for an API project, I have created a JWT Middleware, and I want to apply it to all my routes, except 2 of them.
For now I have in my routes/api.php :
Route::prefix('v1')->group(function () {
Route::get('ping', 'Api\Ping\PingController#ping');
// auth routes
Route::group(['prefix' => 'login/'], function () {
Route::post('login', 'Api\Auth\AuthController#login');
Route::group(['middleware' => 'jwt:api'], function() {
Route::get('me', 'Api\Auth\AuthController#me');
Route::post('refreshToken', 'Api\Auth\AuthController#refresh');
Route::post('logout', 'Api\Auth\AuthController#logout');
});
});
Route::group(['middleware' => 'jwt:api'], function() {
Route::resource('users', 'Api\User\UserController');
// my other routes protected .....
I don't like this approach because I need to copy the middleware.
I tried this approach :
Route::group(
[
'middleware' => ['jwt:api', ['except' => 'login/login']],
'prefix' => 'v1/',
], function() {
But I have this error :
Illegal offset type in isset or empty
Is it possible ? I want to group everything in my route file.

Possible solutions:
You can pass additional parameters to middleware via dots and check in middleware to do not use passed routes
Also, you can overwrite middleware and add some property\constant with array of excepts, like in csrf middleware
Implement ability in Laravel core to pass except array as in your exmaple and make a PR to framework github
Left it as you have done

Related

Load backend and frontend routes separately without interfering

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');
});

How to set name in route group in laravel 5.5?

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.');

Restricting routes with auth middleware group in laravel 5.2

I'm trying to prevent people from accessing the /dashboard route unless they're authenticated(logged in). I looked at the laravel docs and here's what I thought I was supposed to do to accomplish this.
Route::group(['middleware' => 'auth'], function (){
Route::get('/dashboard', [
'uses' => 'UserController#getDashboard',
'as' => 'dashboard'
]);
});
You don't need to add that extra middleware in the route. Just use the group and you'll be fine. You can see here: https://laravel.com/docs/5.1/routing#route-groups
Route::group(['middleware' => 'auth'], function () {
// User needs to be authenticated to enter here.
Route::get('/', function () {
// Uses Auth Middleware
});
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});

Multi auth for laravel 5.2 use middleware

I want to use multi authenticate in Laravel 5.2. But I found a strange problem.
Here is my code in route.php.
However I can not get $errors in the login.blade.php, it just returns null.
<?php
Route::group(['middleware' => ['web'], 'namespace' => 'Admin', 'prefix' => 'admin'], function () {
Route::auth();
});
?>
But when I remove the web middleware, it works.
<?php
Route::group(`enter code here`['namespace' => 'Admin', 'prefix' => 'admin'], function () {
Route::auth();
});
?>
I don't know why. My understanding is that when I want to use the session, I must use the web middleware.
Because on Laravel 5.2 the web middleware is automatically applied, your routes in routes.php are grouped with prefix App\Http\Controllers and web middleware. You can find this definition on mapWebRoutes() method of the RouteServiceProdiver.php.

Laravel 5.2.29 session::flash lost instantly

I created a new laravel project and laravel flash seems to not be working as i want. The moment I return to a route the flash is gone. I have controller method that does absolutly nothing but flash and return to a route.
Like so
public function activateContract(Request $request ){
return redirect()->to('test')->with('status', 'test');
}
My routes file
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/', function(){
return redirect()->intended(route('contract.index'));
});
Route::group(['middleware' => 'auth'], function () {
Route::group(['prefix' => 'contract'], function(){
Route::get('', ['as' => 'contract.index' , 'uses' => 'User\ContractController#index']);
Route::post('', ['as' => 'contract.index' , 'uses' => 'User\ContractController#activateContract']);
Route::get('mijn', ['as' => 'user.contract.index' , 'uses' => 'User\ContractController#userContracts']);
});
});
Route::get('test', function(){
dd(session('status'));
});
c});
Here is the ouput of the die dump in the test route witch magicaly lost the flash message.
null
You need to send the message with the redirect like so:
return redirect()->to('test')->with('status', 'test');
And then you can access it with the session helper function:
session('status');
docs
Edit: Place your Route::get('test') into your group with middleware 'web'.
See more about HTTP Middleware here
Laravel 5.2 changed middleware document as :Keep in mind, the web middleware group is automatically applied to your default routes.php file by the RouteServiceProvider.
It means that if you keep a route in another ['middleware' => 'web'], the data set by session()->flash() would be lost by executed web middleware twice.
It is also the answer someone asked why web executed twice.
Laravel 5.2 : Web middleware is applied twice

Categories