Routing

Rutingu bazik

rRutat vendosin korelacion ndërmjet kërkesave (request) nga Web klienti (shfletuesi) dhe ekzekutimit të kodit korrespondues në server, me ç'rast serveri kthen përgjigje (response) në formë të tekstit apo dokumentit në formatin HTML, XML, JSON, etj.

Rutat e aplikacionit definohen në fajllat që gjenden në folderin routes:

  • api.php
  • channels.php
  • console.php
  • web.php

Për një Web aplikacion standard, rutat definohen në web.php.

HTTP request metodat

Për definimin e rutave përdoret klasa Route duke i thirrë metodat statike: get, post, put, patch, delete, options, në formën:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

Metoda e zgjedhur pranon dy parametra, ku parametri i parë paraqet URL-në e dëshiruar, ndërsa parametri i dytë funksionin që duhet të ekzekutohet.

Forma më bazike një rute në Laravel përbëhet nga URI dhe closure.

Route::get('/kontakti', function () {
    return 'Të dhënat e kontaktit';
});

Ruta:

/kontakti

Funksioni:

function () {
    return 'Të dhënat e kontaktit';
}

Brenda bllokut të closure function () {} mund të vendoset çfarëdo sasie kodi, mirëpo për logjikë më komplekse rekomandohet që kodi të shkruhet brenda një kontrolleri. Urdhëri return në këtë rast bën dërgimin e rezultatit dalës në shfletuesin e vizitorit, në këtë rast tekstin "Të dhënat e kontaktit". Pra, me return u kthye një response nga serveri, si përgjigje ndaj request që u dërgua me kontakti. Adresa komplete për thirrjen e kësaj rute do të ishte:

http://www.domaini.im/kontakti

Nëse dërgimi i request duhet të bëhet me metodën POST, atëherë në vend të get, shënojmë post:

Route::post('/kontakti', function () {
    return 'Të dhënat e formularit u regjistruan!';
});

Kjo rutë do të ekzekutohet vetëm nëse kërkesa është dërguar me metodën POST, pra me dërgimin e të dhënave të një formulari dhe nuk mund të thirren si adresë në shfletues. Për të funksionuar kjo, tagu hapës i formularit duhet të ketë përmbajtje vijuese:

<form action="/kontakti" method="POST">

Në situatat kur një rute i lejohet thirrja me HTTP request metoda të ndryshme, përdoret formati:

Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('foo', function () {
    //
});

Me match përcaktojmë listën e HTTP request metodave të lejuara në formë të vargut (array).

Nëse përdorim any, lejohen të gjitha HTTP request metodat.

Ruta për kontroller

Route::get('/profile', 'UserController@index');

Me këtë definicion, kur në adresën e shfletuesit shënohet:

http://www.domaini.im/profile

do të ekzekutohet metoda index() e klasës UserController, e cila duhet të jetë e vendosur në folderin app/Http/Controllers si fajll UserController.php.

CSRF Protection

Formularët që përdorin ruta me metodat POST, PUT ose DELETE, duhet të jenë të mbrojtura nga CSRF, që realizohet me shtimin e input fushës CSRF brenda formularit.

<form method="POST" action="/profile">
    @csrf
    ...
</form>

@csrf gjatë konvertimit në HTML, shndërrohet në:

<input type="hidden" name="_token" value="WDEq2smt3K7n83AaqtMhklpXbSA027ta9Y9WjvNM">

Hash-i i shënuar si vlerë e atributit value ndryshohet në çdo sesion të ri.

Hash-i i shënuar si vlerë e atributit value ndryshohet në çdo sesion të ri.

Rutat për redirektim

Nëse dëshironi ta krijoni një rutë që redirekton në një URI tjetër, përdoret metoda Route::redirect. Me këtë mundësohet krijimi i një rute pa pasur nevojë të formohet URI e plotë.

Route::redirect('/prejrutes', '/kahruta', 301);

Kjo është ekuivalente me:

header("HTTP/1.1 301 Moved Permanently"); 
header("Location: /kahruta"); 

View Routes

Nëse na nevojitet vetëm shfaqja e një view, mund ta ndërtojmë një rutë si vijon:

Route::view('/welcome', 'welcome');
Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

Argumenti i parë është ruta, i dyti emri i view, ndërsa vargu në argumentin e tretë janë variablat që përcillen në view.

Parametrat e rutave

Parametrat e domosdoshëm

Nëpërmes rutave, mund t'i definojmë segmentet e URL që janë dinamike, si për shembull id e anëtarit apo slug i një artikulli.

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

Rutat që definohen në këtë mënyrë mund të duken kështu:

/user/1
/user/78
/user/1264

Pra, segmenti i dytë, respektivisht ajo që është definuar në {id}, do të përmbajë një vlerë dinamike.

Vlera e shënuar brenda {id} do të "kapet" nga funksioni anonim si variabël (në këtë shembull si $id) që mëpastaj i vihet në dispozicion bllokut të kodit të funksionit anonim. Në shembullin e mësipërm, nëse URL është:

http://domaini.im/user/54 

funksioni anonim do ta kthejë tekstin:

User 54

Në një rutë mund të definohen aq parametra sa kemi nevojë:

Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
    //
});

Në këtë shembull, vlera e {post} bartet në $postId, ndërsa vlera e {comment} në variablin $commentId. Më pas, kodi brenda këtij Closure operon me këto dy variabla si vlera hyrëse.

Për emërtimin e parametrave përdoren shkronjat dhe underscore _. Parametrat injektohen në Closure apo kontrollerë me atë renditje si janë shënuar.

Parametrat opsionalë

Në rastet kur një parametër i rutës duhet të jetë opsional, përdorim shenjën ? pas emrit të parametrit. Variabli ku do të ruhet vlera që përcillet më tej në Closure apo kontroller, duhet ta ketë edhe vlerën e nënkuptuar (default).

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

Kufizimet me Regular Expression

Formati i parametrave të rutës mund të kufizohet me metodën where në instancën e rutës. Kjo metodë pranon emrin e parametrit dhe regular expression që definon çfarë kufizimesh duhet të aplikohen ndaj parametrit.

Route::get('user/{name}', function ($name) {

})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {

})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function (id, name) {

})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

Kufizimet globale

Nëse një parametër i rutës duhet gjithmonë të jetë i kufizuar me një regular expression, duhet të përdoret metoda pattern. Këto mostra (patterns) definohen në metodën bootRouteServiceProvider (App\Providers\RouteServiceProvider.php).

public function boot()
{
    Route::pattern('id', '[0-9]+');
    parent::boot();
}

Pas definimit, kufizimi do të aplikohet në të gjitha rutat ku përdoret ai emër i parametër i rutës

Route::get('user/{id}', function ($id) {
    // Ekzekutohet vetëm nëse id është vlerë numerike
});

Rutat e emërtuar

Rutat e emërtuar mundësojnë gjenerimin e URL-ve apo redireksioneve për rutat e caktuara. Emri specifikohet duke e lidhur metodën name në definicionin e rutës.

Route::get('user/profile', function () {
    //
})->name('profile');

Rasti kur e definojmë rutën për metodën e një kontrolleri:

Route::get('user/profile', 'UserController@showProfile')->name('profile');

Brenda kodit të një view, kjo rutë transformohet në URL kështu:

<a href="{ { route('profile') } }">Profili</a>

Gjenerimi i URL-ve të rutave të emërtuar

Brenda kodit të aplikacionit URL-të e bazuara në rutat e emërtuar mund të gjenerohen me ndihmën e funksionit global route në këtë mënyrë:

// Generating URLs...
$url = route('profile');

// Generating Redirects...
return redirect()->route('profile');

Nëse ruta e emërtuar ka të definuar parametra, përcjellja e parametrave bëhet si argument i dytë në funksionin route, me çka mundësohet insertimi automatik i parametrave në pozicionet korrekte në URL-në e gjeneruar.

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

Inspektimi i rutave aktuale

Në rastet kur na nevojitet të determinojnë nëse kërkesa (request) aktuale është drejtuar në rutën e emërtuar të caktuar, mund të përdoret metoda named në instancën e Route. Në një middleware të rutës, kontrollimi bëhet në këtë mënyrë:

public function handle($request, Closure $next)
{
    if ($request->route()->named('profile')) {
        //
    }

    return $next($request);
}

Grupimi i rutave

Prefikset e rutave

Grupet e rutave ju mundësojnë bashkëndarjen e atributeve të rutës, siç janë middleware apo namespace, për një grup më të madh të rutave pa pasur nevojë që këto të definohen për secilën rutë veç e veç.

Në këtë shembull, dy ruta bashkëndajnë prefiks të njëjtë, atë courses:

Route::group(['prefix' => 'admin'], function () {
    Route::get('dashboard', 'CoursesController@dashboard');
    Route::get('course/{id}', 'CoursesController@getCourse');
});

Kështu, ruta dashboard thirret si:

http://domaini.im/admin/dashboard

ndërsa ruta lesson thirret si:

http://domaini.im/admin/course/15

Namespaces

Rutat mund të grupohen edhe sipas PHP namespace me një grup të kontrollerëve duke përdorur metodën namespace.

Route::namespace('Admin')->group(function () {
    // Controllers Within The "App\Http\Controllers\Admin" Namespace
});

Si vlerë të metodës namespace shënojmë segmentin e namespace pas App\Http\Controllers, në këtë rast Admin.

Sub-Domain Routing

Grupet e rutave mund të përdoren për menaxhimin e rutave nëpërmes subdomainave. Subdomaini paraqitet si parametër i rutës dhe mund të bartet më tej në Closure apo kontroller. Kjo realizohet me metodën domain.

Route::domain('{subdomain}.domaini.im')->group(function () {
    Route::get('user/{id}', function ($subdomain, $id) {
        //
    });
});

Me këtë, nëse kemi një subdomain në kuadër të domaini.im, emërtimi i atij subdomaini do të ruhet si $subdomain dhe bartet në tej. Shembull:

http://laravel.domaini.im/user/15

Variabli $subdomain: laravel

Variabli $id: 15

Middleware

Për t'ia caktuar një middleware që vlen për një grup të rutave, përdoret metoda middleware para definimit të grupit. Middleware-t ekzekutohen në radhitjen si janë shënuar në varg:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

    Route::get('user/profile', function () {
        // Uses first & second Middleware
    });
});

Route Name Prefixes

Në shembullin e mëposhtëm ruta që ka name('users') do të mund të thirret si admin.users brenda kodit.

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // Route assigned name "admin.users"...
    })->name('users');
});

Brenda kodit shënohet:

route('admin.users')

Rasti me parametra të rutës:

Route::name('admin.')->group(function () {
    Route::get('users/{name}', function () {
        // Route assigned name "admin.users"...
    })->name('users');
});

Brenda kodit shënohet:

route('admin.users', ['name' => 'John Doe']) 

Lidhja rutë-model (Route Model Binding)

Lidhja rutë-model mundëson injektim automatik të instancës së modelit drejtpërsëdrejti në rutë. Kështu, në vend se të injektohet vetëm ID-ja e produktit, mund të injektohet instanca e modelit Product që i përgjigjet ID-së së dhënë.

Lidhja implicite

Marrim këtë shembull:

Route::get('api/products/{product}', function (App\Product $product) {
    return $product->name;
});

Duke qenë se variabli $product është definuar si model i App\Product, dhe emri i tij përputhet me emrin {product} të segmentit të URL-së, në mënyrë automatike do të bëhet injektimi i instancës së modelit që ka ID korresponduese me vlerën e shënuar në URL. Nëse instanca nuk gjendet, gjenerohet gabimi 404.

Ndërrimi i emrit të çelësit

Siç u theksua më sipër, gjatë lidhjes automatike të parametrit të rutës dhe instancës së modelit korrespondues, merret parasysh ID-ja e fushës së tabelës. Nëse dëshirojmë që instanca e modelit të krijohet në bazë të një çelësi tjetër, këtë e ndryshojmë me metodën getRouteKeyName():

public function getRouteKeyName()
{
    return 'slug';
}

Në këtë rast, në vend të fushës id të tabelës, kërkimi do të bëhet në bazë të fushës slug.

Lidhja eksplicite

Lidhja eksplicite mundëson lidhjen e një parametri me emër të caktuar të rutës me instancën e një modeli të caktuar nëpër tërë aplikacionin, pa pasur nevojë të bëhet typehinting.

Në metodën boot të klasës RouteServiceProvider:

public function boot()
{
    parent::boot();
    Route::model('user', App\User::class);
}

Me këtë bëhet e mundur që kudo, në cilëndo rutë, në cilindo segment të rutës, ku përdoret parametri user, automatikisht do të injektohet instanca e modelit App\User.

Route::get('profile/{user}', function ($user) {
    //
});

Customizing The Resolution Logic

Nëse dëshirojmë ta implementojmë ndonjë logjikë tjetër të lidhjes së parametrit të rutës dhe instancës së modelit, e përdorim metodën Route::bind. Metodës bind i përcillet një Closure i cili e pranon vlerën e segmentit të URL dhe kthen instancën e klasës që duhet të injektohet në rutë. Në këtë shembull, në vend të id, përdoret fusha name e tabelës.

public function boot()
{
    parent::boot();

    Route::bind('user', function ($value) {
        return App\User::where('name', $value)->first() ?? abort(404);
    });
}

Limitimi i kërkesave

Në Laravel përfshihet një middleware që limiton qasjen në ruta. Një rute apo një grupi të rutave ia caktojmë middleware throttle, i cili pranon dy parametra që përcaktojnë numrin maksimal të kërkesave që mund të bëhen brenda një numri të caktuar të minutave, në këtë shembull 60 kërkesa brenda 1 minuti.

Route::middleware('auth:api', 'throttle:60,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Limitimi dinamik i kërkesave

Numri maksimal i qasjeve mund të jetë i ndryshëm për përdorues të ndryshëm. Nëse për shembull, modeli User e ka atributin rate_limit, ky atribut mund të përdoret nga ana e throttle middleware për ta kalkuluar numrin maksimal të kërkesave.

Route::middleware('auth:api', 'throttle:rate_limit,1')->group(function () {
    Route::get('/user', function () {
        //
    });
});

Form Method Spoofing

Formularët në HTML nuk suportojnë metodat PUT, PATCH, DELETE, ndonëse ato janë të definuara në protokolin HTTP. Laravel përdor një fushë të fshehur të quajtur _method ku si vlerë përdoren PUT, PATCH ose DELETE. Metoda e vetë formularit do të jetë POST.

Direktiva @method e Blade e gjeneron fushën _method.

Qasja e rutës aktuale

Për të marrë informatën mbi rutën aktuale, mund të përdoren metodat current, currentRouteName, dhe currentRouteAction.

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();