Что 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 56

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, но, вероятно, также работает с другими версиями.