Download the PHP package vertilia/router without Composer

On this page you can find all versions of the php package vertilia/router. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package router

router

A lightweight http routing library tuned for performance, allowing translation of request path into controller name and validation of path parameters as defined in OpenAPI specification and (partly) in URI Template.

A highly efficient routing mechanism is especially useful in large routing tables since the number of operations to find the controller depends on the routing tree levels and not on the total number of routes in the list.

Simply saying, instead of looking up all available paths represented as a list of regular expressions, we construct a routing tree of folders from this list of paths and only visit the levels corresponding to current request. This leads us step by step to the correct route instead of blindly scanning the whole list of available routes until the matching route is found (or not). Also, the time to find incorrect routes is minimized, we don't need to scan the whole list to find out that a route is missing.

People regularly researching their access logs to discover the most frequent requests to put them higher in routes list will appreciate the functionality. These researches are now a history, and they may put their precious time on something more important.

The router algorithm is universal, in a sense that when defining routing rules, you can attach any structure to the leaf node, and it will be returned when corresponding route is provided. This leaf node is represented by an array containing at least controller element with the name of operation that will be launched by the user-land code when the route is found. If requested path contained parameters, they will be detected and injected in returned array as parameters element.

Since we believe in high effectiveness of ValidArray-based HttpRequestInterface structure in context of request handling, we also provide an HttpRequestRouter class allowing automatic registration of route parameters in request object, their validation via filters provided in leaf elements and easy access via array notation as in $request['param']. These parameters are guaranteed to be valid following the user-specified format (see tests).

High efficiency of filtering mechanism is backed by php-native filter extension.

Usage

Universal router

When instantiating a universal router you need to pass the HttpParserInterface parser object (which will translate the parameters placeholders to regexps) and a list of routing files.

HttpRequest router

In most cases you are working in CGI context, so you'll likely use an HttpRequestRouter class. This one will use OpenApiParser by default, so you will not need to inject this one, but instead you will provide an HttpRequest, from which the router will retrieve the route to lookup:

Routing file

Each routing file is a valid php script returning an array with routing information, where each entry specifies a leaf node corresponding to a route. In its simplest form it's just a controller name for specific route:

The more complex form may be used to provide filtering information for specific route, or any other information you will need. In this case instead of a string with controller name an associative array is used. The only required element here is controller, which will store the name of controller your code is looking for. Other elements may be defined as convenient:

This form (with filters element) is required if you use HttpRequestRouter version of the router, which uses filters from leaf element to store and validate detected path parameters in HttpRequest object.

In the last route filters are provided not only for path parameter id but also for description and image parameters that may come from other sources, like query, cookies, http body or headers. All of them will be filtered accordingly and accessible inside the HttpRequest object in the form of, for example, $request['description'].

If filter for path parameter is not provided explicitly, parameters element will still be injected into the returned leaf element containing all detected path parameters, but these parameters will not be validated nor registered in HttpResponse object and user will need to validate their values by other means.

Yes, you need to implement the controllers and make them available via composer autoloader or other mechanism. This is out of scope of routing library, but we have a real-world example of router use below.

Also, it's up to you to decide in which form controller names are provided to the application, whether it is a class name as we use in our examples, or method names, or function names, or even a partial string that will be completed later. Implement it the way you like. We prefer the method described above, since it has several advantages. Class names referencable via ::class constants make it simpler to type using IDE code completion. Also, they are more error-prone, since renaming a class with your IDE will either automatically rename the controller name in route file or at least display it as non-existent in there. You will not need to wait the integration or even deployment phase to discover the undefined exception. And yes, the optimisation phase described below will convert it to strings anyway.

Providing content MIME type

To be able to set different controllers and validations for different incoming content types it is also possible to provide content MIME type when defining the route, like in:

In this case content type-specific routes take precedence over generic routes, like in

If the route could not be found in content type-aware form, it is searched in generic routes.

Optimisation of routes parsing

When loading routing tables each route must be split to identify its method, path and MIME type (if present), then the path is analyzed to distinguish static paths from paths with variables, and then paths with variables are replaced by a tree structure where regular expressions allow to recognize parameters and catch variables values.

This parsing process is executed on each request, so when the number of routes is elevated, it may start to weight considerably on performance.

To go faster, we can completely bypass the parsing stage on each request by pre-compiling the routing table and save it in a native php file. Loading it on each request will take no time with active opcode caching.

To use pre-compiling method:

Example

This script needs to be executed every time the routes file is updated to translate etc/routes.php file into cache/routes-generated.php:

You may provide several input files if your routes are split between them. routec tool will output a final file with all routes combined.

On each request we don't need to parse the whole list of routes since we use already cached structure from cache/routes-generated.php:

Limitations of optimization techniques

Please be aware of the following caveats when going this way:

  1. ⚠️ Php constants that you may use to define input filters (like FILTER_VALIDATE_INT, FILTER_FLAG_HOST_REQUIRED etc.) are normally exported as their numeric values. routec tool is trying to restore constants names from these values. These values may change from version to version of php binary, so try to generate the exported routes file using the same version that will be used with setParsedRoutes() call. routec will do its best trying to replace these numeric values by their respective constants in optimized routes file, but it's in your interests to verify the result in the optimized file. Pay special attention to flags sharing the same integer value, like FILTER_FLAG_IPV4, FILTER_FLAG_HOSTNAME and FILTER_FLAG_EMAIL_UNICODE, or flags not available in all php versions, like FILTER_FLAG_GLOBAL_RANGE.

  2. ⚠️ Also, if you use validation callbacks (FILTER_CALLBACK or ValidArray::FILTER_EXTENDED_CALLBACK filters), they will not be exported at all, and you'll need to manually copy these callbacks from initial routes file.

Sample petstore.yaml specification

API specification file for this example is available from OpenAPI GitHub repository.

Routing file corresponding to the specification is as follows:

Routing format reference

Recognized format:

ROUTE is a string containing 2 or 3 parts delimited by space character:

Parts of a ROUTE:

If Content-Type header is provided within a request, and corresponding 3-parts route is not found, search is repeated with corresponding 2-parts route without CONTENT_TYPE part.

ROUTE examples:

LEAF_STRUCTURE is returned when corresponding route is found. May be of 2 types:

If scalar form is used for LEAF_STRUCTURE (like "UserResponse"), it is translated internally during parsing phase into an array with a single controller element: ["controller" => "UserResponse"]. When LEAF_STRUCTURE is returned after the route is identified, it is always returned as an array.

Examples of correct routes

LEAF_STRUCTURE returned for corresponding requests

Request METHOD PATH TYPE Returned leaf structure
GET / ["controller" => "IndexResponse"]
POST /api/users/me/login application-json ["controller" => "UserLoginResponse"]
GET /api/users/42/posts
[
"controller" => "UserPostsResponse",
"filters" => ["id" => FILTER_VALIDATE_INT],
"parameters" => ["id" => "42"],
]

All versions of router with dependencies

PHP Build Version
Package Version
Requires php Version >=7.4
vertilia/filesystem Version ^1
vertilia/parser Version ^1
vertilia/request Version ^1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package vertilia/router contains the following files

Loading the files please wait ....