Laravel Middleware return variable to controller
Solution 1
I believe the correct way to do this (in Laravel 5.x) is to add your custom fields to the attributes property.
From the source code comments, we can see attributes is used for custom parameters:
/**
* Custom parameters.
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
* @api
*/
public $attributes;
So you would implement this as follows;
$request->attributes->add(['myAttribute' => 'myValue']);
You can then retrieved the attribute by calling:
\Request::get('myAttribute');
Or from request object in laravel 5.5+
$request->get('myAttribute');
Solution 2
Instead of custom request parameters, you can follow the inversion-of-control pattern and use dependency injection.
In your middleware, register your Page
instance:
app()->instance(Page::class, $page);
Then declare that your controller needs a Page
instance:
class PagesController
{
protected $page;
function __construct(Page $page)
{
$this->page = $page;
}
}
Laravel will automatically resolve the dependency and instantiate your controller with the Page
instance that you bound in your middleware.
Solution 3
In Laravel >= 5 you can use $request->merge
in the middleware.
public function handle($request, Closure $next)
{
$request->merge(["myVar" => "1234"]);
return $next($request);
}
And in the controller
public function index(Request $request)
{
$myVar = $request->myVar;
...
}
Solution 4
Laravel 5.7
// in Middleware register instance
app()->instance('myObj', $myObj);
and
// to get in controller just use the resolve helper
$myObj = resolve('myObj');
Solution 5
As mentioned in one of the comments above for laravel 5.3.x
$request->attributes->add(['key => 'value'] );
Doesn't work. But setting the variable like this in the middleware works
$request->attributes->set('key', 'value');
I could fetch the data using this in my controller
$request->get('key');
Alex
Updated on July 08, 2021Comments
-
Alex almost 3 years
I am carrying out a permissions check on a user to determine whether they can view a page or not. This involves passing the request through some middleware first.
The problem I have is I am duplicating the same database query in the middleware and in the controller before returning the data to the view itself.
Here is an example of the setup;
-- routes.php
Route::get('pages/{id}', [ 'as' => 'pages', 'middleware' => 'pageUser' 'uses' => 'PagesController@view' ]);
-- PageUserMiddleware.php (class PageUserMiddleware)
public function handle($request, Closure $next) { //get the page $pageId = $request->route('id'); //find the page with users $page = Page::with('users')->where('id', $pageId)->first(); //check if the logged in user exists for the page if(!$page->users()->wherePivot('user_id', Auth::user()->id)->exists()) { //redirect them if they don't exist return redirect()->route('redirectRoute'); } return $next($request); }
-- PagesController.php
public function view($id) { $page = Page::with('users')->where('id', $id)->first(); return view('pages.view', ['page' => $page]); }
As you can see, the
Page::with('users')->where('id', $id)->first()
is repeated in both the middleware and controller. I need to pass the data through from one to the other so an not to duplicate. -
Alex almost 9 yearsThanks @norman - thats a good solution and i didn't know you could do it...! I was questioning if i should be using middleware at this point at all, but it seems i should. The documentation does not mention anything of the sort. Thanks again
-
Noman Ur Rehman almost 9 years@Alex Yes, I think if its a common piece of code that executes in every controller action, it is not a bad idea to implement it as a middleware.
-
Alex over 8 yearsI have changed this to the correct answer. Whilst Norman was right, this seems to adhere to Laravel's best practices. Thanks
-
user985366 about 8 yearsHow do you then access the attributes within the receiving controller?
-
GWed about 8 yearsadd request class to controller method arguments (IoC container) or call static class \Request
-
Shawn C. about 8 years$myAttribute = \Request::get('myAttribute');
-
schellingerht almost 8 yearsWow, this solution looks very clean!
-
developernaren over 7 yearsfor some reason,
$request->attributes->add(['key => 'value'] );
did not work for me but$request->attributes->set('key', 'value')
worked, I could fetch the data using$request->get('key')
, -
GWed over 7 yearsWhat version of laravel are you using?
-
Arian Acosta over 7 yearsThis is a really good idea, I went ahead and created a Service Provider then registered a Service Container. That way when needed some attributes, I would just inject the dependencies. Much cleaner and transparent. Thanks!
-
Hafiz over 7 yearsWhat if someone want to add an object instead of just string value?
-
GWed over 7 yearsIt's just an array so an object can be added the same way as you do for any array
-
Gediminas about 7 yearsCan't make it work - value is still empty. Laravel 5.3.4. Trying to use code in answer and @developernaren example :(
-
developernaren about 7 years@Gediminas can you post your code snippet somwhere? It is working perfectly for me. Make sure the middleware is called when the controller is called.
-
JCarlosR about 7 years@ArianAcosta Please, can you elaborate an answer with your way? I mean, how to use dependency injection and how it is associated with the middleware.
-
Arian Acosta about 7 years@JCarlos Sure! The idea would be to have a custom Service Container class that holds as internal properties the data that you need to pass around between the middleware and the controller. If you register that Service Container as a singleton with $this->app->singleton(...) then, it will always be the same instance every time you inject it. So, essentially you would first inject it in the middleware (by simply requiring it as an argument), then put the data inside of it, and finally require it in the controller where you can access the data. See laravel.com/docs/5.4/container good luck
-
Vinay Vissh almost 7 years@Gaz_Edge Thanks a lot! Using Laravel 5.4.23 and putting arrays/objects inside attributes works like a charm!
-
jjok over 6 yearsWhy would you access
Request::instance()
statically, rather than using$request
? -
Pietro over 6 yearsThis is a GREAT answer ... neat! :)
-
jonan.pineda over 6 yearsYou can also use
$request->request->add(['myAttribute' => 'myValue']);
to be able to use the magic getter shorthand$request->myAttribute
-
Serhii Topolnytskyi about 5 yearsRemark: in __constructor it doesn't work, because middleware loaded after controller's constructor. But you could use DI in any action of controller.
-
hizmarck about 4 years@SerhiiTopolnytskyi In my case that works in the constructor.
-
Olle Härstedt over 3 yearsIs this really good praxis? Shouldn't the request object represent only what we got from the browser?
-
Ali over 2 yearsthis worked,thanks bro