Wat de backend betreft, komt elke developer uiteindelijk wel in aanraking met routes. Routes kunnen worden beschouwd als de ruggengraat van de backend, omdat elk verzoek dat de server ontvangt wordt doorgestuurd naar een controller via een routinglijst die verzoeken koppelt aan controllers of acties.

Laravel verbergt veel informatie over de uitvoering voor ons en bevat veel syntactic sugar om zowel nieuwe als ervaren developers te helpen bij de ontwikkeling van hun webapplicaties.

Laten we dus eens goed bekijken hoe je routes beheert in Laravel.

Backend routing en cross-site scripting in Laravel

Op een server bestaan zowel public als private routes. Public routes kunnen een bron van zorg zijn vanwege de mogelijkheid van cross-site scripting (XSS), een soort injectie-aanval die jou en je gebruikers kwetsbaar kan maken voor hackers.

Het probleem is dat een gebruiker kan worden omgeleid van een route waarvoor geen sessietoken nodig is naar een route waarvoor dat wel nodig is – en hij heeft nog steeds toegang zonder het token.

De eenvoudigste manier om dit probleem op te lossen is om een nieuwe HTTP header af te dwingen en “referrer” toe te voegen aan de route om dit scenario te beperken:

'main' => [
  'path' => '/main',
  'referrer' => 'required,refresh-empty',
  'target' => ControllerDashboardController::class . '::mainAction'
]

Laravel basic routing

In Laravel stellen routes gebruikers in staat om het juiste verzoek naar de gewenste controller te routen. De meest elementaire Laravel Route accepteert een Uniform Asset Identifier (je route path) en een afsluiting die zowel een functie als een klasse kan zijn.

In Laravel worden routes gemaakt in de bestanden web.php en api.php. Laravel wordt standaard geleverd met twee routes: één voor het WEB en één voor de API.

Deze routes staan in de map routes/, maar ze worden geladen in de Providers/RouteServiceProvider.php.

Standaard state van route service provider van Laravel in de command line.
Standaard state van route service provider van Laravel.

In plaats daarvan kunnen we de routes rechtstreeks laden in RouteServiceProvider.php, waarbij we de map routes/ helemaal overslaan.

Laravel routes direct laden in de provider via de command line
Laravel routes direct laden in de provider.

Redirects

Bij het definiëren van een route, zullen we meestal de gebruiker die er toegang toe krijgt willen omleiden, en de redenen daarvoor variëren nogal. Het kan zijn omdat het een verouderde route is en we de backend of de server hebben veranderd, of het kan zijn omdat we twee-factor authenticatie (2FA) willen installeren, enzovoort.

Laravel heeft een eenvoudige manier om dit te doen. Dankzij de eenvoud van het framework kunnen we de redirect methode gebruiken op de Route facade, die de entry route accepteert en de route waarnaar moet worden doorgestuurd.

Optioneel kunnen we als derde parameter de statuscode voor de redirect meegeven. De methode permanentRedirect doet hetzelfde als de methode redirect, behalve dat hij altijd een 301 statuscode teruggeeft:

// Simple redirect
Route::redirect("/class", "/myClass");

// Redirect with custom status
Route::redirect("/home", "/office", 305);

// Route redirect with 301 status code
Route::permanentRedirect("/home", "office");

Binnen de redirect routes is het verboden om de “destination” en “status” keywords als parameters te gebruiken, omdat die door Laravel zijn gereserveerd.

// Illegal to use
Route::redirect("/home", "/office/{status}");

Views

Views zijn de .blade.php bestanden die we gebruiken om de frontend van onze Laravel applicatie te renderen. Het gebruikt de blade templating engine, en het is de standaard manier om een full-stack applicatie te bouwen met alleen Laravel.

Als we willen dat onze route een view teruggeeft, kunnen we eenvoudigweg de view methode op de Route facade gebruiken. Deze accepteert een route parameter, een view naam, en een optionele array van waarden die aan de view worden doorgegeven.

// When the user accesses my-domain.com/homepage
// the homepage.blade.php file will be rendered
Route::view("/homepage", "homepage");

Laten we aannemen dat onze view “Hello, {name}” wil zeggen door een optionele array met die parameter door te geven. Dat kunnen we doen met de volgende code (als de ontbrekende parameter vereist is in de view , zal het verzoek mislukken en een fout geven):

Route::view('/homepage', 'homepage', ['name' => "Kinsta"]);

Routelijst

Naarmate je applicatie groter wordt, groeit ook het aantal verzoeken dat geroutet moet worden. En met een grote hoeveelheid informatie kan verwarring ontstaan.

Dit is waar het artisan route:list commando ons kan helpen. Het geeft een overzicht van alle routes die in de applicatie zijn gedefinieerd, hun middlewares en controllers.

php artisan route:list

Dit toont een lijst van alle routes zonder de middlewares. Hiervoor moeten we de flag -v gebruiken:

php artisan route:list -v

In een situatie waarin je misschien een domein-gestuurd ontwerp gebruikt waarbij je routes specifieke namen in hun paden hebben, kun je als volgt gebruik maken van de filtermogelijkheden van dit commando:

php artisan route:list –path=api/account

Hiermee worden alleen de routes getoond die beginnen met api/account.

Aan de andere kant kunnen we Laravel opdragen om extern gedefinieerde routes uit te sluiten of op te nemen door de opties –except-vendor of –only-vendor te gebruiken.

Route parameters

Soms moet je met de route segmenten van de URI vastleggen, zoals een user ID of token. We kunnen dit doen door een routeparameter te definiëren, die altijd wordt omsloten door accolades ({}) en alleen mag bestaan uit alfabetische tekens.

Als onze routes dependencies bevatten in hun callbacks, zal de Laravel service container ze automatisch injecteren:

use IlluminateHttpRequest;
use Controllers/DashboardController;
Route::post('/dashboard/{id}, function (Request $request, string $id) {
  return 'User:' . $id;
}
Route::get('/dashboard/{id}, DashboardController.php);

Vereiste parameters

De vereiste parameters van Laravel zijn parameters in routes die we niet mogen overslaan bij een call. Anders wordt er een fout teruggegeven:

Route::post("/gdpr/{userId}", GetGdprDataController.php");

Nu hebben we binnen de GetGdprDataController.php direct toegang tot de $userId parameter.

public function __invoke(int $userId) {
  // Use the userId that we received…
}

Een route kan een willekeurig aantal parameters aannemen. Ze worden geïnjecteerd in de route callbacks/controllers op basis van de volgorde waarin ze staan:

 // api.php
Route::post('/gdpr/{userId}/{userName}/{userAge}', GetGdprDataController.php);
// GetGdprDataController.php
public function __invoke(int $userId, string $userName, int $userAge) {
  // Use the parameters…
}

Optionele parameters

In een situatie waarin we iets willen doen op een route wanneer alleen een parameter aanwezig is en niets anders, zonder de hele applicatie te beïnvloeden, kunnen we een optionele parameter toevoegen. Deze optionele parameters worden aangeduid met ?:

 Route::get('/user/{age?}', function (int $age = null) {
  if (!$age) Log::info("User doesn't have age set");
  else Log::info("User's age is " . $age);
}
Route::get('/user/{name?}', function (int $name = "John Doe") {
  Log::info("User's name is " . $name);
}

Route wildcard

Laravel biedt ons een manier om te filteren hoe onze optionele of verplichte parameters eruit moeten zien.

Stel dat we een string van een user ID willen. We kunnen dit valideren op routeniveau met de methode where.

De methode where accepteert de naam van de parameter en de regex regel die zal worden toegepast op de validatie. Standaard neemt het de eerste parameter, maar als we er veel hebben, kunnen we een array doorgeven met de naam van de parameter als key en de regel als waarde, en Laravel zal ze allemaal voor ons parsen:

Route::get('/user/{age}', function (int $age) {
  //
}->where('age', '[0-9]+');
Route::get('/user/{age}', function (int $age) {
  //
}->where('[0-9]+');
Route::get('/user/{age}/{name}', function (int $age, string $name) {
  //
}->where(['age' => '[0-9]+', 'name' => '[a-z][A-z]+');

We kunnen nog een stap verder gaan en validatie toepassen op alle routes in onze applicatie door de methode pattern te gebruiken op de Route facade:

 Route::pattern('id', '[0-9]+');

Dit zal elke id parameter valideren met deze regex expressie. En als we die eenmaal gedefinieerd hebben, wordt hij automatisch toegepast op alle routes die die parameternaam gebruiken.

Zoals we kunnen zien, gebruikt Laravel het teken / als scheidingsteken in het pad. Als we het in het pad willen gebruiken, moeten we expliciet toestaan dat het deel uitmaakt van onze placeholder met behulp van een where regex.

 Route::get('/find/{query}', function ($query) {
  //
})->where('query', , '.*');

Het enige nadeel hierbij is dat het alleen wordt ondersteund in het laatste routesegment.

Routes met een naam

Zoals het kopje al aangeeft, kunnen we routes een naam geven, zogenaamde named routes, wat het handig maakt om URL’s of omleidingen te genereren voor specifieke routes.

Zo maak je named routes

Een eenvoudige manier om een route met naam aan te maken wordt geboden door de methode name die aan de Route facade is gekoppeld. De naam van elke route moet uniek zijn:

 Route::get('/', function () {
})->name("homepage");

Routegroepen

Met routegroepen kun je route-attributen zoals middlewares delen over een groot aantal routes zonder ze op elke route opnieuw te hoeven definiëren.

Middleware

Door een middleware toe te wijzen aan alle routes die we hebben, kunnen we ze combineren in een groep, eerst door de methode group te gebruiken. Eén ding om rekening mee te houden is dat de middlewares worden uitgevoerd in de volgorde waarin ze op de groep worden toegepast:

 Route:middleware(['AuthMiddleware', 'SessionMiddleware'])->group(function () {
  Route::get('/', function() {} );
  Route::post('/upload-picture', function () {} );
});

Controllers

Als een groep dezelfde controller gebruikt, kunnen we de methode controller gebruiken om de gemeenschappelijke controller voor alle routes binnen die groep te definiëren. Nu moeten we de methode specificeren die de route zal callen.

 Route::controller(UserController::class)->group(function () {
  Route::get('/orders/{userId}', 'getOrders');
  Route::post('/order/{id}', 'postOrder');
});

Subdomeinroutes

Een subdomeinnaam is een stukje extra informatie dat wordt toegevoegd aan het begin van de domeinnaam van een website. Hiermee kunnen websites hun inhoud voor specifieke functies, zoals online winkels, blogs, presentaties, enzovoort, scheiden en organiseren van de rest van de website.

Onze routes kunnen worden gebruikt om routing van subdomeinen af te handelen. We kunnen het domein en een deel van het subdomein opvangen voor gebruik in onze controller en route. Met behulp van de domain methode op de Route facade kunnen we onze routes groeperen onder een enkel domein:

 Route::domain('{store}.enterprise.com')->group(function() {
  Route::get('order/{id}', function (Account $account, string $id) {
    // Your Code
  }
});

Prefixes en naamprefixes

Wanneer we een groep routes hebben, kunnen we in plaats van ze één voor één aan te passen, gebruik maken van de extra hulpprogramma’s die Laravel biedt, zoals prefix en name op de Route facade.

De methode prefix kan gebruikt worden om elke route in de groep te prefixen met een gegeven URI, en de methode name kan gebruikt worden om elke routenaam te prefixen met een gegeven string.

Hierdoor kunnen we nieuwe dingen maken zoals admin routes zonder dat we elke naam of prefix hoeven aan te passen om ze te identificeren:

 Route::name('admin.")->group(function() {
  Route::prefix("admin")->group(function() {
    Route::get('/get')->name('get');
    Route::put('/put')->name(put');
    Route::post('/post')->name('post');
  });
});

Nu worden de URI’s voor deze routes admin/get, admin/put, admin/post, en de namen admin.get, admin.put, en admin.post.

Routecaching

Bij het uitrollen van de applicatie naar productieservers zal een goede Laravel developer gebruik maken van Laravel’s routecache.

Wat is routecaching?

Routecaching vermindert de tijd die nodig is om alle routes van de applicatie te registreren.

Met php artisan route:cache wordt een instance van Illuminate/Routing/RouteCollection gegenereerd, en na te zijn gecodeerd, wordt de geserialiseerde uitvoer geschreven naar bootstrap/cache.routes.php.

Nu zal elk ander verzoek dit cachebestand laden, als het bestaat. Daarom hoeft onze applicatie niet langer entries uit het routebestand te parsen en om te zetten in Illuminate/Routing/Route objecten in Illuminate/Routing/RouteCollection.

Waarom het belangrijk is om routecaching te gebruiken

Als je de routecaching feature van Laravel niet gebruikt, loop je het risico dat je applicatie langzamer draait dan hij zou kunnen, wat weer kan leiden tot minder sales, minder gebruikers en minder vertrouwen in je merk.

Afhankelijk van de schaal van je project en hoeveel routes er zijn, kan een eenvoudig routecaching commando je applicatie versnellen met 130% tot 500% – een enorme winst voor bijna geen moeite.

Samenvatting

Routing is de ruggengraat van backenddevelopment. Het Laravel framework blinkt hierin uit door een eenvoudige manier om routes te definiëren en te beheren.

Laravel maakt development veel toegankelijker en helpt om op een eenvoudige manier een app te versnellen.

Welke andere trucs en tips ben jij tegengekomen met betrekking tot Laravel routes? Laat het ons weten in de commentsectie!

Coman Cosmin

Cosmin Coman is een technologisch schrijver en developer met meer dan 3 jaar ervaring. Naast het schrijven voor Kinsta heeft hij meegewerkt aan onderzoek bij kernfysische faciliteiten en universiteiten. Hij is technisch onderlegd en geïntegreerd in de gemeenschap en komt altijd met innovatieve oplossingen.