web-dev-qa-db-fra.com

Laravel Un middleware renvoie une variable au contrôleur)

J'effectue une vérification des autorisations sur un utilisateur pour déterminer s'il peut ou non afficher une page. 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 renvoyer les données à la vue elle-même.

Voici un exemple de la configuration;

- routes.php

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

- PageUserMiddleware.php (classe 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 constater, la Page::with('users')->where('id', $id)->first() est répétée dans le middleware et le contrôleur. Je dois transmettre les données de l'un à l'autre afin de ne pas les dupliquer.

65
Alex

Je pense que la bonne façon de faire ceci (dans Laravel 5.x) est d’ajouter vos champs personnalisés à la propriété attributs.

À partir des 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;

Donc, vous implémenteriez ceci comme suit:

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

Vous pouvez ensuite récupérer l'attribut en appelant:

\Request::get('myAttribute');

Ou à partir d'un objet de requête dans laravel 5.5+

 $request->get('myAttribute');
108
Gaz_Edge

Au lieu de paramètres de demande personnalisés, vous pouvez suivre le modèle d'inversion de contrôle et utiliser l'injection de dépendance.

Enregistrez votre instance Page dans votre middleware:

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

Puis 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 l'instance Page que vous avez liée dans votre middleware.

20
crishoj

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');
    ...
}
15
Vinicius

Je suis sûr que s’il était possible de transmettre des données d’un middleware à un contrôleur, elles figureraient dans la documentation Laravel.

Regardez this et this , cela pourrait aider.

En bref, vous pouvez relier vos données à l'objet de requête qui est transmis au middleware. La façade d'authentification Laravel) le fait aussi.

Ainsi, dans votre middleware, vous pouvez avoir:

$request->myAttribute = "myValue";
6
Noman Ur Rehman

Comme mentionné dans l’un des commentaires ci-dessus pour laravel 5.3.x

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

Ça ne marche pas Mais définir la variable comme celle-ci 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');
5
Tariq Khan

Laravel 5.7

// in Middleware register instance
app()->instance('myObj', $myObj);

et

// to get in controller just use the resolve helper
$myObj = resolve('myObj');

C'est très simple:

Voici le code middleware:

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

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

    return $next($request);
}

et voici le code du contrôleur:

$request->customVar;
3
Ashfaq Muhammad

$ request est le tableau afin que nous puissions simplement ajouter de la valeur et une clé au tableau et obtenir la requête $ avec cette clé dans le contrôleur.

$ request ['id'] = $ id;

2
Durgesh Pandey

Si votre site Web contient des pages cms extraites de la base de données et que vous souhaitez afficher leurs titres dans les blocs d'en-tête et de pied de page de toutes les pages de laravel), utilisez un middleware. Écrivez le code ci-dessous dans votre 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);

}

Ensuite, allez à votre header.blade.php et footer.blade.php et écrivez ci-dessous le code pour ajouter des liens de pages cms:

<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>

Merci beaucoup à tous et profitez du code :)

2
Kamlesh

J'ai pu ajouter des valeurs à l'objet Request avec:

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

et les récupérer plus tard avec:

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

Ceci est possible parce que Requête laravels étend Requête symfonys qui a l'attribut " $ attributs " de type ParameterBag c'est-à-dire destiné à contenir paramètres personnalisés .

Je pense que cela devrait être une bonne pratique de transmettre des données à des middleware, contrôleurs ou tout autre endroit ultérieur où il est possible d'accéder à l'objet Request.

Testé avec Laravel 5.6 , mais fonctionne probablement aussi avec d'autres versions.

1
suud

je ne parle pas anglais, alors ... désolé pour les erreurs possibles.

Vous pouvez utiliser la liaison IoC pour cela. Dans votre middleware, vous pouvez le faire pour lier une instance de page $:

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

Ensuite, dans votre contrôleur, vous appelez cette instance:

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

App :: instance ne ré-instance pas la classe, retourne plutôt l'instance contraignante.

1
Carlos Porter