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.
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');
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.
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');
...
}
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";
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');
// 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;
$ 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;
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 :)
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.
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.