Что Laravel промежуточного вернуть переменную в контроллере
Я выполняю проверку разрешений на пользователя, чтобы определить, могут ли они просмотреть страницу или нет. Это включает в себя передачу запроса через некоторое промежуточное программное обеспечение в первую очередь.
проблема у меня есть я дублирую один и тот же запрос базы данных в middleware и в контроллере перед возвратом данных в само представление.
вот пример установки;
-- маршруты.php
Route::get('pages/{id}', [
'as' => 'pages',
'middleware' => 'pageUser'
'uses' => 'PagesController@view'
]);
-- PageUserMiddleware.класс PHP 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]);
}
Как видите,Page::with('users')->where('id', $id)->first()
повторяется как в промежуточном программном обеспечении, так и в контроллере. Мне нужно передать данные от одного к другому, чтобы не дублировать.
9 ответов:
Я считаю, что правильный способ сделать это (в Laravel 5.x) - это добавление пользовательских полей в свойство атрибуты.
из комментариев исходного кода мы видим, что атрибуты используются для пользовательских параметров:
/** * Custom parameters. * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $attributes;
Так вы бы реализовать это следующим образом:
$request->attributes->add(['myAttribute' => 'myValue']);
затем вы можете получить атрибут, вызвав:
\Request::get('myAttribute');
в laravel >= 5 Вы можете использовать
$request->merge
в middleware:public function handle($request, Closure $next) { $request->merge(array("myVar" => "1234")); return $next($request); }
и в контроллере:
public function index(Request $request) { $myVar = Request::instance()->query('myVar'); ... }
вместо пользовательских параметров запроса вы можете следовать шаблону инверсии управления и использовать инъекцию зависимостей.
в вашем промежуточном программном обеспечении, зарегистрируйте ваш
Page
например:
app()->instance(Page::class, $page);
затем объявите, что ваш контроллер нуждается в
Page
например:class PagesController { protected $page; function __construct(Page $page) { $this->page = $page; } }
Laravel автоматически разрешит зависимость и создаст экземпляр вашего контроллера с помощью
Page
экземпляр, который вы связали в ваше промежуточное.
Я уверен, что если бы можно было передать данные из промежуточного программного обеспечения в контроллер, то это было бы в документации Laravel.
посмотреть этой и этой, это может помочь.
короче говоря, вы можете копить свои данные на объект запроса, который передается в middleware. Фасад аутентификации Laravel делает это тоже.
Итак, в вашем промежуточном программном обеспечении вы можете иметь:
$request->myAttribute = "myValue";
как упоминалось в одном из комментариев выше для laravel 5.3.x
$request->attributes->add(['key => 'value'] );
не работает. Но установка переменной, как это в middleware работает
$request->attributes->set('key', 'value');
я мог бы получить данные, используя это в моем контроллере
$request->get('key');
$request-это массив, так что мы можем просто добавить значение и ключ к массиву и получить $request с этим ключом в контроллере.
$request ['id'] = $id;
Это очень просто:
вот код промежуточного программного обеспечения:
public function handle($request, Closure $next) { $request->merge(array("customVar" => "abcde")); return $next($request); }
а вот код контроллера:
$request->customVar;
Я не говорю по-английски, так... извините за возможные ошибки.
Вы можете использовать привязку МОК для этого. В вашем middleware вы можете сделать это для привязки экземпляра $page:
\App::instance('mi_page_var', $page);
после этого в контроллере вы вызываете этот экземпляр:
$page = \App::make('mi_page_var');
приложение:: instance не повторяет экземпляр класса, вместо этого возвращает экземпляр ранее привязки.
я смог добавить значения в запрос-объект с помощью:
$request->attributes->set('key', 'value');
и получить их обратно в более поздний момент с:
$request->attributes->get('key');
это возможно, потому что laravels запрос выходит запрос symfonys, который имеет атрибут " $ attributes" типа ParameterBag, предназначенный для пользовательские параметры.
Я думаю, что это должно быть лучшей практикой для передачи данных в последующие Промежуточное программное обеспечение, контроллеры или любое другое место, где можно получить доступ к объекту запроса.
протестировано с Laravel 5.6, но, вероятно, также работает с другими версиями.