Laravel Route::current() returns null - php

I am trying to use the current route in middleware in Laravel 5.7 using the following line of code:
$route = Route::current();
But I get a null value for $route. Any ideas?

The route couldn't be available yet because the router hasn't been yet called. That's depends on what middlewares are called before your middleware.
I think that, in a before middleware, you can try with: $route = $request->path(); just to be sure and not depending on the Router being booted or not.

You just want to change where your middleware is registered in app/Http/Kernel.php if you need access to the Route facade.
I'm betting that your middleware is in the protected $middleware array. It should be in one of your $middlewareGroups usually web or api. Or if you need it for a specific route you can add it to the $routeMiddleware array.
For example, I wanted to access Route from within my HandleInertiaRequests middleware so I had to move to $middlewareGroups like shown in this screenshot:

Related

Laravel 7.1 - URL::defaults() not working in high priority middleware

I am using subdomain routing heavily within my project, as it's a multi-tenant application with each tenant having their own subdomain.
As a result, all of my routes are wrapped in:
Route::domain('{tenant}.'.config('app.base_url'))->group(function () {
// My routes here!
});
To use the route() helper within my code, I need to pass it all of the route parameters associated with it. Every single route has tenant associated with it, so I constantly found myself repeating code and writing route('my-route-name', ['tenant' => $request->route('tenant')]);
I've created a middleware with the following code in it:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use URL;
class SetTenantFromRequest
{
public function handle(Request $request, Closure $next)
{
list($subdomain) = explode('.', $request->getHost(), 2);
URL::defaults(['tenant' => $subdomain]);
return $next($request);
}
}
And placed it in the HTTP Kernel.php file like so:
protected $middleware = [
TrustProxies::class,
CheckForMaintenanceMode::class,
ValidatePostSize::class,
TrimStrings::class,
ConvertEmptyStringsToNull::class,
WebHeaders::class,
SetLanguage::class,
SetTenantFromRequest::class,
];
// Removed for brevity...
protected $middlewarePriority = [
StartSession::class,
ShareErrorsFromSession::class,
SetTenantFromRequest::class,
Authenticate::class,
ThrottleRequests::class,
AuthenticateSession::class,
SubstituteBindings::class,
Authorize::class,
];
I had to add it to the $middlewarePriority array as it needs to run before the Authenticate middleware. Since Authenticate calls return route('login');, I need that URL parameter available beforehand.
Now with doing all of this, I still get the following error thrown from the Authenticate middleware: Missing required parameters for [Route: login] [URI: login].
If I run ddd(URL::getDefaultParameters()); within the Authenticate middleware, it prints an empty array. However if I run the same ddd(...) within the SetTenantFromRequest middleware, it shows the tenant in there as I expect it to be.
Does anyone have an idea on how I can solve this problem?
Moving this from the global middleware stack to the web middleware stack alleviates the issue.
This forces me to add the tenant parameter to the route(...) call within my Authenticate middleware, but it does allow me to forgo it everywhere else.

Laravel override group middleware

How to override group middleware? What i want to achieve is to add other throttle limit for register/login routes.
My current throttle is set in kernel.
'api' => [
'throttle:40,1',
'bindings',
],
I want to set new throttle limit for login/register routes.
This is how i did it.
Route::post('login', 'Api\UserController#login')->middleware('throttle:15,3')->name('user.login');
Route::post('register', 'Api\UserController#register')->middleware('throttle:15,3')->name('user.register');
When i run php artisan route:list it says that this middleware api,throttle:15,3 is applied to this route.
The problem is when i run login request, response header says
X-RateLimit-Limit 40
X-RateLimit-Remaining 38
So as far as i see my new middleware is not applied. But my throttle requests are counted twice. How can i apply different middleware for throttle on login/register routes and override the old one ?
Old topic, but its the first i found; time for an updated answer.
I've had this problem in the past as well. My solution back then was to add the middleware in the constructor of the controllers. I dislike it but it works.
I'm currently using Laravel 8 with a new project and found that the following solution works:
Set the default middleware in kernel.php
'api' => [
'throttle:40,1',
'bindings',
],
Remove the middleware throttle:40,1 from the specific route, and add the correct middleware throttle:15,3:
Route::post('login', 'Api\UserController#login')->withoutMiddleware('throttle:40,1')->middleware('throttle:15,3')->name('user.login');
If you do not remove the middleware, it will run the throttle middleware twice per request.
I also played around with $this->middleware( 'throttle:40,1' )->except( ['login'] ) in the constructor of Api\UserController, however that does not give the required result; it will just add the middleware for all but one method, it does not overwrite.
Had this same question and just did some research. It doesn't appear that there is a way to overwrite the middleware configuration.
I, too, see that my middleware has updated in route:list but when resolving the middleware, it always uses a merged set of rules and so that initial api rule will end up overriding anything that defines something else over that.
You have a couple of options:
Remove the throttle rule from the Kernel api middleware definition and then use a Route::group() to re-add that specific rule to the rest of the routes. Then, in the same file, you can create a new Route::group() which defines the custom throttle config.
Route::group(['middleware' => 'throttle:120,1'], function () {
...
});
Route::group(['middleware' => 'throttle:15,3'], function () {
...
});
Create a custom api-auth.php file which is wrapped in a custom middleware group that you define just like the default api middleware. (You'll need to add another call in your RouteServiceProvider to load it like this:
public function map() {
...
$this->mapCustomAuthRoutes();
}
protected function mapCustomAuthRoutes()
{
Route::middleware(['throttle:15,3', 'bindings'])
->namespace($this->namespace)
->as('api.')
->group(base_path('routes/api-auth.php'));
}

How can i make sure middleware is run before another

Hi have a middleware that i must ensure is run after the auth middleware. How can i guarantee that the auth middleware is processed before mine? Is this even possible?
Thanks in advance.
from the laravel 5.4 documentation:
Route::get('/', function () {
//
})->middleware('first', 'second');
First and second must be route middleware, if you look in app/Http/Kernel.php you can find them.
Your middlware will be run after, Auth middleware have a higher priority. See variable $middlewarePriority of your Kernel base class (Illuminate\Foundation\Http\Kernel).
First middleware is StartSession and this is what we want.
If you want, you can modify this variable to run one of your middleware before Auth.

Silex 2: Get route in before middleware

I have defined a before middleware in my Silex 2.0 application, and I would like to know what route is being processed.
For instance:
If I am loading the URL /hello/foo, I want obtain the string /hello/foo in some variable from my before middleware.
If I am loading the URL /en/hello/foo, I want obtain the string /en/hello/foo in some variable from my before middleware.
$request->getPathInfo() should work

Accessing Auth in Exceptions\Handler.php

I'm trying to access the Auth class from within the render method of the App\Exceptions\Handler class (app/Exceptions/Handler.php) to determine if the User is currently logged in, using the Auth::check() method.
This worked fine in 5.1, but I've upgraded to 5.2 and it no longer works.
To debug this, I've been printing Auth::user() to the logs (which returns NULL), then returning a redirect() to another view.
Then from the view/controller the redirect goes to, printing the same Auth::user() to the logs, which works as expected and returns the logged in user.
So it seems there's no problem accessing the Auth class or the user() method from within the Exceptions\Handler class, it's just that it returns NULL for some reason, whereas other parts of the app return the User..
Thanks for any info on this!
This happens because StartSession middleware is inside $middlewareGroups (the application's route middleware groups), so you don't have access to the authenticated user because the middlewares that initialize your session starts later in the lifecycle than the ExceptionHandler.
In app\Kernel.php file, move this line:
\Illuminate\Session\Middleware\StartSession::class,
from $middlewareGroups to the global stack $middleware. These middleware are run during every request to your application so, after this, Auth::user() will works.
WARNING: With this solution you will not be able to use the cookie session driver. Works well with file and others.
UPDATE:
If you still need to use StartSession inside global stack $middleware and also you need cookie session driver, you must move three middlewares from $middlewareGroup to $middleware in the next order:
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class
After some research, it seems the 404 errors are the only culprits. If it's a 500 error, Auth::user() works. So, in my routes.php file, I added this at the bottom
Route::any('{page}', 'ErrorController#Error404')->where('page', '(.*)');
to catch any unhandled endpoints. In that ErrorController#Error404 method, I can access the Auth class. So whatever logic you have in your App\Exceptions\Handler, you can duplicate it in the ErrorController#Error404 method. (Or better: extract it to some other entity that can be referenced in both places.)

Categories