PHPPamokos.lt


5. Nuo Filters prie Middleware

Laravel 4 versijoje kataloge /app buvo du svarbūs failai - routes.php ir filters.php. Ir jei pirmasis tik pakeitė savo dislokaciją ir persikėlė į kitą katalogą, tai Filtrų funkcionalumas buvo perdarytas gan kardinaliai - juos pakeitė Middleware.

Pastaba. Iš tikro, ir Laravel 5 galima "senoviškai" naudoti filtrus, bet tai yra nerekomenduojama praktika, kuri kažkurioje vėlesnėje Laravel versijoje bus visai uždrausta, tad neverta to daryti.

Taigi, Middleware, nors atrodo naujas, ilgas ir nesuprantamas žodis - iš esmės, yra tie patys filtrai, tik kitaip pavadinami, kitaip deklaruojami ir iškelti į kitą katalogą.

Priminsiu, kas yra filtrai, ir kaip mes juos naudojome Laravel 4 versijoje. Jie skirti kažkokiam tarpiniam veiksmui prieš vykdant pagrindinį funkcionalumą - dažniausias pritaikymas yra autorizacijos patikrinimas prieš bet kokį kreipimąsi į Controllerį. Filtras patikrina, ar vartotojas prisijungęs, ir "praleidžia" jį toliau arba sustabdo ir tuoj pat užbaigia skripto veikimą su klaida. Tai tam tikslui ketvirtoje versijoje faile app/filters.php mes kūrėme konstrukcijas Route::filter(), ir vėliau faile app/routes.php priskirdavome juos vienam ar kitokiam URL kvietimui.

Kaip visa tai veikia Laravel 5? Principas panašus, tik veiksmų seka skirtinga.

Kaip sukurti Middleware klasę

Iš komandinės eilutės generuojame naują klasę. Sakykime, norime patikrinti, ar lankytojas pilnametis, ir amžius bus mums paduodamas kaip GET parametras.

php artisan make:middleware AdultMiddleware

Rezultatas - kataloge /app/Http/Middleware sukuriamas failas AdultMiddleware.php su tokiu turiniu:

namespace App\Http\Middleware;

class AdultMiddleware implements Middleware {

    /**
     * Run the request filter.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        //
    }

}

Kaip matote, šioje klasėje yra vienintelis metodas handle(), kurio paskirtis ir yra - įvykdyti filtro sąlygas, ir jei jos nepatenkintos - perkelti vartotoją į kažkokį klaidos puslapį ir nepraleisti jo toliau. Sakykime, taip:

public function handle($request, Closure $next)
{
    if ($request->input('age') < 18)
	{
	    return redirect('adult-gate');
	}
}

Svarbus momentas - užklausa imama iš parametro $request, kuris savyje turi visą mūsų HTTP užklausą su visais kintamaisiais ir parametrais, pvz input.

Kitas parametras $next yra Closure tipo anoniminė funkcija, kuri yra panaudojama tuo atveju, kai filtras "praeina" patikrinimą ir leidžiama vartotojui judėti toliau. Pilna funkcija atrodytų taip:

public function handle($request, Closure $next)
{
    if ($request->input('age') < 18)
	{
	    return redirect('adult-gate');
	}
	return $next($request);
}

Neišsigąskite - visais tais Closure ir $next dalykais jums rūpintis nereikės - tiesiog kvieskite ir naudokite būtent šiuos parametrus, o kaip jie viduje iš tikro suveikia - tuo pasirūpins Laravel. Ta proga pereikime prie to, kaip panaudojama ši Middleware klasė.

Kaip panaudoti Middleware klasę

Globalus Middleware

Jei norite kažkokią konkrečią Middleware klasę paleisti su visomis URL užklausomis, galima ją pridėti prie app/Http/Kernel.php faile esančių masyvų:

class Kernel extends HttpKernel {

	protected $middleware = [
		'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
		'Illuminate\Cookie\Middleware\EncryptCookies',
		'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
		'Illuminate\Session\Middleware\StartSession',
		'Illuminate\View\Middleware\ShareErrorsFromSession',
		'App\Http\Middleware\VerifyCsrfToken',
	];

	protected $routeMiddleware = [
		'auth' => 'App\Http\Middleware\Authenticate',
		'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
		'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
	];

}

Masyve $middleware esančios visos Middleware klasės veikia pagal nutylėjimą su visomis užklausomis. O $routeMiddleware tai yra sutrumpinimų rinkinys, kad būtų po to greičiau priskirti konkrečiam Route veiksmui.

Tiesioginis priskyrimas prie Route

Gera žinia yra ta, kad įprastas filtrų pajungimas iš Laravel 4 versijos - veiks labai panašiai ir Laravel 5 versijoje, tik parametras vadinsis 'middleware':

Route::get('admin/users', ['middleware' => 'adult', function()
{
    // ...
}]);
Priskyrimas prie Controllerio

Taip pat galima priskirti klasę ir senu geru metodu prie Controllerio, anksčiau tai būdavo $this->filter(), o dabar $this->middleware():

class AdultController extends Controller {

    public function __construct()
    {
        $this->middleware('adult');
        $this->middleware('auth', ['only' => 'update'])
    }

}

"After" filtrai - dabar Terminable Middleware

Retai naudojamas atvejis (pats nesu niekur savo projektuose naudojęs "after" filtrų), bet gali būti naudingas, sakykime, log'ų saugojimui. Tai tas senasis Laravel 4 after filtrų variantas naujoje versijoje atrodo visai kitaip ir vadinasi Terminable Middleware - atrodo panašiai kaip ir paprastas Middleware, generuojama štai tokia klasė:

use Illuminate\Contracts\Routing\TerminableMiddleware;

class AdultMiddleware implements TerminableMiddleware  {

    public function handle($request, Closure $next)
    {
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // naudojame $response objektą - saugome duomenis į logus ar pan.
    }

}


(c) 2015-2018. Visais klausimais kreipkitės povilas@laraveldaily.com