Sprawdzam uprawnienia użytkownika, aby określić, czy może przeglądać stronę, czy nie. Obejmuje to najpierw przekazanie żądania przez niektóre oprogramowanie pośredniczące.
Problem polega na tym, że powielam to samo zapytanie do bazy danych w oprogramowaniu pośrednim i w kontrolerze przed zwróceniem danych do samego widoku.
Oto przykład konfiguracji;
- tours.php
Route::get('pages/{id}', [
'as' => 'pages',
'middleware' => 'pageUser'
'uses' => 'PagesController@view'
]);
- PageUserMiddleware.php (klasa 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]);
}
Jak widać, Page::with('users')->where('id', $id)->first()
operacja powtarza się zarówno w oprogramowaniu pośrednim, jak i kontrolerze. Muszę przekazywać dane z jednego do drugiego, aby ich nie powielać.
Odpowiedzi:
Uważam, że właściwym sposobem na to (w Laravel 5.x) jest dodanie własnych pól niestandardowych do właściwości atrybutów.
Z komentarzy do kodu źródłowego widać, że atrybuty są używane dla parametrów niestandardowych:
/** * Custom parameters. * * @var \Symfony\Component\HttpFoundation\ParameterBag * * @api */ public $attributes;
Więc zaimplementowałbyś to w następujący sposób;
$request->attributes->add(['myAttribute' => 'myValue']);
Następnie możesz pobrać atrybut, wywołując:
\Request::get('myAttribute');
Lub z obiektu żądania w programie Laravel 5.5+
$request->get('myAttribute');
źródło
$request->request->add(['myAttribute' => 'myValue']);
aby móc użyć skrótu magicznego gettera$request->myAttribute
Zamiast niestandardowych parametrów żądania można zastosować wzorzec inwersji kontroli i użyć iniekcji zależności.
W oprogramowaniu pośrednim zarejestruj swoją
Page
instancję:app()->instance(Page::class, $page);
Następnie zadeklaruj, że Twój kontroler potrzebuje
Page
instancji:class PagesController { protected $page; function __construct(Page $page) { $this->page = $page; } }
Laravel automatycznie rozwiąże zależność i utworzy instancję kontrolera z
Page
instancją związaną z oprogramowaniem pośredniczącym.źródło
W laravel> = 5 możesz użyć
$request->merge
w oprogramowaniu pośrednim:public function handle($request, Closure $next) { $request->merge(array("myVar" => "1234")); return $next($request); }
A w kontrolerze:
public function index(Request $request) { $myVar = $request->instance()->query('myVar'); ... }
źródło
Request::instance()
statyczny, zamiast używać$request
?Laravel 5.7
// in Middleware register instance app()->instance('myObj', $myObj);
i
// to get in controller just use the resolve helper $myObj = resolve('myObj');
źródło
Jak wspomniano w jednym z powyższych komentarzy dla laravel 5.3.x
$request->attributes->add(['key => 'value'] );
Nie działa. Ale ustawienie takiej zmiennej w oprogramowaniu pośrednim działa
$request->attributes->set('key', 'value');
Mogłem pobrać dane za pomocą tego w moim kontrolerze
$request->get('key');
źródło
Jestem pewien, że gdyby było możliwe przekazanie danych z oprogramowania pośredniego do kontrolera, to byłoby to w dokumentacji Laravela.
Spójrz na to i to , może pomóc.
Krótko mówiąc, możesz przenieść swoje dane na obiekt żądania, który jest przekazywany do oprogramowania pośredniczącego. Fasada uwierzytelniania Laravel również to robi.
Tak więc w swoim oprogramowaniu pośrednim możesz mieć:
$request->myAttribute = "myValue";
źródło
To bardzo proste:
Oto kod oprogramowania pośredniego:
public function handle($request, Closure $next) { $request->merge(array("customVar" => "abcde")); return $next($request); }
a oto kod kontrolera:
$request->customVar;
źródło
Jeśli Twoja witryna zawiera strony cms, które są pobierane z bazy danych i chcesz wyświetlać ich tytuły w bloku nagłówka i stopki na wszystkich stronach aplikacji laravel, użyj oprogramowania pośredniego. Napisz poniższy kod w swoim oprogramowaniu pośrednim:
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); }
Następnie przejdź do plików header.blade.php i footer.blade.php i napisz poniższy kod, aby dodać linki do stron 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>
Bardzo dziękuję wszystkim i życzymy udanego kodu :)
źródło
nie mówię po angielsku, więc ... przepraszam za możliwe błędy.
Możesz użyć do tego powiązania IoC. W swoim oprogramowaniu pośrednim możesz to zrobić, aby powiązać instancję $ page:
\App::instance('mi_page_var', $page);
Następnie w kontrolerze wywołujesz tę instancję:
$page = \App::make('mi_page_var');
App :: instance nie powoduje ponownego wystąpienia klasy, zamiast tego zwraca poprzednie powiązanie wystąpienia.
źródło
Udało mi się dodać wartości do obiektu Request za pomocą:
$request->attributes->set('key', 'value');
i odzyskaj je później za pomocą:
$request->attributes->get('key');
Jest to możliwe, ponieważ laravels Request rozszerza żądanie symfonys, które ma atrybut „ $ attributes ” typu ParameterBag, który jest przeznaczony do przechowywania parametrów niestandardowych .
Myślę, że powinno to być najlepszą praktyką, aby przekazać dane do kolejnego oprogramowania pośredniczącego, kontrolerów lub dowolnego innego miejsca, w którym można uzyskać dostęp do obiektu żądania.
Testowany z Laravelem 5.6 , ale prawdopodobnie działa również z innymi wersjami.
źródło
$request
jest tablicą, abyśmy mogli po prostu dodać wartość i klucz do tablicy i uzyskać$request
z tym kluczem w kontrolerze.$request['id'] = $id;
źródło