hyperf/docs/en/router.md

214 lines
10 KiB
Markdown
Raw Normal View History

# Routing
2019-05-08 00:05:14 +08:00
By default, routing uses the [nikic/fast-route](https://github.com/nikic/FastRoute) package. The [hyperf/http-server](https://github.com/hyperf/http-server) component is responsible for connecting to the `Hyperf` server while `RPC` routing is implemented by [hyperf/rpc-server](https://github.com/hyperf/rpc-server) component.
2019-05-08 00:05:14 +08:00
## HTTP routing
2019-05-08 00:05:14 +08:00
### Define routing via configuration file
2019-05-08 00:05:14 +08:00
Under the [hyperf-skeleton](https://github.com/hyperf/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.
2019-05-08 00:05:14 +08:00
#### Defining routes using closures
2019-05-08 00:05:14 +08:00
Only a URI and a closure (Closure) are needed to construct a basic route:
2019-05-08 00:05:14 +08:00
```php
<?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.
2019-05-08 00:05:14 +08:00
#### Define standard routing
2019-05-08 00:05:14 +08:00
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:
2019-05-08 00:05:14 +08:00
```php
<?php
use Hyperf\HttpServer\Router\Router;
// Any of the following three definitions can achieve the same effect
2019-05-08 00:05:14 +08:00
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`.
2019-05-08 00:05:14 +08:00
#### Available routing methods
2019-05-08 00:05:14 +08:00
The router provides multiple methods to help you register any HTTP request routing:
2019-05-08 00:05:14 +08:00
```php
use Hyperf\HttpServer\Router\Router;
// Register the route of the HTTP METHOD consistent with the method name
2019-05-08 00:07:01 +08:00
Router::get($uri, $callback);
Router::post($uri, $callback);
Router::put($uri, $callback);
Router::patch($uri, $callback);
Router::delete($uri, $callback);
Router::head($uri, $callback);
2019-05-08 00:05:14 +08:00
// Register the route of any HTTP METHOD
2019-05-08 00:05:14 +08:00
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:
2019-05-08 00:05:14 +08:00
```php
use Hyperf\HttpServer\Router\Router;
Router::addRoute(['GET','POST','PUT','DELETE'], $uri, $callback);
2019-06-24 00:28:29 +08:00
```
#### How to define route groups
2019-06-24 11:26:24 +08:00
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`
2019-06-24 11:26:24 +08:00
2019-06-24 00:28:29 +08:00
```php
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');
2019-06-24 00:28:29 +08:00
});
2019-05-08 00:05:14 +08:00
```
### Define routing via annotations
`Hyperf` provides a very convenient [annotation](en/annotation.md) routing function. You can directly define a route by defining `#[Controller]` or `#[AutoController]` annotations on any class.
#### AutoController annotation
2019-05-08 00:05:14 +08:00
`#[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.
2019-05-08 00:05:14 +08:00
> When using `#[AutoController]` annotation, `use Hyperf\HttpServer\Annotation\AutoController;` namespace is required.
2019-05-08 00:05:14 +08:00
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:
2019-05-08 00:05:14 +08:00
| Controller | Annotation | Route URI |
|:----------------:|:----------------------------------:|:--------------:|
| MyDataController | #[AutoController] | /my_data/index |
| MydataController | #[AutoController] | /mydata/index |
| MyDataController | #[AutoController(prefix: "/data")] | /data/index |
2019-05-08 00:05:14 +08:00
```php
<?php
declare(strict_types=1);
namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
#[AutoController]
2019-05-08 00:05:14 +08:00
class UserController
{
// Hyperf will automatically generate a /user/index route for this method, allowing requests via GET or POST
2019-05-08 00:05:14 +08:00
public function index(RequestInterface $request)
{
// Obtain the id parameter from the request
2019-05-08 00:05:14 +08:00
$id = $request->input('id', 1);
return (string)$id;
}
}
```
#### Controller annotation
2019-05-08 00:05:14 +08:00
`#[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.
2019-05-08 00:05:14 +08:00
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.
2019-05-08 00:05:14 +08:00
```php
<?php
declare(strict_types=1);
namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
#[Controller]
2019-05-08 00:05:14 +08:00
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")]
2019-05-08 00:05:14 +08:00
public function index(RequestInterface $request)
{
// Obtain the id parameter from the request
2019-05-08 00:05:14 +08:00
$id = $request->input('id', 1);
return (string)$id;
}
}
```
#### Annotation parameters
2019-05-08 00:05:14 +08:00
2022-11-15 14:01:54 +08:00
Both `#[Controller]` and `#[AutoController]` provide two parameters, `prefix` and `server`.
2019-05-08 00:05:14 +08:00
`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`.
2022-11-15 14:00:41 +08:00
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.
2019-05-08 00:05:14 +08:00
2022-11-15 14:02:31 +08:00
`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`.
2019-05-08 00:05:14 +08:00
### Route parameters
2019-06-24 11:26:24 +08:00
> Given route parameters must be consistent with the controller parameter key name and type, otherwise the controller cannot accept the relevant parameters
2019-06-24 11:26:24 +08:00
2019-06-24 00:28:29 +08:00
```php
Router::get('/user/{id}', 'App\Controller\UserController::info');
2019-06-24 00:28:29 +08:00
```
Access route parameter via controller method injection.
2019-06-24 00:28:29 +08:00
2019-06-24 11:26:24 +08:00
```php
public function info(int $id)
2019-06-24 11:26:24 +08:00
{
$user = User::find($id);
return $user->toArray();
}
2019-06-24 00:28:29 +08:00
```
2019-05-08 00:05:14 +08:00
Access route parameter via request object.
```php
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
2019-05-08 00:05:14 +08:00
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}]`.
2019-05-08 00:05:14 +08:00
#### Get routing information
2019-05-08 00:05:14 +08:00
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`.
2020-03-05 09:23:53 +08:00
## HTTP exceptions
2020-03-05 09:23:53 +08:00
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.
2022-11-15 14:00:41 +08:00
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](en/exception-handler.md).