Is there a way to access a custom route parameter, same way as route "name": 'cache'=>true
Route::GET('tools/languages/{page?}', array('uses'=> 'Tools#list_languages', 'as'=>'list_languages', 'cache'=>true));
How to access cache value from Controller?
thanks,
Yes you can get your Route parameter from Middleware.
In your middleware you can get "matched route object" like this :
class MyMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$matchedRouteObject = $request->route();
$next($request);
}
}
See print_r($request->route()) there is a property that named action in this Route object. action property has all parameters of matched Route.
routes/web.php :
Route::get('tools/languages/{page?}', [
'uses' => 'Tools#list_languages',
'middleware' => 'App\Http\Middleware\MyMiddleware',
'cache' => 'value'
]);
app/Http/Middleware/MyMiddleware.php :
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Response;
class MyMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$matchedRouteObject = $this->route();
$deedVariable = $mathedRouteObject->action['cache']; // here you got your variable.
return $next($request);
}
}
Extending #Exprator answer, you could access the parameter in your controller as
public function list_languages(Request $request)
{
$request->route()->getAction()['cache']; // returns true
}
https://laravel.com/api/5.4/Illuminate/Routing/Route.html#method_getAction
Related
I'm using Laravel 5.4 and I'd like to filter the subdomain.
web.php
Route::group(['domain' => '{city}.localhost'], function () {
if ($city does not exist in database) {rediret to localhost};
Route::get('/', 'HomeController#home');
});
What I'd like
If subdomain exists in the database continue. Otherwise redirect to the same address but without a subdomain.
I would suggest using middleware to interrogate the $request URL and redirect accordingly, much like the RedirectIfAuthenticated middleware does.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class CheckSubdomain
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
// check $request->url() here...
if ($notInDatabase) {
return redirect()->route('/somewhere');
}
return $next($request);
}
}
in my website i have a fairly complected category which i have to show in every view (in the client side) so i thought i put the code for creating category in a middleware and pass the result to views
so i've created my middleware but i cant figure out how can i pass its data to my view withouth having to do something in the controllers
i've tried these methods in my middleware
<?php
namespace App\Http\Middleware;
use Closure;
class CtegoryMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->merge(array("all_categories" => "abc"));
$request['all_categories']= 'abc';
return $next($request);
}
}
route :
Route::group(['middleware' => ['category' ]], function () {
Route::get('/', 'HomeController#index');
});
but in my view when i echo all_categories i get
Undefined variable: all_categories
btw i've checked by echoing something , the middleware gets triggered on the request
I think in your use case, using a globally available view variable should suffice.
<?php
namespace App\Http\Middleware;
use Closure;
class CtegoryMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->merge(array("all_categories" => "abc"));
$request['all_categories']= 'abc';
/**
* This variable is available globally on all your views, and sub-views
*/
view()->share('global_all_categories', 'abc');
return $next($request);
}
}
The variable is loaded once (if you do database query, the query will only execute once), and the variable is then stored in the View factory.
My goal is to pass User Context like email or ID into Sentry so I can see which users broke something.
I've configured a piece of Global Middleware to add user context to my Sentry errors. Here is the class:
class AddUserToSentry
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::user())
{
//dd(Auth::user()->email);
app('sentry')->user_context(array(
'email' => Auth::user()->email
));
}
return $next($request);
}
}
In my Handler.php I have:
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* #param \Exception $e
* #return void
*/
public function report(Exception $e)
{
if ($this->shouldReport($e)) {
app('sentry')->captureException($e);
}
parent::report($e);
}
What am I missing to make this work? All I get for user context is the IP address, which is not very helpful in my case.
Thank you very much,
Josh
Here is a complete example, the source is from the official Sentry documentation. To avoid having to add use Auth; you can simply use the auth() helper function.
namespace App\Http\Middleware;
use Closure;
class SentryContext
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
*
* #return mixed
*/
public function handle($request, Closure $next)
{
if (app()->bound('sentry')) {
/** #var \Raven_Client $sentry */
$sentry = app('sentry');
// Add user context
if (auth()->check()) {
$sentry->user_context(['id' => auth()->user()->id, 'email' => auth()->user()->email]);
}
// Add tags context
// $sentry->tags_context(['foo' => 'bar']);
}
return $next($request);
}
}
You need to provide access to Laravel's Auth Facade in your controller like so:
Use Auth;
I was facing an issue these days when I tried to pass arguments from my router to my middleware, to check if the authenticated user has the permissions to access that route.
How can I pass an argument from routes to the middleware?
I tried to do it and it works very well for me:
In my routes files:
Route::group(['prefix' => 'agenda', 'middleware' => 'auth', 'permissions' => 'user.create|user.delete'], function() {
//my routes here...
});
and inside the middleware:
class AuthMiddleware {
private $r;
private $guard;
public function __construct(Router $r, Guard $g)
{
$this->r = $r;
$this->guard = $g;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$route = $this->r->getCurrentRoute();
$action = $route->getAction(); //$action['permissions'] is the string received from the routes file.
}
I'm having a trouble with creating the "owner" middleware.
For example, I have a Articles and Usermodel associated with user_id key.
I want to add the "owner" middleware to the ArticlesController, so the only owner of that article can edit, update and delete it.
I've been searching for this issue for a while, but never found the code, which would work.
Some of them tried to make it work with Form Requests, but I'm interested in using Middleware.
Create middleware:
php artisan make:middleware OwnerMiddleware
namespace App\Http\Middleware;
use App\Article;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class OwnerMiddleware
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$articleId = $request->segments()[1];
$article = Article::findOrFail($articleId);
if ($article->user_id !== $this->auth->getUser()->id) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
Add it to app\Http\Kernel.php:
protected $routeMiddleware = [
'owner' => 'App\Http\Middleware\OwnerMiddleware',
];
Use middleware in your routes:
Route::group(['middleware' => ['owner']], function() {
// your route
});
Alternatively you could use route and middleware parameters, it has some advantages:
Even if the request structure changes your middleware would still work
The middleware is reusable for differents resources
You can use it inside controllers
Here’s the middleware (app/Http/Middleware/AbortIfNotOwner.php):
<?php
namespace App\Http\Middleware;
use Closure;
class AbortIfNotOwner
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $resourceName
* #return mixed
*/
public function handle($request, Closure $next, $resourceName)
{
$resourceId = $request->route()->parameter($resourceName);
$user_id = \DB::table($resourceName)->find($resourceId)->user_id;
if ($request->user()->id != $user_id) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
Inside app\Http\Kernel.php:
protected $routeMiddleware = [
'owner' => 'App\Http\Middleware\AbortIfNotOwner',
];
Inside your route file (app/Http/routes.php):
Route::group(['middleware' => ['owner:articles']], function() {
// your route
});
And optionally call it in the controller:
public function __construct()
{
$this->middleware('owner:articles', ['only' => ['edit', 'update']]);
}