Laravel Middleware return variable to controller

浪子不回头ぞ 提交于 2019-12-28 04:50:06

问题


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.


回答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');



回答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.




回答3:


In laravel >= 5 you can use $request->merge in the middleware:

public function handle($request, Closure $next)
{

    $request->merge(array("myVar" => "1234"));

    return $next($request);
}

And in the controller:

public function index(Request $request)
{

    $myVar = $request->instance()->query('myVar');
    ...
}



回答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');



回答5:


I am sure if it was possible to pass data from a middleware to a controller then it would be in the Laravel documentation.

Have a look at this and this, it might help.

In short, you can piggy back your data on the request object which is being passed to the middleware. The Laravel authentication facade does that too.

So, in your middleware, you can have:

$request->myAttribute = "myValue";



回答6:


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



回答7:


It is very simple:

Here is middleware code:

public function handle($request, Closure $next)
{

    $request->merge(array("customVar" => "abcde"));

    return $next($request);
}

and here is controller code:

$request->customVar;



回答8:


$request is the array so that we can just add value and key to the array and get the $request with this key in the controller.

$request['id'] = $id;




回答9:


If your website has cms pages which are being fetched from database and want to show their titles in the header and footer block on all pages of laravel application then use middleware. Write below code in your middleware:

namespace App\Http\Middleware;

use Closure;

use Illuminate\Support\Facades\DB;

public function handle($request, Closure $next)
{    

$data = DB::table('pages')->select('pages.id','pages.title')->where('pages.status', '1')->get();

\Illuminate\Support\Facades\View::share('cms_pages', $data);

return $next($request);

}

Then goto your header.blade.php and footer.blade.php and write below code to add links of cms pages:

<a href="{{ url('/') }}">Home</a> | 

@foreach ($cms_pages as $page) 

<a href="{{ url('page/show/'.$page->id) }}">{{ $page->title }}</a> | 

@endforeach

<a href="{{ url('contactus') }}">Contact Us</a>

Thanks a lot to all and enjoy the code :)




回答10:


i don't speak english, so... sorry for possible errors.

You can use the IoC binding for this. In your middleware you can do this for binding $page instance:

\App::instance('mi_page_var', $page);

After, in your controller you call that instance:

$page = \App::make('mi_page_var');

The App::instance not re-instance the class, instead return the instance previusly binding.




回答11:


I was able to add values to the Request-object with:

$request->attributes->set('key', 'value');

and get them back at a later point with:

$request->attributes->get('key');

This is possible because laravels Request extends symfonys Request which has the attribute "$attributes" of type ParameterBag that is intended to hold custom parameters.

I think this should be Best Practice to pass data to subsequent Middleware, Controllers or any other place where it's possible to access the Request-object.

Tested with Laravel 5.6, but probably also working with other versions.



来源:https://stackoverflow.com/questions/30212390/laravel-middleware-return-variable-to-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!