Laravel Middleware retour variable au contrôleur
j'effectue un contrôle de permissions sur un utilisateur pour déterminer s'il peut voir une page ou non. Cela implique de passer d'abord la requête par un middleware.
le problème que j'ai est que je duplique la même requête de base de données dans le middleware et dans le contrôleur avant de retourner les données à la vue elle-même.
voici un exemple de configuration;
-- 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]);
}
comme vous pouvez le voir, le Page::with('users')->where('id', $id)->first()
est répété dans le middleware et le contrôleur. Je dois passer les données de l'un à l'autre pour ne pas les dupliquer.
9 réponses
je crois que la bonne façon de le faire (dans Laravel 5.x) est d'ajouter vos champs personnalisés à la propriété attributs.
D'après les commentaires du code source, nous pouvons voir que les attributs sont utilisés pour les paramètres personnalisés:
/**
* Custom parameters.
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
* @api
*/
public $attributes;
pour que vous mettiez en œuvre ceci comme suit;
$request->attributes->add(['myAttribute' => 'myValue']);
vous pouvez alors récupérer l'attribut en appelant:
\Request::get('myAttribute');
dans laravel >= 5 vous pouvez utiliser $request->merge
dans le middleware:
public function handle($request, Closure $next)
{
$request->merge(array("myVar" => "1234"));
return $next($request);
}
et dans le contrôleur:
public function index(Request $request)
{
$myVar = Request::instance()->query('myVar');
...
}
au lieu des paramètres de requête personnalisés, vous pouvez suivre le modèle d'inversion de contrôle et utiliser l'injection de dépendances.
dans votre middleware, enregistrez votre Page
instance:
app()->instance(Page::class, $page);
alors déclarez que votre contrôleur a besoin d'une instance Page
:
class PagesController
{
protected $page;
function __construct(Page $page)
{
$this->page = $page;
}
}
Laravel résoudra automatiquement la dépendance et instanciera votre contrôleur avec le Page
exemple que vous avez lié dans votre middleware.
je suis sûr que s'il était possible de transmettre des données d'un middleware à un contrôleur, ce serait dans la documentation de Laravel.
regarder ce et ce , ça pourrait aider.
en bref, vous pouvez récupérer vos données sur l'objet request qui est passé dans le middleware. La façade d'authentification Laravel le fait aussi.
donc, dans votre middleware, vous pouvez ont:
$request->myAttribute = "myValue";
, Comme mentionné dans l'un des commentaires ci-dessus pour laravel 5.3.x
$request->attributes->add(['key => 'value'] );
ne marche pas. Mais définir la variable comme ceci dans le middleware fonctionne
$request->attributes->set('key', 'value');
je pourrais récupérer les données en utilisant ceci dans mon contrôleur
$request->get('key');
$request est le tableau de sorte que nous pouvons juste ajouter de la valeur et de la clé au tableau et obtenir la requête $avec cette clé dans le contrôleur.
$ request ['id'] = $id;
c'est très simple:
voici middleware code:
public function handle($request, Closure $next)
{
$request->merge(array("customVar" => "abcde"));
return $next($request);
}
et voici le code du contrôleur:
$request->customVar;
je ne parle pas anglais, donc... désolé pour les éventuelles erreurs.
vous pouvez utiliser la reliure du CIO pour cela. Dans votre middleware, vous pouvez faire ceci pour lier $page instance:
\App::instance('mi_page_var', $page);
après, dans votre controller vous appelez cette instance:
$page = \App::make('mi_page_var');
de L'App::instance de ne pas re-instance de la classe, au lieu de retourner l'instance previusly de liaison.
j'ai pu ajouter des valeurs à la requête-objet avec:
$request->attributes->set('key', 'value');
et les faire revenir à un point plus tard:
$request->attributes->get('key');
cela est possible parce que demande laravels étend demande symfonys qui a l'attribut " $attributs de type ParameterBag qui est destiné à tenir paramètres personnalisés .
je pense que ce devrait être la meilleure pratique pour transmettre des données à des middlewares ultérieurs, contrôleurs ou tout autre endroit où il est possible d'accéder à la requête-objet.
Testé avec Laravel 5.6 , mais probablement aussi en travaillant avec d'autres versions.