Documentation/Routing

Routing

Routing is the primary task of the framework in handling incoming requests. Here, the route responsible for the request address is defined, and subsequent actions are assigned.

Sometimes routing in frameworks is also referred to as "routing," which is the same thing.

Project routes are defined by the developer in the /routes/map.php file. Other route files from the "routes" folder can be included in this file, and together they form the routing map. A notable feature of these routes is that when they are loaded, the framework checks them for overall correctness and the sequence of methods used. In case of an exception, an error is generated with a reason for the exception. Since all routes in the routing map are subject to verification, this guarantees their overall correctness.

After the first request or when using a special console command, routes are updated and cached. Therefore, route files should not include external code, only methods from the Route class.

If after making changes to the routing map, the framework does not generate characteristic messages, these messages will not appear in the future, at least until the next changes in the connected route files.

Routes are defined by methods of the Route class, one of the most commonly used being get(). The methods of this class are used exclusively in the routing map.


#Route::get() Method

This method allows you to specify the handling of the HTTP GET method under specified conditions. As shown in the example:

Route::get('/''Hello, world!');

The route will display the line "Hello, world!" when accessed at the root URL of the site. To render HTML code (which may contain PHP code) from a template, the method is used together with the view() function.


#Dynamic Addresses

The HLEB2 framework processes arbitrary addresses according to the scheme defined by the application developer, for example:

Route::get('/resource/{version}/{page}/''Dynamic address used');

In this case, all URL addresses matching the conditional scheme "site.com/resource/.../.../" will return the same text string, and the values "version" and "page" become accessible from the Hleb\Static\Request object: Request::param("version")->asString() and Request::param("page")->asPositiveInt().
These values can also be retrieved from the container and through the same-named arguments of the controller method.

In the route address, you may specify that the last part can be optional:

Route::get('/profile/user/{id?}/''Variable ID value');

Route::get('/contacts/form?/''Optional end part');

If the address is missing, it will still match this route, but the value of 'id' will be NULL.


#Default Values for Dynamic Addresses

An example of a dynamic route in which default values are specified for the second and third named parts.

Route::get('/example/{first}/{second:two}/{third:three?}''defaults value in dynamic route');

Similar to '/example/{first}/two/three?', only in the given Request, additional values 'second' => 'two', 'third' => 'three' will be added to the already existing dynamic parameter 'first'. If the final parameter is absent, it will be null.


#Variable Addresses

Multiple route assignments (a numbered array of URL segments will appear in Request::param()):

Route::get('/example/...0-5/''From 0 to 5 arbitrary parts');
// or
Route::get('/example/...1-3,7,9,11-20/''Number of parts within the specified range');

#Tag in Address

The framework does not allow interpreting parts of the URL as compound segments, as this contradicts standards, but there is an exception to this rule.
A common scenario is when a user's login is prefixed with a special @ tag in the URL. It can be set as follows:

Route::get('/profile/@{username}''Username with tag');

#Function view()

The function specifies which template from the /resources/views/ folder to associate with the route. Example for the file /resources/views/index.php:

Route::get('/'view('index'));

Variables can be passed to the function as a second argument in an associative array.

Route::get('/'view('index', ['title' => 'Index page']));

The variables will be available in the template.

<?php
// File /resources/views/index.php

/** @var string $title */
echo $title// Index page

For predefined addresses '404', '403', and '401', the corresponding standard error page will be displayed in the view() function.


#Function preview()

Sometimes, to specify a certain predefined text response in the route, it is necessary to set the appropriate Content-Type header and output certain request parameters. Currently, only the injection of the original route address, dynamic parameters from the address, and the HTTP request method is available. For example:

Route::any('/page/{name}'preview('Current route {{route}}, request parameter {%name%}, request method {{method}}'));

#Function redirect()

The redirect() method is used to specify address redirections in routes. It can contain links to internal or external URLs and can also include dynamic query parameters from the original route:

Route::get('/old/address/{name}')->redirect('/new/address/{%name%}'301);

#Route Grouping

Route grouping is used to assign common properties to routes by adding methods to groups, which then apply the method's action to the entire group.
The scope of a group is defined using the toGroup() method at the beginning of the group and endGroup() at the end.

Route::toGroup()->prefix('example');

    
// /example/first/page/
    
Route::get('first/page''First page content');
    
// /example/second/page/
    
Route::get('second/page''Second page content');

Route::endGroup();

In this case, the prefix() method added to the group applies to all routes within it.

Groups can be nested within other groups. There is also an alternative syntax for groups:

Route::toGroup()
    ->
prefix('example')
    ->
group(function () {
        
// /example/first/page/
        
Route::get('first/page''First page content');
        
// /example/second/page/
        
Route::get('second/page''Second page content');
    });

#Named Routes

Each route can be assigned a unique name.

Route::get('/'view('default'))->name('homepage');

This name can be used to generate its URL, making the code independent of the actual URL addresses.
This is achieved by using route names instead of addresses. For example, this site operates using route names to build links to pages.


#Handling HTTP Methods

Similar to the get() method for the HTTP GET method, there are methods like post(), put(), patch(), delete(), options() corresponding to POST, PUT, PATCH, DELETE, OPTIONS.

These methods match their respective HTTP methods, except for options().
In all other cases, the OPTIONS method is handled according to the standard, but with options(), you can separately define how OPTIONS requests are processed (redefine them).

Route::options('/ajax/query/''...')->controller(OptionsController::class);

Route::post('/ajax/query/''{"result": "ok"}')->name('post.example.query');

#Route::any() Method

Assigned to a route, it matches all HTTP methods, behaving otherwise like get().


#Route::match() Method

Similar to the get() method, but with an additional first argument where you can pass an array of the supported HTTP methods.

Route::match(['get''post'], '/''Handler for POST and GET methods');

#Route::fallback() Method

Catches all unmatched paths for all HTTP methods (or specified ones). There can only be one fallback() method in routes for a specific HTTP method.

This allows you to assign handling for an unmatched route (instead of a 404 error) for all types of HTTP methods or individually.


#Route Protection

To protect routes from CSRF attacks, the protect() method is used. Assigning it to a route or group of routes adds a check for the presence of a special token set previously.

Route::get'/ajax/query''Protected route')->protect();

It works as follows:
An access token is output on the page, you can use the csrf_token() or csrf_field() function.
This token is sent via JavaScript or in a form with the request.
The request's route has the protect() method and checks the token.


#Controller Assignment

Controller is a part of the MVC architecture (Action-Domain-Responder for the web), responsible for the subsequent handling of a request identified by the router but should not contain business logic.

A controller cannot be used for a group of routes; it is assigned to a specific one or individually. The controller() method is used for this.

use App\Controllers\DefaultController;

Route::get('/')->controller(DefaultController::class, 'index');

In the example, the first argument is the class of the assigned controller, the second is the controller method used. The 'index' method can be omitted as it is used by default.
Note that the get() method no longer needs a second argument when a controller is used.


#Middleware Controllers

If a controller can only be assigned once to a route, multiple middlewares can be applied. You can also assign a middleware to a group of routes.

Route::toGroup()
    ->
middleware(FirstGeneralMiddleware::class)
    ->
middleware(SecondGeneralMiddleware::class);

    
Route::get('/example''...')->middleware(GetMiddleware::class);
    
Route::post('/example''...')->middleware(PostMiddleware::class);

Route::endGroup();

The middleware() method means that the middleware will be executed before the main route handler. There is a similar method, before(), and a method after() (which runs after the main handler). The main handler here refers to the text returned by the route, the assigned template, or the execution of the controller.

Assigned middlewares are executed in the order they are declared.

The arguments for the middleware method are similar to the controller. You can specify the method to be executed as the second argument, with the default being 'index'. The difference is the presence of a third argument, which can pass an array of parameters to the middleware. These parameters are available in the Hleb\Static\Router::data() method or via the container.


#Modules

A module is a type of controller. It points to the project's /modules/ directory and contains the name of the module being used.

Route::get('/section/')->module('default'DefaultModuleController::class);

#Where() Method Validation

A route can have dynamic parts in its URL, and with the where() method, you can define rules for those parts.

Route::toGroup()
    ->
prefix('/{lang}/')
    ->
where(['lang' => '[a-z]{2}']);

    
Route::post('/profile/{user}/{id}''...')
        ->
where(['user' => '/[a-z]+/i''id' => '[0-9]+']);

Route::endGroup();

In this example, the parts named 'lang', 'user', and 'id' will be validated using regular expressions.


#Domain Limitation

The special method domain() can be assigned to a route or group of routes.
The first argument can specify the domain or subdomain name, and the second argument defines the level of rule matching.


#Substitution Principle

There is a method where the target controller and method are determined based on the values of the dynamic URL.
In this case, the route might look like this:

Route::get('/page/{controller}/{method}')
    ->
controller('Main<controller>Controller''init<method>');

In this example, for the URL /page/part/first/, the framework will attempt to determine the controller as 'MainPartController' and the method as 'initFirst' (converted following the camelCase principle).

The substitution principle in handlers should be managed carefully, as URL data may lead to unexpected controllers or methods being invoked.

Additionally, you can specify dependencies on the request HTTP method by using the key '[verb]'.

Route::match(['get''post'], '/page/{target}')
    ->
controller('Main<target>[verb]Controller''[verb]Method>');

In this example, for the URL /page/example/, the framework will attempt to determine the controller as 'MainExampleGetController' and the method as 'getMethod' (converted following the camelCase principle).
For the POST method, these will be 'MainExamplePostController' and 'postMethod'.

The ability to perform substitutions can be particularly useful when distributing request HTTP methods across controller methods.


#Updating Route Cache

By default, the route cache in the framework is automatically updated after changes are made to the /routes/map.php file. There is also a console command to update the route cache:

$php console --routes-upd

For high-traffic projects, you might need to disable automatic updates in production and only recalculate the route cache using the console command.
This is configured via the 'routes.auto-update' setting in the /config/common.php file.

Using Hosting Controller

Page translated: chatgpt 4-o
Back to top