Update English document about Annotation.

- Added demo for query builder.
- Added meilisearch client into awesome components.

Co-authored-by: codelin <494020937@qq.com>
Co-authored-by: Alone88 <im@alone88.cn>
Co-authored-by: 李铭昕 <715557344@qq.com>
This commit is contained in:
Tall 2022-01-13 12:09:04 +08:00 committed by GitHub
parent 3e44fd5d2a
commit 52094d0fad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 308 additions and 291 deletions

View File

@ -56,10 +56,7 @@ use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use App\Models\User;
/**
* DemoProducer
* @Producer(exchange="hyperf", routingKey="hyperf")
*/
#[Producer(exchange: 'hyperf', routingKey: 'hyperf')]
class DemoProducer extends ProducerMessage
{
public function __construct($id)
@ -109,9 +106,7 @@ use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\Amqp\Result;
/**
* @Consumer(exchange="hyperf", routingKey="hyperf", queue="hyperf", nums=1)
*/
#[Consumer(exchange: 'hyperf', routingKey: 'hyperf', queue: 'hyperf', nums: 1)]
class DemoConsumer extends ConsumerMessage
{
public function consume($data): string

View File

@ -47,19 +47,33 @@ There are three apply types of annotation, `class`, `method of class` and `prope
### Use class level annotation
Class level annotation definitions are in the comment block above the `class` keyword. For example, the commonly used `@Controller` and `@AutoController` are examples of the use of class level annotation. The following code example is an example of correctly using class level annotation, indicating The `@ClassAnnotation` annotation is applied to the `Foo` class.
- PHP < 8.0
```php
<?php
/**
* @ClassAnnotation()
* @ClassAnnotation
*/
class Foo {}
```
- PHP >= 8.0
```php
<?php
#[ClassAnnotation]
class Foo {}
```
### Use method level annotation
Method level annotation definitions are in the comment block above the class method. For example, the commonly used `@RequestMapping` is example of the use of method level annotation. The following code example is an example of correctly using method level annotation, indicating The `@MethodAnnotation` annotation is applied to the `bar` method of `Foo` class.
- PHP < 8.0
```php
<?php
class Foo
{
/**
@ -72,11 +86,28 @@ class Foo
}
```
- PHP >= 8.0
```php
<?php
class Foo
{
#[MethodAnnotation]
public function bar()
{
// some code
}
}
```
### Use property level of annotation
Property level annotation definitions are in the comment block above the property. For example, the commonly used `@Value` and `@Inject` are examples of the use of property level annotation. The following code example is an example of correctly using property level annotation, indicating The `@PropertyAnnotation` annotation is applied to the `$bar` property of `Foo` class.
- PHP < 8.0
```php
<?php
class Foo
{
/**
@ -86,6 +117,17 @@ class Foo
}
```
- PHP >= 8.0
```php
<?php
class Foo
{
#[PropertyAnnotation]
private $bar;
}
```
### The passing of annotation parameter
- Pass the main single parameter `@DemoAnnotation("value")`
@ -98,6 +140,8 @@ class Foo
Create an annotation class into anywhere, as in the following code example:
- PHP < 8.0
```php
namespace App\Annotation;
@ -130,6 +174,27 @@ class Foo extends AbstractAnnotation
- `CLASS` annotation means allows define on class
- `ALL` annotation means allows define in all scopes
- PHP >= 8.0
```php
<?php
namespace App\Annotation;
use Hyperf\Di\Annotation\AbstractAnnotation;
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
class Bar extends AbstractAnnotation
{
// some code
}
#[Attribute(Attribute::TARGET_CLASS)]
class Foo extends AbstractAnnotation
{
// some code
}
```
Let's note that in the example code above, the annotation class inherits the `Hyperf\Di\Annotation\AbstractAnnotation` abstract class. This is not required for annotation classes, but for Hyperf annotation classes, inherit `Hyperf\Di\Annotation\AnnotationInterface` interface is required, so the role of the abstract class here is to provide a minimal definition. The abstract class has been implemented for you to `automatically assign annotation parameters to class properties`, `automatically collects the annotation data to AnnotationCollector`.
### Custom Annotation Collector

View File

@ -29,9 +29,7 @@ use Hyperf\Di\Annotation\Aspect;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
/**
* @Aspect
*/
#[Aspect]
class FooAspect extends AbstractAspect
{
// The class to be cut in can be multiple, or can be identified by `::` to the specific method, or use * for fuzzy matching
@ -58,9 +56,9 @@ class FooAspect extends AbstractAspect
}
```
Each `Aspect` have to define `@Aspect` annotation or configure in `config/autoload/aspects.php` to enable.
Each `Aspect` have to define `#[Aspect]` annotation or configure in `config/autoload/aspects.php` to enable.
> Use `@Aspect` annotatin have to `use Hyperf\Di\Annotation\Aspect;` namespace;
> Use `#[Aspect]` annotatin have to `use Hyperf\Di\Annotation\Aspect;` namespace;
## Cache of Proxy Class

View File

@ -61,9 +61,7 @@ namespace App\Process;
use Hyperf\AsyncQueue\Process\ConsumerProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process(name="async-queue")
*/
#[Process(name: "async-queue")]
class AsyncQueueConsumer extends ConsumerProcess
{
}
@ -151,16 +149,11 @@ use App\Service\QueueService;
use Hyperf\Di\Annotation\Inject;~~~~~~~~
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController
*/
#[AutoController]
class QueueController extends Controller
{
/**
* @Inject
* @var QueueService
*/
protected $service;
#[Inject]
protected QueueService $service;
public function index()
{

View File

@ -30,9 +30,7 @@ use Hyperf\Cache\Annotation\Cacheable;
class UserService
{
/**
* @Cacheable(key="user", ttl=9000, listener="user-update")
*/
#[Cacheable(key: "user", ttl: 9000, listener: "user-update")]
public function user($id)
{
$user = User::query()->where('id',$id)->first();
@ -63,11 +61,8 @@ use Psr\EventDispatcher\EventDispatcherInterface;
class SystemService
{
/**
* @Inject
* @var EventDispatcherInterface
*/
protected $dispatcher;
#[Inject]
protected EventDispatcherInterface $dispatcher;
public function flushCache($userId)
{
@ -76,4 +71,4 @@ class SystemService
return true;
}
}
```
```

View File

@ -33,15 +33,10 @@ use Hyperf\Di\Annotation\Inject;
class UserService
{
/**
* @Inject
* @var UserServiceClient
*/
private $client;
#[Inject]
private UserServiceClient $client;
/**
* @CircuitBreaker(timeout=0.05, failCounter=1, successCounter=1, fallback="App\UserService::searchFallback")
*/
#[CircuitBreaker(timeout: 0.05, failCounter: 1, successCounter: 1, fallback: "App\UserService::searchFallback")]
public function search($offset, $limit)
{
return $this->client->users($offset, $limit);

View File

@ -41,9 +41,7 @@ namespace App\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
/**
* @Command
*/
#[Command]
class FooCommand extends HyperfCommand
{
/**
@ -67,9 +65,7 @@ namespace App\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
/**
* @Command
*/
#[Command]
class FooCommand extends HyperfCommand
{
public function __construct()
@ -93,9 +89,7 @@ namespace App\Command;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
/**
* @Command
*/
#[Command]
class FooCommand extends HyperfCommand
{
/**
@ -132,9 +126,7 @@ use Hyperf\Command\Annotation\Command;
use Hyperf\Command\Command as HyperfCommand;
use Symfony\Component\Console\Input\InputArgument;
/**
* @Command
*/
#[Command]
class FooCommand extends HyperfCommand
{
/**

View File

@ -75,7 +75,7 @@ Configurations in the `config/config.php` and `config/autoload/server.php` and `
### Get configuration value
The Config component provides three ways to get the configuration value, obtained through the `Hyperf\Config\Config` object, obtained via the `@Value` annotation, and obtained via the `config(string $key, $default)` function.
The Config component provides three ways to get the configuration value, obtained through the `Hyperf\Config\Config` object, obtained via the `#[Value]` annotation, and obtained via the `config(string $key, $default)` function.
#### Get configuration value by Config Object
@ -89,18 +89,19 @@ This way requires you already have an instance of the `Config` object. The defau
$config->get($key$default);
```
#### Get Configuration by `@Value` Annotation
#### Get Configuration by `#[Value]` Annotation
This way requires the object must be created by the [hyperf/di](https://github.com/hyperf/di) component. The details of the injection instance can be found in [Dependency Injection](en/di.md) chapter, in the example we assume that `IndexController` is an already defined `Controller` class, and the `Controller` class must be created by the `DI` container;
The string in `@Value()` corresponds to the `$key` parameter in `$config->get($key)`. When the object instance is created, the corresponding configuration is automatically injected into the defined class property.
The string in `#[Value()]` corresponds to the `$key` parameter in `$config->get($key)`. When the object instance is created, the corresponding configuration is automatically injected into the defined class property.
```php
<?php
use Hyperf\Config\Annotation\Value;
class IndexController
{
/**
* @Value("config.key")
*/
#[Value(key: "config.key")]
private $configValue;
public function index()

View File

@ -63,7 +63,7 @@ return [
### Using annotations
The definition of a task can be quickly completed through the `@Crontab` annotation. The following definition examples and the configuration file definition achieve the same purpose. Define a timed task named `Foo` to execute `App\Task\FooTask::execute()` every minute.
The definition of a task can be quickly completed through the `#[Crontab]` annotation. The following definition examples and the configuration file definition achieve the same purpose. Define a timed task named `Foo` to execute `App\Task\FooTask::execute()` every minute.
```php
<?php
@ -73,25 +73,18 @@ use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Crontab\Annotation\Crontab;
use Hyperf\Di\Annotation\Inject;
/**
* @Crontab(name="Foo", rule="* * * * *", callback="execute", memo="This is an example scheduled task")
*/
#[Crontab(name: "Foo", rule: "* * * * *", callback: "execute", memo: "This is an example scheduled task")]
class FooTask
{
/**
* @Inject()
* @var \Hyperf\Contract\StdoutLoggerInterface
*/
private $logger;
#[Inject]
private StdoutLoggerInterface $logger;
public function execute()
{
$this->logger->info(date('Y-m-d H:i:s', time()));
}
/**
* @Crontab(rule="* * * * * *", memo="foo")
*/
#[Crontab(rule: "* * * * * *", memo: "foo")]
public function foo()
{
var_dump('foo');

View File

@ -100,7 +100,7 @@ class IndexController
}
```
#### Inject by `@Inject`
#### Inject by `#[Inject]`
```php
<?php
@ -113,11 +113,11 @@ use Hyperf\HttpServer\Annotation\AutoController;
class IndexController
{
/**
* Use `@Inject` to inject the attribute type object declared by `@var`
* Use `#[Inject]` to inject the attribute type object declared by `@var`
*
* @Inject
* @var UserService
*/
#[Inject]
private $userService;
public function index()
@ -131,11 +131,11 @@ class IndexController
> Note that the caller, that is, the `IndexController` must be an object created by `DI` to perform automatic injection. Controller is created by `DI` by default.
> The namespace `use Hyperf\Di\Annotation\Inject;` should be used when `@Inject` used.
> The namespace `use Hyperf\Di\Annotation\Inject;` should be used when `#[Inject]` used.
##### Required Parameter
The `@Inject` annotation has a `required` parameter, and the default value is `true`. When the parameter is defined as `false`, it indicates that this attribute is an optional dependency. When the object corresponding to `@var` does not exist in DI, a `null` will be injected instead of throwing an exception.
The `#[Inject]` annotation has a `required` parameter, and the default value is `true`. When the parameter is defined as `false`, it indicates that this attribute is an optional dependency. When the object corresponding to `@var` does not exist in DI, a `null` will be injected instead of throwing an exception.
```php
<?php
@ -147,12 +147,12 @@ use Hyperf\Di\Annotation\Inject;
class IndexController
{
/**
* Inject the attribute type object declared by the `@var` annotation through the `@Inject` annotation
* Inject the attribute type object declared by the `@var` annotation through the `#[Inject]` annotation
* Null will be injected when UserService does not exist in the DI container or cannot be created
*
* @Inject(required=false)
* @var UserService
*/
#[Inject(required: false)]
private $userService;
public function index()
@ -220,11 +220,8 @@ use Hyperf\HttpServer\Annotation\AutoController;
class IndexController
{
/**
* @Inject
* @var UserServiceInterface
*/
private $userService;
#[Inject]
private UserServiceInterface $userService;
public function index()
{
@ -300,7 +297,7 @@ return [
In this way, when injecting `UserServiceInterface`, the container will hand over the object's creation to `UserServiceFactory`.
> Of course, in this scenario, you can use the `@Value` annotation to inject configuration more conveniently rather than building a factory class. This example is just for explaining.
> Of course, in this scenario, you can use the `#[Value]` annotation to inject configuration more conveniently rather than building a factory class. This example is just for explaining.
### Lazy Loading
@ -346,7 +343,7 @@ class Foo{
}
````
You can also inject lazy loading proxy through the annotation `@Inject(lazy=true)`. Implementing lazy loading through annotations does not need to create configuration files.
You can also inject lazy loading proxy through the annotation `#[Inject(lazy: true)]`. Implementing lazy loading through annotations does not need to create configuration files.
```php
use Hyperf\Di\Annotation\Inject;
@ -354,9 +351,9 @@ use App\Service\UserServiceInterface;
class Foo{
/**
* @Inject(lazy=true)
* @var UserServiceInterface
*/
#[Inject(lazy: true)]
public $service;
}
````
@ -392,7 +389,7 @@ $userService = make(UserService::class, ['enableCache' => true]);
## Get the Container Object
Sometimes we wish to achieve some more dynamic requirements, we would like to be able to directly obtain the `Container` object. In most cases, the entry classes of the framework, such as command classes, controllers, RPC service providers, etc., are created and maintained by `Container`, which means that most of your business codes are all under the management of `Container`. This also means that in most cases you can get the `Hyperf\Di\Container` object by declaring in the `Constructor` or by injecting the `Psr\Container\ContainerInterface` interface class through the `@Inject` annotation. Here is an example:
Sometimes we wish to achieve some more dynamic requirements, we would like to be able to directly obtain the `Container` object. In most cases, the entry classes of the framework, such as command classes, controllers, RPC service providers, etc., are created and maintained by `Container`, which means that most of your business codes are all under the management of `Container`. This also means that in most cases you can get the `Hyperf\Di\Container` object by declaring in the `Constructor` or by injecting the `Psr\Container\ContainerInterface` interface class through the `#[Inject]` annotation. Here is an example:
```php
<?php
@ -426,4 +423,4 @@ $container = \Hyperf\Utils\ApplicationContext::getContainer();
### The container only manages long-lived objects
In other words, the objects managed by container are **all singletons**. This design is more efficient for long-life applications, reducing the meaningless creation and destruction of objects. This also means that all objects that need to be managed by the DI container **can not** contain the `state` value. Which `state` represents some values that will change with the request. In fact, in [coroutine](en/coroutine.md) programming, these state values should also be stored in the `coroutine context`, that is, ` Hyperf\Utils\Context`.
In other words, the objects managed by container are **all singletons**. This design is more efficient for long-life applications, reducing the meaningless creation and destruction of objects. This also means that all objects that need to be managed by the DI container **can not** contain the `state` value. Which `state` represents some values that will change with the request. In fact, in [coroutine](en/coroutine.md) programming, these state values should also be stored in the `coroutine context`, that is, ` Hyperf\Utils\Context`.

View File

@ -87,7 +87,7 @@ return [
### Registering listeners with annotation
Hyperf also provides an easier way to register listeners by registering with the `@Listener` annotation, as long as the annotation is defined on the listener class and the listener class is automatically completed in the `Hyperf annotation scan domain` Registration, code examples are as follows:
Hyperf also provides an easier way to register listeners by registering with the `#[Listener]` annotation, as long as the annotation is defined on the listener class and the listener class is automatically completed in the `Hyperf annotation scan domain` Registration, code examples are as follows:
```php
<?php
@ -97,9 +97,7 @@ use App\Event\UserRegistered;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
/**
* @Listener
*/
#[Listener]
class UserRegisteredListener implements ListenerInterface
{
public function listen(): array
@ -122,9 +120,9 @@ class UserRegisteredListener implements ListenerInterface
}
```
When registering the listener via annotations, we can define the order of the current listener by setting the `priority` attribute, such as `@Listener(priority=1)`, the underlying uses the `SplPriorityQueue` structure to store, the `priority` number is the greater, the priority the higher.
When registering the listener via annotations, we can define the order of the current listener by setting the `priority` attribute, such as `#[Listener(priority: 1)]`, the underlying uses the `SplPriorityQueue` structure to store, the `priority` number is the greater, the priority the higher.
> Use `@Listener` annotation need to `use Hyperf\Event\Annotation\Listener;` namespace
> Use `#[Listener]` annotation need to `use Hyperf\Event\Annotation\Listener;` namespace
### Trigger Event
@ -140,11 +138,8 @@ use App\Event\UserRegistered;
class UserService
{
/**
* @Inject
* @var EventDispatcherInterface
*/
private $eventDispatcher;
#[Inject]
private EventDispatcherInterface $eventDispatcher;
public function register()
{

View File

@ -29,7 +29,7 @@ Services have two roles, one is `ServiceProvider`, which is a service that provi
### Define service provider
So far, only the form of annotations is supported to define `ServiceProvider`, and subsequent editions will add more form of configuration.
We can directly define a class through the `@RpcService` annotation and publish this service:
We can directly define a class through the `#[RpcService]` annotation and publish this service:
```php
<?php
@ -40,8 +40,8 @@ use Hyperf\RpcServer\Annotation\RpcService;
/**
* Note that if you want to manage the service through the service center, you need to add the publishTo attribute in the annotation
* @RpcService(name="CalculatorService", protocol="jsonrpc-http", server="jsonrpc-http")
*/
#[RpcService(name: "CalculatorService", protocol: "jsonrpc-http", server: "jsonrpc-http")]
class CalculatorService implements CalculatorServiceInterface
{
// Implement an addition method, simply consider that the parameters are int type
@ -53,13 +53,13 @@ class CalculatorService implements CalculatorServiceInterface
}
```
`@RpcService` has `4` parameters:
`#[RpcService]` has `4` parameters:
The `name` attribute is the name that defines the service. Just define a globally unique name here. Hyperf will generate a corresponding ID based on this attribute and register it to the service center;
The `protocol` attribute defines the protocol exposed by the service. Currently, only `jsonrpc-http`, `jsonrpc`, and `jsonrpc-tcp-length-check` are supported, which correspond to the HTTP protocol and two protocols under the TCP protocol respectively. The default value is `jsonrpc-http`, the value here corresponds to the `key` of the protocol registered in `Hyperf\Rpc\ProtocolManager`. They are essentially JSON RPC protocol, the difference lies in data formatting, data packaging, data transmitter.
The `server` attribute is the `Server` carried by the binded publishing service class, the default value is `jsonrpc-http`. This attribute corresponds to the `name` under `servers` in the `config/autoload/server.php` file, which also means that we need to define a corresponding `Server`, we will elaborate on how to deal with this in the next chapter;
The `publishTo` attribute defines the service center to be published. Currently only supports `consul` or null. When it is null, it means that the service will not be published to the service center, which also means that you need to manually deal with the service discovery. When the value is `consul`, you need to configure the relevant configuration of the [hyperf/consul](zh-cn/consul.md) component. To use this function, you need to install [hyperf/service-governance](https://github. com/hyperf/service-governance) component, please refer to [Service Registration](zh-cn/service-register.md) section for details.
> To use the `@RpcService` annotation, the `use Hyperf\RpcServer\Annotation\RpcService;` namespace is required.
> To use the `#[RpcService]` annotation, the `use Hyperf\RpcServer\Annotation\RpcService;` namespace is required.
#### Define JSON RPC Server
@ -165,7 +165,7 @@ return [
];
```
After the configuration is completed, when the service is started, Hyperf will automatically register the service, which defined with `publishTo` attribute as `consul` by the `@RpcService`, to the service center.
After the configuration is completed, when the service is started, Hyperf will automatically register the service, which defined with `publishTo` attribute as `consul` by the `#[RpcService]`, to the service center.
> Currently, only the `jsonrpc` and `jsonrpc-http` protocols are supported to publish to the service center, other protocols have not yet implemented service registration

View File

@ -131,9 +131,7 @@ use Hyperf\Kafka\AbstractConsumer;
use Hyperf\Kafka\Annotation\Consumer;
use longlang\phpkafka\Consumer\ConsumeMessage;
/**
* @Consumer(topic="hyperf", nums=5, groupId="hyperf", autoCommit=true)
*/
#[Consumer(topic: "hyperf", nums: 5, groupId: "hyperf", autoCommit: true)]
class KafkaConsumer extends AbstractConsumer
{
public function consume(ConsumeMessage $message): string
@ -157,9 +155,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\Kafka\Producer;
/**
* @AutoController()
*/
#[AutoController]
class IndexController extends AbstractController
{
public function index(Producer $producer)
@ -185,9 +181,7 @@ use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\Kafka\Producer;
use longlang\phpkafka\Producer\ProduceMessage;
/**
* @AutoController()
*/
#[AutoController]
class IndexController extends AbstractController
{
public function index(Producer $producer)

View File

@ -66,14 +66,12 @@ use Hyperf\Nsq\Annotation\Consumer;
use Hyperf\Nsq\Message;
use Hyperf\Nsq\Result;
/**
* @Consumer(
* topic="hyperf",
* channel="hyperf",
* name ="DemoNsqConsumer",
* nums=1
* )
*/
#[Consumer(
topic: "hyperf",
channel: "hyperf",
name: "DemoNsqConsumer",
nums: 1
)]
class DemoNsqConsumer extends AbstractConsumer
{
public function consume(Message $payload): string
@ -87,7 +85,7 @@ class DemoNsqConsumer extends AbstractConsumer
### Disable self-starting of the comsumer process
By default, after using the `@Consumer` annotation definition, the framework will automatically create a child process to start the consumer at startup, and will automatically re-pull it after the child process exits abnormally. However, if some debugging work is carried out in the development stage, it may be inconvenient to debug due to the automatic consumption of consumers.
By default, after using the `#[Consumer]` annotation definition, the framework will automatically create a child process to start the consumer at startup, and will automatically re-pull it after the child process exits abnormally. However, if some debugging work is carried out in the development stage, it may be inconvenient to debug due to the automatic consumption of consumers.
In this situation, you could control the self-start of the consumption process through two forms to disable the feature, global shutdown and partial shutdown.
@ -112,14 +110,12 @@ use Hyperf\Nsq\Message;
use Hyperf\Nsq\Result;
use Psr\Container\ContainerInterface;
/**
* @Consumer(
* topic="demo_topic",
* channel="demo_channel",
* name ="DemoConsumer",
* nums=1
* )
*/
#[Consumer(
topic: "demo_topic",
channel: "demo_channel",
name: "DemoConsumer",
nums: 1
)]
class DemoConsumer extends AbstractConsumer
{
public function __construct(ContainerInterface $container)
@ -156,9 +152,7 @@ use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
use Hyperf\Nsq\Nsq;
/**
* @Command
*/
#[Command]
class NsqCommand extends HyperfCommand
{
protected $name = 'nsq:pub';
@ -191,9 +185,7 @@ use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
use Hyperf\Nsq\Nsq;
/**
* @Command
*/
#[Command]
class NsqCommand extends HyperfCommand
{
protected $name = 'nsq:pub';
@ -230,9 +222,7 @@ use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
use Hyperf\Nsq\Nsq;
/**
* @Command
*/
#[Command]
class NsqCommand extends HyperfCommand
{
protected $name = 'nsq:pub';

View File

@ -24,9 +24,7 @@ use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Paginator\Paginator;
use Hyperf\Utils\Collection;
/**
* @AutoController()
*/
#[AutoController]
class UserController
{
public function index(RequestInterface $request)

View File

@ -38,7 +38,7 @@ return [
### Register via annotation
Just define the @Process annotation on the custom process class, and Hyperf will collect and automatically complete the registration work:
Just define the #[Process] annotation on the custom process class, and Hyperf will collect and automatically complete the registration work:
```php
<?php
@ -49,9 +49,7 @@ namespace App\Process;
use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process(name="foo_process")
*/
#[Process(name: "foo_process")]
class FooProcess extends AbstractProcess
{
public function handle(): void
@ -61,7 +59,7 @@ class FooProcess extends AbstractProcess
}
```
> When using `@Process` annotation, `use Hyperf\Process\Annotation\Process;` namespace is required;
> When using `#[Process]` annotation, `use Hyperf\Process\Annotation\Process;` namespace is required;
## Add conditions for process startup
@ -76,9 +74,7 @@ namespace App\Process;
use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process(name="foo_process")
*/
#[Process(name: "foo_process")]
class FooProcess extends AbstractProcess
{
public function handle(): void
@ -96,7 +92,7 @@ class FooProcess extends AbstractProcess
## Configuring a custom process
There are some configurable parameters in the custom process, which can be defined by overriding the attributes corresponding to the parameters on the subclass or defining the corresponding attributes in the `@Process` annotation.
There are some configurable parameters in the custom process, which can be defined by overriding the attributes corresponding to the parameters on the subclass or defining the corresponding attributes in the `#[Process]` annotation.
```php
<?php
@ -107,9 +103,7 @@ namespace App\Process;
use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process(name="foo_process", name="user-process", redirectStdinStdout=false, pipeType=2, enableCoroutine=true)
*/
#[Process(name: "foo_process", name: "user-process", redirectStdinStdout: false, pipeType: 2, enableCoroutine: true)]
class FooProcess extends AbstractProcess
{
/**
@ -158,9 +152,7 @@ use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
use Hyperf\Contract\StdoutLoggerInterface;
/**
* @Process(name="demo_process")
*/
#[Process(name: "demo_process")]
class DemoProcess extends AbstractProcess
{
public function handle(): void

View File

@ -36,24 +36,18 @@ use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\RateLimit\Annotation\RateLimit;
/**
* @Controller(prefix="rate-limit")
*/
#[Controller(prefix: "rate-limit")]
class RateLimitController
{
/**
* @RequestMapping(path="test")
* @RateLimit(create=1, capacity=3)
*/
#[RequestMapping(path: "test")]
#[RateLimit(create: 1, capacity: 3)]
public function test()
{
return ["QPS 1, Peek3"];
}
/**
* @RequestMapping(path="test2")
* @RateLimit(create=2, consume=2, capacity=4)
*/
#[RequestMapping(path: "test2")]
#[RateLimit(create: 2, consume: 2, capacity: 4)]
public function test2()
{
return ["QPS 2, Peek2"];
@ -78,16 +72,12 @@ use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\RateLimit\Annotation\RateLimit;
/**
* @Controller(prefix="rate-limit")
* @RateLimit(limitCallback={RateLimitController::class, "limitCallback"})
*/
#[Controller(prefix: "rate-limit")]
#[RateLimit(limitCallback: {RateLimitController::class, "limitCallback"})]
class RateLimitController
{
/**
* @RequestMapping(path="test")
* @RateLimit(create=1, capacity=3)
*/
#[RequestMapping(path: "test")]
#[RateLimit(create: 1, capacity: 3)]
public function test()
{
return ["QPS 1, Peek3"];

View File

@ -26,9 +26,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
#[AutoController]
class IndexController
{
public function info(RequestInterface $request)
@ -44,9 +42,7 @@ If you want to obtain routing parameters through controller method parameters, y
```php
// Route definition using annotation method
/**
* @GetMapping(path="/user/{id:\d+}")
*/
#[GetMapping(path: "/user/{id:\d+}")]
// Route definition using configuration method
use Hyperf\HttpServer\Router\Router;
@ -64,9 +60,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
#[AutoController]
class IndexController
{
public function info(RequestInterface $request, int $id)
@ -86,9 +80,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
#[AutoController]
class IndexController
{
public function info(RequestInterface $request)

View File

@ -81,21 +81,21 @@ Router::addGroup('/user/', function (){
### 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.
`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
`@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.
`#[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.
> 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 |
| Controller | Annotation | Route URI |
|:----------------:|:----------------------------------:|:--------------:|
| MyDataController | #[AutoController] | /my_data/index |
| MydataController | #[AutoController] | /mydata/index |
| MyDataController | #[AutoController(prefix: "/data")] | /data/index |
```php
<?php
@ -106,9 +106,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
#[AutoController]
class UserController
{
// Hyperf will automatically generate a /user/index route for this method, allowing requests via GET or POST
@ -123,17 +121,17 @@ class UserController
#### 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.
`#[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.
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.
- 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
<?php
@ -145,15 +143,11 @@ use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
/**
* @Controller()
*/
#[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")
*/
#[RequestMapping(path: "index", methods: "get,post")]
public function index(RequestInterface $request)
{
// Obtain the id parameter from the request
@ -165,7 +159,7 @@ class UserController
#### Annotation parameters
Both `@Controller` and `@AutoController` provide two parameters, `prefix` and `server`.
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 .

View File

@ -10,7 +10,7 @@ composer require hyperf/service-governance
# Register Servive
Service registration can be done by defining a class through the `@RpcService` annotation, which can be regarded as service publishing. So far, only the JSON RPC protocol has been adapted. Referring the [JSON RPC Service](en/json-rpc.md) for more details.
Service registration can be done by defining a class through the `#[RpcService]` annotation, which can be regarded as service publishing. So far, only the JSON RPC protocol has been adapted. Referring the [JSON RPC Service](en/json-rpc.md) for more details.
```php
<?php
@ -19,9 +19,7 @@ namespace App\JsonRpc;
use Hyperf\RpcServer\Annotation\RpcService;
/**
* @RpcService(name="CalculatorService", protocol="jsonrpc-http", server="jsonrpc-http")
*/
#[RpcService(name: "CalculatorService", protocol: "jsonrpc-http", server: "jsonrpc-http")]
class CalculatorService implements CalculatorServiceInterface
{
// Implement an add method with only int type in this example.
@ -33,10 +31,10 @@ class CalculatorService implements CalculatorServiceInterface
}
```
There are `4` params of `@RpcService`:
There are `4` params of `#[RpcService]`:
`name` attribute is the name of this service. Just take a globally unique name here, and Hyperf will generate a corresponding ID based on this attribute and register it in the service center;
`protocol` attribute is the protocol the service exposed out. So far, only `jsonrpc` and `jsonrpc-http` are supported corresponding to the two protocols under the TCP and HTTP respectively. The default value is `jsonrpc-http`. The value here corresponds to the `key` of the protocol registered in `Hyperf\Rpc\ProtocolManager`. Both of these two are essentially JSON RPC protocols. The difference lies in data formatting, data packaging, and data transmitters.
`server` attribute is the `Server` to be carried by the service class which should be published. The default value is `jsonrpc-http`. This attribute corresponds to the `name` under `servers` in the `config/autoload/server.php` file. This also means that we need to define a corresponding `Server`, we will elaborate on how to deal with this in the next chapter;
`publishTo` attribute defines the service center where the service is to be published. Currently, only `consul` is supported, or you can leave it as null. When it is null, it means that the service will not be published to the service center, which means that you need to manually deal with the problem of service discovery. When the value is `consul`, you need to configure the relevant configuration of the [hyperf/consul](en/consul.md) component. To use this function, you need to install [hyperf/service-governance](https://github.com/hyperf/service-governance) component;
> The `use Hyperf\RpcServer\Annotation\RpcService;` is required when the `@RpcService` annotation is used.
> The `use Hyperf\RpcServer\Annotation\RpcService;` is required when the `#[RpcService]` annotation is used.

View File

@ -53,14 +53,12 @@ The session object can be accessed by injecting `Hyperf\Contract\SessionInterfac
namespace App\Controller;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Contract\SessionInterface;
class IndexController
{
/**
* @Inject()
* @var \Hyperf\Contract\SessionInterface
*/
private $session;
#[Inject]
private SessionInterface $session;
public function index()
{

View File

@ -43,15 +43,13 @@ use Hyperf\SocketIOServer\BaseNamespace;
use Hyperf\SocketIOServer\Socket;
use Hyperf\Utils\Codec\Json;
/**
* @SocketIONamespace("/")
*/
#[SocketIONamespace("/")]
class WebSocketController extends BaseNamespace
{
/**
* @Event("event")
* @param string $data
*/
#[Event("event")]
public function onEvent(Socket $socket, $data)
{
// response
@ -59,9 +57,9 @@ class WebSocketController extends BaseNamespace
}
/**
* @Event("join-room")
* @param string $data
*/
#[Event("join-room")]
public function onJoinRoom(Socket $socket, $data)
{
// Add the current user to the room
@ -73,9 +71,9 @@ class WebSocketController extends BaseNamespace
}
/**
* @Event("say")
* @param string $data
*/
#[Event("say")]
public function onSay(Socket $socket, $data)
{
$data = Json::decode($data);
@ -116,9 +114,7 @@ Push the target Socket through SocketAPI, or speak in the room as the target Soc
```php
<?php
/**
* @Event("SomeEvent")
*/
#[Event("SomeEvent")]
function onSomeEvent(\Hyperf\SocketIOServer\Socket $socket){
// sending to the client
@ -193,8 +189,8 @@ $io->of('/foo')->emit();
/**
* Use within the class is also equivalent
* @SocketIONamespace("/foo")
*/
#[SocketIONamespace("/foo")]
class FooNamespace extends BaseNamespace {
public function onEvent(){
$this->emit();
@ -209,7 +205,7 @@ class FooNamespace extends BaseNamespace {
Socket.io implements multiplexing through custom namespaces. (Note: It is not a PHP namespace)
1. The controller can be mapped to the xxx namespace through `@SocketIONamespace("/xxx")`,
1. The controller can be mapped to the xxx namespace through `#[SocketIONamespace("/xxx")]`,
2. Can also be registered through the `SocketIORouter`
@ -311,7 +307,7 @@ class WebSocketController extends BaseNamespace
}
```
2. You can add `@Event()` annotation on the controller, and use the method name as the event name to distribute. At this time, it should be noted that other public methods may conflict with the event name.
2. You can add `#[Event]` annotation on the controller, and use the method name as the event name to distribute. At this time, it should be noted that other public methods may conflict with the event name.
```php
<?php
@ -324,10 +320,8 @@ use Hyperf\SocketIOServer\Annotation\Event;
use Hyperf\SocketIOServer\BaseNamespace;
use Hyperf\SocketIOServer\Socket;
/**
* @SocketIONamespace("/")
* @Event()
*/
#[SocketIONamespace("/")]
#[Event]
class WebSocketController extends BaseNamespace
{
public function echo(Socket $socket, $data)

View File

@ -207,6 +207,7 @@ namespace HyperfTest\Cases;
use HyperfTest\HttpTestCase;
use App\Service\Dao\UserDao;
/**
* @internal
* @coversNothing
@ -238,7 +239,7 @@ Sometimes it is difficult to test the `system under test (SUT)` because it relie
If you cannot use (or choose not to use) the actual dependent component (DOC) when writing a test, you can use a test double instead. The test double does not need to behave in exactly the same way as the real dependent component; it only needs to provide the same API as the real component, so that the system under test will think it is a real component!
The following shows the test doubles of injecting dependencies through the constructor and injecting dependencies through the @Inject annotation.
The following shows the test doubles of injecting dependencies through the constructor and injecting dependencies through the #[Inject] annotation.
### Inject dependency test doubles through constructor
@ -343,11 +344,8 @@ use Hyperf\Di\Annotation\Inject;
class DemoLogic
{
/**
* @var DemoApi $demoApi
* @Inject()
*/
private $demoApi;
#[Inject]
private DemoApi $demoApi;
public function test()
{

View File

@ -170,11 +170,8 @@ use Hyperf\Validation\Contract\ValidatorFactoryInterface;
class IndexController
{
/**
* @Inject()
* @var ValidatorFactoryInterface
*/
protected $validationFactory;
#[Inject]
protected ValidatorFactoryInterface $validationFactory;
public function foo(RequestInterface $request)
{
@ -264,11 +261,8 @@ use Hyperf\Validation\Contract\ValidatorFactoryInterface;
class IndexController
{
/**
* @Inject()
* @var ValidatorFactoryInterface
*/
protected $validationFactory;
#[Inject]
protected ValidatorFactoryInterface $validationFactory;
public function foo(RequestInterface $request)
{
@ -893,9 +887,7 @@ use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Hyperf\Validation\Event\ValidatorFactoryResolved;
/**
* @Listener
*/
#[Listener]
class ValidatorFactoryResolvedListener implements ListenerInterface
{

View File

@ -121,9 +121,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Annotation\AutoController;
use function Hyperf\ViewEngine\view;
/**
* @AutoController(prefix="view")
*/
#[AutoController(prefix: "view")]
class ViewController extends AbstractController
{
public function child()
@ -210,9 +208,7 @@ use Hyperf\Framework\Event\BootApplication;
use Hyperf\ViewEngine\Blade;
use Psr\Container\ContainerInterface;
/**
* @Listener
*/
#[Listener]
class BladeWithoutDoubleEncodingListener implements ListenerInterface
{
/**

View File

@ -191,9 +191,7 @@ namespace App\Controller;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\View\RenderInterface;
/**
* @AutoController
*/
#[AutoController]
class ViewController
{
public function index(RenderInterface $render)

View File

@ -24,11 +24,8 @@ use Hyperf\WebSocketClient\Frame;
class IndexController
{
/**
* @Inject
* @var ClientFactory
*/
protected $clientFactory;
#[Inject]
protected ClientFactory $clientFactory;
public function index()
{
@ -55,4 +52,4 @@ By default, the created `Client` object will be closed by `defer`. If it is not
```php
$autoClose = false;
$client = $clientFactory->create($host, $autoClose);
```
```

View File

@ -196,16 +196,11 @@ use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\WebSocketServer\Sender;
/**
* @AutoController
*/
#[AutoController]
class ServerController
{
/**
* @Inject
* @var Sender
*/
protected $sender;
#[Inject]
protected Sender $sender;
public function close(int $fd)
{

View File

@ -10,7 +10,7 @@
- 注释:给程序员看,帮助理解代码,对代码起到解释、说明的作用。
- 注解:给应用程序看,用于元数据的定义,单独使用时没有任何作用,需配合应用程序对其元数据进行利用才有作用。
### 注解解析如何实现?
### 注释型注解解析如何实现?
Hyperf 使用了 [doctrine/annotations](https://github.com/doctrine/annotations) 包来对代码内的注解进行解析,注解必须写在下面示例的标准注释块才能被正确解析,其它格式均不能被正确解析。
注释块示例:
@ -47,17 +47,33 @@ return [
### 使用类注解
类注解定义是在 `class` 关键词上方的注释块内,比如常用的 `@Controller``@AutoController` 就是类注解的使用典范,下面的代码示例则为一个正确使用类注解的示例,表明 `@ClassAnnotation` 注解应用于 `Foo` 类。
- PHP 版本低于 8.0 时
```php
<?php
/**
* @ClassAnnotation()
* @ClassAnnotation
*/
class Foo {}
```
- PHP 版本大于等于 8.0 时
```php
<?php
#[ClassAnnotation]
class Foo {}
```
### 使用类方法注解
类方法注解定义是在方法上方的注释块内,比如常用的 `@RequestMapping` 就是类方法注解的使用典范,下面的代码示例则为一个正确使用类方法注解的示例,表明 `@MethodAnnotation` 注解应用于 `Foo::bar()` 方法。
- PHP 版本低于 8.0 时
```php
<?php
class Foo
{
/**
@ -70,10 +86,28 @@ class Foo
}
```
- PHP 版本大于等于 8.0 时
```php
<?php
class Foo
{
#[MethodAnnotation]
public function bar()
{
// some code
}
}
```
### 使用类属性注解
类属性注解定义是在属性上方的注释块内,比如常用的 `@Value``@Inject` 就是类属性注解的使用典范,下面的代码示例则为一个正确使用类属性注解的示例,表明 `@PropertyAnnotation` 注解应用于 `Foo` 类的 `$bar` 属性。
- PHP 版本低于 8.0 时
```php
<?php
class Foo
{
/**
@ -83,7 +117,18 @@ class Foo
}
```
### 注解参数传递
- PHP 版本大于等于 8.0 时
```php
<?php
class Foo
{
#[PropertyAnnotation]
private $bar;
}
```
### 注释型注解参数传递
- 传递主要的单个参数 `@DemoAnnotation("value")`
- 传递字符串参数 `@DemoAnnotation(key1="value1", key2="value2")`
@ -95,7 +140,10 @@ class Foo
在任意地方创建注解类,如下代码示例:
- PHP 版本低于 8.0 时
```php
<?php
namespace App\Annotation;
use Hyperf\Di\Annotation\AbstractAnnotation;
@ -119,14 +167,35 @@ class Foo extends AbstractAnnotation
}
```
> 注意注解类的 `@Annotation``@Target` 注解为全局注解,无需 `use`
> 注意注解类的 `@Annotation``@Target` 注解为全局注解,无需 `use`
其中 `@Target` 有如下参数:
其中 `@Target` 有如下参数:
- `METHOD` 注解允许定义在类方法上
- `PROPERTY` 注解允许定义在类属性上
- `CLASS` 注解允许定义在类上
- `ALL` 注解允许定义在任何地方
- PHP 版本大于等于 8.0 时
```php
<?php
namespace App\Annotation;
use Hyperf\Di\Annotation\AbstractAnnotation;
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)]
class Bar extends AbstractAnnotation
{
// some code
}
#[Attribute(Attribute::TARGET_CLASS)]
class Foo extends AbstractAnnotation
{
// some code
}
```
我们注意一下在上面的示例代码中,注解类都继承了 `Hyperf\Di\Annotation\AbstractAnnotation` 抽象类,对于注解类来说,这个不是必须的,但对于 Hyperf 的注解类来说,继承 `Hyperf\Di\Annotation\AnnotationInterface` 接口类是必须的,那么抽象类在这里的作用是提供极简的定义方式,该抽象类已经为您实现了`注解参数自动分配到类属性`、`根据注解使用位置自动按照规则收集到 AnnotationCollector` 这样非常便捷的功能。
### 自定义注解收集器

View File

@ -147,3 +147,4 @@
- [overtrue/wechat](zh-cn/sdks/wechat) EasyWeChat一个流行的非官方微信 SDK
- [Yurunsoft/PHPMailer-Swoole](https://github.com/Yurunsoft/PHPMailer-Swoole) Swoole 协程环境下的可用的 PHPMailer
- [yansongda/hyperf-pay](https://github.com/yansongda/hyperf-pay) 支持 `支付宝/微信` 的支付组件,基于 [yansongda/pay](https://github.com/yansongda/pay) 实现,适配于 `Hyperf` 框架。
- [alapi/hyperf-meilisearch](https://github.com/anhao/hyperf-meilisearch/) 为Hyperf Scout 提供的 meilisearch 客户端

View File

@ -387,6 +387,18 @@ $users = Db::table('user')->where([
])->get();
```
你还可以使用闭包的方式创建查询数组
```php
$users = Db::table('user')->where([
['status', '=', '1'],
['gender', '=', '1'],
[function ($query) {
$query->where('type', 3)->orWhere('type', 6);
}]
])->get();
```
### Or 语句
你可以一起链式调用 `where` 约束,也可以在查询中添加 `or` 字句。 `orWhere` 方法和 `where` 方法接收的参数一样: