hyperf/docs/en/router.md
2022-11-15 14:02:31 +08:00

10 KiB

Routing

By default, routing uses the nikic/fast-route package. The hyperf/http-server component is responsible for connecting to the Hyperf server while RPC routing is implemented by hyperf/rpc-server component.

HTTP routing

Define routing via configuration file

Under the hyperf-skeleton skeleton, all routing definitions are defined in the config/routes.php file by default. Hyperf also supports annotation routing, which is the recommended method, especially when there are a lot of routes.

Defining routes using closures

Only a URI and a closure (Closure) are needed to construct a basic route:

<?php
use Hyperf\HttpServer\Router\Router;

Router::get('/hello-hyperf', function () {
    return 'Hello Hyperf.';
});

You can now request http://host:port/hello-hyperf through a browser or the cURL command line to access the route.

Define standard routing

The so-called standard routing refers to the routing handled by the controllers and actions. This method is quite similar to the closure definition with the obvious difference that business logic can be delegated to respective controller classes:

<?php
use Hyperf\HttpServer\Router\Router;

// Any of the following three definitions can achieve the same effect
Router::get('/hello-hyperf', 'App\Controller\IndexController::hello');
Router::get('/hello-hyperf', 'App\Controller\IndexController@hello');
Router::get('/hello-hyperf', [App\Controller\IndexController::class, 'hello']);

The route is defined as binding the /hello-hyperf path to the hello method under App\Controller\IndexController.

Available routing methods

The router provides multiple methods to help you register any HTTP request routing:

use Hyperf\HttpServer\Router\Router;

// Register the route of the HTTP METHOD consistent with the method name
Router::get($uri, $callback);
Router::post($uri, $callback);
Router::put($uri, $callback);
Router::patch($uri, $callback);
Router::delete($uri, $callback);
Router::head($uri, $callback);

// Register the route of any HTTP METHOD
Router::addRoute($httpMethod, $uri, $callback);

Sometimes you may need to register a route that can correspond to multiple different HTTP methods at the same time. This can be achieved by using the addRoute method:

use Hyperf\HttpServer\Router\Router;

Router::addRoute(['GET','POST','PUT','DELETE'], $uri, $callback);

How to define route groups

The route group adds the group prefix to each URI. The actual route is group/route, namely /user/index, /user/store, /user/update, /user/delete

Router::addGroup('/user/', function (){
    Router::get('index', 'App\Controller\UserController@index');
    Router::post('store', 'App\Controller\UserController@store');
    Router::get('update', 'App\Controller\UserController@update');
    Router::post('delete', 'App\Controller\UserController@delete');
});

Define routing via annotations

Hyperf provides a very convenient annotation routing function. You can directly define a route by defining #[Controller] or #[AutoController] annotations on any class.

AutoController annotation

#[AutoController] provides routing binding support for most simple access scenarios. When using #[AutoController], Hyperf will automatically parse all the public methods of the class it is in and provide both GET and POST Request method.

When using #[AutoController] annotation, use Hyperf\HttpServer\Annotation\AutoController; namespace is required.

Pascal case controller names will be converted to snake_case automatically. The following is an example of the correspondence between the controller, annotation and the resulting route:

Controller Annotation Route URI
MyDataController #[AutoController] /my_data/index
MydataController #[AutoController] /mydata/index
MyDataController #[AutoController(prefix: "/data")] /data/index
<?php
declare(strict_types=1);

namespace App\Controller;

use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;

#[AutoController]
class UserController
{
    // Hyperf will automatically generate a /user/index route for this method, allowing requests via GET or POST
    public function index(RequestInterface $request)
    {
        // Obtain the id parameter from the request
        $id = $request->input('id', 1);
        return (string)$id;
    }
}

Controller annotation

#[Controller] exists to meet more detailed routing definition requirements. The use of the #[Controller] annotation is used to indicate that the current class is a controller class, and the #[RequestMapping] annotation is required to update the detailed definition of request method and URI.

We also provide a variety of quick and convenient mapping annotations, such as #[GetMapping], #[PostMapping], #[PutMapping], #[PatchMapping] and #[DeleteMapping], each corresponding with a matching request method.

  • When using #[Controller] annotation, use Hyperf\HttpServer\Annotation\Controller namespace is required.
  • When using #[RequestMapping] annotation, use Hyperf\HttpServer\Annotation\RequestMapping namespace is required.
  • When using #[GetMapping] annotation, use Hyperf\HttpServer\Annotation\GetMapping namespace is required.
  • When using #[PostMapping] annotation, use Hyperf\HttpServer\Annotation\PostMapping namespace is required.
  • When using #[PutMapping] annotation, use Hyperf\HttpServer\Annotation\PutMapping namespace is required.
  • When using #[PatchMapping] annotation, use Hyperf\HttpServer\Annotation\PatchMapping namespace is required.
  • When using #[DeleteMapping] annotation, use Hyperf\HttpServer\Annotation\DeleteMapping namespace is required.
<?php
declare(strict_types=1);

namespace App\Controller;

use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;

#[Controller]
class UserController
{
    // Hyperf will automatically generate a /user/index route for this method, allowing requests via GET or POST
    #[RequestMapping(path: "index", methods: "get,post")]
    public function index(RequestInterface $request)
    {
        // Obtain the id parameter from the request
        $id = $request->input('id', 1);
        return (string)$id;
    }
}

Annotation parameters

Both #[Controller] and #[AutoController] provide two parameters, prefix and server.

prefix represents the URI prefix for all methods under the controller, the default is the lowercase of the class name. For example, in the case of UserController, the prefix defaults to user, so if the controller method is index, then the final route is /user/index. It should be noted that the prefix is not always used: when the path of a method in a class starts with /, it means that the path is defined as an absolute URI and the value of prefix will be ignored. At the same time, if the prefix attribute is not set, then the part after \\Controller\\ in the controller class namespace will be used as the route prefix in SnakeCase style.

server indicates which server the route is defined for. Since Hyperf supports starting multiple servers at the same time, there may be multiple HTTP servers running at the same time. Therefore defining the server parameter can be used to distinguish which server the route is defined for. The default is http.

Route parameters

Given route parameters must be consistent with the controller parameter key name and type, otherwise the controller cannot accept the relevant parameters

Router::get('/user/{id}', 'App\Controller\UserController::info');

Access route parameter via controller method injection.

public function info(int $id)
{
    $user = User::find($id);
    return $user->toArray();
}

Access route parameter via request object.

public function index(RequestInterface $request)
{
    // If it exists, it will return, if it does not exist, it will return the default value null
    $id = $request->route('id');
    // If it exists, it returns, if it doesn't exist, it returns the default value 0
    $id = $request->route('id', 0);
}

Required parameters

We can define required route parameters using {}. For example, /user/{id} declares that id is a required parameter.

Optional parameters

Sometimes you may want a route parameter to be optional. In this case, you can use [] to declare the parameter inside the brackets as an optional parameter, such as /user/[{id}].

Get routing information

If the devtool component is installed, you can use the php bin/hyperf.php describe:routes command to get the routing list information. You can also provide the path option, which is convenient for obtaining the information of a single route, for example: php bin/hyperf.php describe:routes --path=/foo/bar.

HTTP exceptions

When the route fails to match the route, such as route not found (404), request method not allowed (405) and other HTTP exceptions, Hyperf will uniformly throw an exception that inherits the Hyperf\HttpMessage\Exception\HttpException class. You need to manage these exceptions through the ExceptionHandler mechanism and do the corresponding response processing. By default, you can directly use the Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler provided by the component for exception capture and processing. Not that you need to configure this exception handler in the config/autoload/exceptions.php configuration file and ensure that the sequence link between multiple exception handlers is correct. When you need to customize the response to HTTP exceptions such as route not found (404) and request method not allowed (405), you can directly implement your own exception handling based on the code of HttpExceptionHandler And configure your own exception handler. For the logic and usage instructions of the exception handler, please refer to Exception Handling.