Ich führe eine Berechtigungsprüfung für einen Benutzer durch, um festzustellen, ob er eine Seite anzeigen kann oder nicht. Dazu muss die Anforderung zuerst über eine Middleware geleitet werden.
Das Problem, das ich habe, ist, dass ich die gleiche Datenbankabfrage in der Middleware und im Controller dupliziere, bevor ich die Daten an die Ansicht selbst zurückgebe.
Hier ist ein Beispiel für die Einrichtung;
- routes.php
Route::get('pages/{id}', [
'as' => 'pages',
'middleware' => 'pageUser'
'uses' => '[email protected]'
]);
- PageUserMiddleware.php (Klasse 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]);
}
Wie Sie sehen, wird die Page::with('users')->where('id', $id)->first()
sowohl in der Middleware als auch im Controller wiederholt. Ich muss die Daten von einem zum anderen weitergeben, um sie nicht zu duplizieren.
Ich glaube, dass der richtige Weg, dies zu tun (in Laravel 5.x)), darin besteht, Ihre benutzerdefinierten Felder der Eigenschaft attributes hinzuzufügen.
Aus den Quellcodekommentaren können wir ersehen, dass Attribute für benutzerdefinierte Parameter verwendet werden:
/**
* Custom parameters.
*
* @var \Symfony\Component\HttpFoundation\ParameterBag
*
* @api
*/
public $attributes;
Sie würden dies also wie folgt implementieren:
$request->attributes->add(['myAttribute' => 'myValue']);
Sie können das Attribut dann abrufen, indem Sie Folgendes aufrufen:
\Request::get('myAttribute');
Oder vom Anfrageobjekt in laravel 5.5+
$request->get('myAttribute');
Anstelle von benutzerdefinierten Anforderungsparametern können Sie dem Inversion-of-Control-Muster folgen und die Abhängigkeitsinjektion verwenden.
Registrieren Sie in Ihrer Middleware Ihre Page
-Instanz:
app()->instance(Page::class, $page);
Deklarieren Sie dann, dass Ihr Controller eine Page
-Instanz benötigt:
class PagesController
{
protected $page;
function __construct(Page $page)
{
$this->page = $page;
}
}
Laravel löst die Abhängigkeit automatisch auf und instanziiert Ihren Controller mit der Instanz Page
, die Sie in Ihre Middleware eingebunden haben.
In laravel> = 5 können Sie $request->merge
in der Middleware:
public function handle($request, Closure $next)
{
$request->merge(array("myVar" => "1234"));
return $next($request);
}
Und im Controller:
public function index(Request $request)
{
$myVar = $request->instance()->query('myVar');
...
}
Ich bin mir sicher, wenn es möglich wäre, Daten von einer Middleware an einen Controller zu übertragen, finden Sie diese in der Laravel Dokumentation.
Schauen Sie sich this und this an, es könnte helfen.
Kurz gesagt, Sie können Ihre Daten auf das Anforderungsobjekt übertragen, das an die Middleware übergeben wird. Die Laravel Authentifizierungsfassade macht das auch.
In Ihrer Middleware können Sie also Folgendes haben:
$request->myAttribute = "myValue";
Wie in einem der obigen Kommentare für laravel 5.3.x erwähnt
$request->attributes->add(['key => 'value'] );
Funktioniert nicht Das Setzen der Variablen in der Middleware funktioniert jedoch
$request->attributes->set('key', 'value');
Ich könnte die Daten mit diesem in meinem Steuerpult holen
$request->get('key');
// in Middleware register instance
app()->instance('myObj', $myObj);
und
// to get in controller just use the resolve helper
$myObj = resolve('myObj');
Es ist sehr einfach:
Hier ist der Middleware-Code:
public function handle($request, Closure $next)
{
$request->merge(array("customVar" => "abcde"));
return $next($request);
}
und hier ist der Controller-Code:
$request->customVar;
$ request ist das Array, sodass wir nur Wert und Schlüssel zum Array hinzufügen und die $ request mit diesem Schlüssel im Controller abrufen können.
$ request ['id'] = $ id;
Wenn Ihre Website CMS-Seiten enthält, die aus der Datenbank abgerufen werden und deren Titel im Kopf- und Fußzeilenblock auf allen Seiten der Anwendung laravel=) angezeigt werden sollen, verwenden Sie 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);
}
Gehen Sie dann zu header.blade.php und footer.blade.php und schreiben Sie den folgenden Code, um Links von CMS-Seiten hinzuzufügen:
<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>
Vielen Dank an alle und viel Spaß mit dem Code :)
Ich konnte dem Request-Objekt Werte hinzufügen mit:
$request->attributes->set('key', 'value');
und holen sie sich zu einem späteren Zeitpunkt zurück mit:
$request->attributes->get('key');
Dies ist möglich, weil laravels Request erweitert symfonys Request das Attribut " $ attributes " vom Typ ParameterBag hat soll benutzerdefinierte Parameter halten.
Ich denke, dies sollte Best Practice sein, um Daten an nachfolgende Middleware, Controller oder an jeden anderen Ort zu übertragen, an dem es möglich ist, auf das Request-Objekt zuzugreifen.
Getestet mit Laravel 5.6 , aber wahrscheinlich auch mit anderen Versionen.
ich spreche kein Englisch, also ... Entschuldigung für mögliche Fehler.
Sie können hierfür die IoC-Bindung verwenden. In Ihrer Middleware können Sie dies zum Binden der $ page-Instanz tun:
\App::instance('mi_page_var', $page);
Danach rufen Sie in Ihrem Controller diese Instanz auf:
$page = \App::make('mi_page_var');
Die App :: -Instanz instanziiert die Klasse nicht erneut, sondern gibt stattdessen die Instanz zurück, die zuvor gebunden war.