Routing
Basic Routing
The fundamental concept of basic routing in Dreamfork involves specifying a URI along with a closure, offering a straightforward and expressive approach to defining routes and their behavior. This method simplifies the process, eliminating the need for complex routing configuration files:
use Framework\Support\Facades\Route;
Route::get('/welcome', function() {
return 'Welcome!';
});
The Default Interfaces
All routes in Dreamfork are defined in files located within the routes folder. By default, these files are automatically loaded by the App\Providers\RouteServiceProvider. This provider encompasses the definition of all route interfaces, allowing for customization of their settings. For instance, it is possible to disconnect a specific interface, modify its prefix, or add request/response headers directly in this provider.
For example, if you intend for your application to solely function as a backend API, you can disable the web interface in App\Providers\RouteServiceProvider by setting enabled to false. Within the routes folder, each interface has its own file. The default files are routes/web.php and routes/api.php Routes defined in routes/web.php are treated as HTTP routes by default and have no prefix. This means that you can access the following route by navigating to http://example.com/user in your browser:
// routes/web.php
use Framework\Support\Facades\Route;
Route::get('/user', [UserController::class, 'index']);
Routes specified in the routes/api.php file are encapsulated within a route group by the App\Providers\RouteServiceProvider. This grouping automatically applies the /api URI prefix to all routes within the file, eliminating the need for manual application to each route. To customize the prefix and other options for the route group, adjustments can be made within your RouteServiceProvider class.
The Custom Interfaces
In Dreamfork, creating custom interfaces is a straightforward process. To achieve this, you need to define your interface in the RouteServiceProvider:
// RouteServiceProvider
private $availableInterfaces = [
...
'rss' => [
'enabled' => true,
'prefix' => '/rss',
'request-headers' => [],
'response-headers' => []
]
];
Afterward, you should create a file with the name of your interface in the routes folder. In this example, the file is named rss.php In this file, you can define the routes that should be accessible for this interface:
// routes/rss.php
use Framework\Support\Facades\Route;
Route::get('/feed', function() {
return 'RSS feed';
});
Available Router Methods
The router provides the ability to register routes that respond to various HTTP verbs. You can use the following methods to register routes for specific HTTP verbs:
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);
In certain cases, you may need to register a route that responds to all HTTP verbs. The any method allows you to achieve this by registering a route that responds to any HTTP verb:
Route::any('/welcome', function() {
return 'Welcome!';
});
When using the same URI for multiple routes, prioritize the order of declaration. Place routes using
get,post,put,patch,delete, andoptionsmethods before those using theanymethod. This ensures proper matching of incoming requests with the intended route.
Using Controllers In Routing
In addition to using closures as callbacks, you can streamline your routes by passing controllers and their associated methods. Instead of providing a callback, you can specify the exact controller and method to be invoked. Routes automatically map controllers from the App\Controllers folder, eliminating the need to explicitly define them in the routes file.
// routes/web.php
use Framework\Support\Facades\Route;
Route::get('/user', [UserController::class, 'index']);
In this case, the UserController controller's index method will be called when the specified route is accessed.
Due to automatic mapping, controllers passed in routes must reside in the
App\Controllersfolder. Ensure that the controllers are properly located in this directory to avoid routing issues.
Route Parameters
Required Parameters
To capture segments of the URI in your route, use route parameters. For instance, if you need to extract a user's ID from the URL, define a route parameter like this:
Route::get('/user/{id}', function (string $id) {
return 'User '.$id;
});
You can define multiple route parameters as needed:
Route::get('/user/{id}/history/{historyId}', function (string $id, string $historyId) {
// ...
});
Route parameters are enclosed in curly braces {}, and they should consist of alphanumeric characters. Underscores (_) are also allowed in parameter names. Parameters are injected into route callbacks/controllers based on their order; the names of the callback/controller arguments do not impact the injection process.
Global Parameters
In every route, two parameters, namely $request and $routes, are automatically injected. These parameters, of types Framework\Http\Request and Framework\Http\Routing\RouteCollection, provide access to essential information regardless of the specific parameters defined for a given route.
You can always access these global parameters, even if no additional parameters for them are specified for a particular route:
Route::get('/user/{uid}', function ($request, $routes, $uid) {
// Access $request and $routes here
});
The $request parameter allows you to retrieve information about the incoming HTTP request, while $routes provides access to the collection of defined routes in your application. These global parameters are injected automatically and can be utilized as needed in your route callbacks or controllers.
It's important to note that global parameters are automatically injected into the first available position among the function arguments. This means that if you define a route parameter to capture a segment but use a different name in the function than the one assigned to the parameter, the argument in the function will be mapped to the first one available global parameter.
Route::get('/user/{id}', function ($uid) {
// $uid is mapped to $request, not to the 'id' parameter defined in the route
});
In this scenario, $uid will be mapped to the $request global parameter, not to the id parameter defined in the route. Always consider the automatic injection order when working with global route parameters.
Route Groups
Route groups provide a convenient way to share route attributes, such as a prefix or authentication requirements, among a multitude of routes. This eliminates the need to specify these attributes individually for each route, promoting cleaner and more efficient route organization.
Group
To include routes within a group, you can use the group method. The first argument to this method is the group's prefix, and the second argument is a callback function containing the routes. For example:
Route::group('/auth', function () {
Route::post('/register', function() {
// ...
});
Route::post('/login', function() {
// ...
});
});
In this way, routes within the group will be generated with the path prefix /auth, resulting in paths like /auth/register.
Guard
To place routes within a middleware guard, ensuring that specific paths are accessible only after successful authentication, use the guard method. Provide a callback function as an argument, containing the desired routes. The guard verifies the authenticity of the request by passing it through an authentication service that utilizes tokenization:
Route::guard(function () {
Route::get('/user', function() {
// ...
});
});
In this case, the routes within the guard will be protected, and access will be granted only to authenticated users. The authentication process involves tokenization, ensuring secure validation of the incoming requests.
Fallback Routes
Using the Route::fallback method, you can designate a route to execute when no other route matches the incoming request.
Route::fallback(function () {
return "Route does not exist";
});
It's important to note that the fallback route should always be the last route registered by your application.
Cross-Origin Resource Sharing (CORS)
Dreamfork can automatically respond to CORS OPTIONS HTTP requests with default configured values. The OPTIONS requests are handled seamlessly by the HandleCors middleware.
If you need to modify the CORS configuration to suit your specific requirements, you can do so in the config/cors.php file. This configuration file contains detailed descriptions of all available options, allowing you to customize the CORS settings according to your needs.
For more information about CORS, please check the MDN web documentation on CORS.