Промежуточное программное обеспечение Laravel возвращает переменную контроллеру


Я провожу проверку разрешений пользователя, чтобы определить, могут ли они просматривать страницу или нет. Это включает в себя сначала передачу запроса через какое-либо промежуточное программное обеспечение.

Проблема, с которой я сталкиваюсь, заключается в том, что я дублирую один и тот же запрос к базе данных в промежуточном программном обеспечении и в контроллере, прежде чем возвращать данные в само представление.

Вот пример настройки;

-- routes.php

Route::get('pages/{id}', [
   'as' => 'pages',
   'middleware' => 'pageUser'
   'uses' => 'PagesController@view'
]);

-- PageUserMiddleware.php (страница пользователя класса)

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

Как вы можете видеть, Page::with('users')->where('id', $id)->first() повторяется как в промежуточном программном обеспечении, так и в контроллере. Мне нужно передать данные от одного к другому, чтобы не дублировать.

Author: ROMANIA_engineer, 2015-05-13

9 answers

Я считаю, что правильный способ сделать это (в Laravel 5.x) - добавить свои пользовательские поля в свойство атрибутов.

Из комментариев к исходному коду мы видим, что атрибуты используются для пользовательских параметров:

 /**
 * Custom parameters.
 *
 * @var \Symfony\Component\HttpFoundation\ParameterBag
 *
 * @api
 */
public $attributes;

Таким образом, вы бы реализовали это следующим образом;

$request->attributes->add(['myAttribute' => 'myValue']);

Затем вы можете получить атрибут, вызвав:

\Request::get('myAttribute');
 76
Author: Gaz_Edge, 2017-10-02 05:42:28

В laravel>=5 вы можете использовать $request->merge в промежуточном программном обеспечении:

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

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

    return $next($request);
}

И в контроллере:

public function index(Request $request)
{

    $myVar = Request::instance()->query('myVar');
    ...
}
 13
Author: Vinicius, 2015-11-07 13:50:49

Вместо пользовательских параметров запроса вы можете следовать шаблону инверсии управления и использовать внедрение зависимостей.

В своем промежуточном программном обеспечении зарегистрируйте свой экземпляр Page:

app()->instance(Page::class, $page);

Затем объявите, что вашему контроллеру нужен экземпляр Page:

class PagesController 
{
    protected $page;

    function __construct(Page $page) 
    {
        $this->page = $page;
    }
}

Laravel автоматически устранит зависимость и создаст экземпляр вашего контроллера с экземпляром Page, который вы привязали в своем промежуточном программном обеспечении.

 11
Author: crishoj, 2015-10-23 08:15:21

Я уверен, что если бы можно было передавать данные из промежуточного программного обеспечения в контроллер, то это было бы в документации Laravel.

Взгляните на это и это , это может помочь.

Короче говоря, вы можете сохранить свои данные в объекте запроса, который передается промежуточному программному обеспечению. Фасад аутентификации Laravel делает то же самое.

Итак, в вашем промежуточном программном обеспечении вы можете иметь:

$request->myAttribute = "myValue";
 6
Author: Noman Ur Rehman, 2017-05-23 12:26:22

Как упоминалось в одном из комментариев выше для laravel 5.3.x

$request->attributes->add(['key => 'value'] ); 

Не работает. Но установка такой переменной в промежуточном программном обеспечении работает

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

Я мог бы получить данные, используя это в своем контроллере

$request->get('key');
 3
Author: Tariq Khan, 2017-09-27 15:30:11

$request - это массив, так что мы можем просто добавить значение и ключ в массив и получить $request с этим ключом в контроллере.

$запрос['id'] = $id;

 2
Author: Durgesh Pandey, 2017-11-15 10:54:24

Это очень просто:

Вот код промежуточного программного обеспечения:

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

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

    return $next($request);
}

А вот код контроллера:

$request->customVar;
 2
Author: Ashfaq Muhammad, 2018-08-07 07:56:04

Я не говорю по-английски, так что... извините за возможные ошибки.

Для этого вы можете использовать привязку IoC. В вашем промежуточном программном обеспечении вы можете сделать это для привязки экземпляра $page:

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

После этого в своем контроллере вы вызываете этот экземпляр:

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

Приложение::экземпляр не создает повторный экземпляр класса, вместо этого возвращает экземпляр, ранее привязанный.

 1
Author: Carlos Porter, 2015-08-18 10:04:51

Я смог добавить значения в объект запроса с помощью:

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

И верните их позже с помощью:

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

Это возможно, потому что Запрос laravels расширяет Запрос symfonys, который имеет атрибут "$атрибуты" типа Параметр, предназначенный для хранения пользовательских параметров.

Я думаю, что это должно быть лучшей практикой для передачи данных последующему промежуточному программному обеспечению, контроллерам или любому другому месту, где это возможен доступ к объекту-запросу.

Протестировано с Laravel 5.6, но, вероятно, также работает с другими версиями.

 0
Author: suud, 2018-07-06 10:57:08