mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-11-29 18:27:44 +08:00
Support setting multiple annotations by inheriting AbstractMultipleAnnotation
, such as @Middleware
. (#3791)
Co-authored-by: assert <zhangchengming@kkguan.com> Co-authored-by: 李铭昕 <715557344@qq.com>
This commit is contained in:
parent
aa269a9d72
commit
29fca4319b
@ -65,6 +65,7 @@
|
||||
- [#3743](https://github.com/hyperf/hyperf/pull/3743) Support custom register for service governance.
|
||||
- [#3753](https://github.com/hyperf/hyperf/pull/3753) Support long pulling mode for Apollo Client.
|
||||
- [#3759](https://github.com/hyperf/hyperf/pull/3759) Added `rpc-multiplex` component.
|
||||
- [#3791](https://github.com/hyperf/hyperf/pull/3791) Support setting multiple annotations by inheriting `AbstractMultipleAnnotation`, such as `@Middleware`.
|
||||
|
||||
## Optimized
|
||||
|
||||
|
45
src/di/src/Annotation/AbstractMultipleAnnotation.php
Normal file
45
src/di/src/Annotation/AbstractMultipleAnnotation.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Di\Annotation;
|
||||
|
||||
abstract class AbstractMultipleAnnotation extends AbstractAnnotation
|
||||
{
|
||||
public function collectClass(string $className): void
|
||||
{
|
||||
$annotation = AnnotationCollector::getClassAnnotation($className, static::class);
|
||||
|
||||
AnnotationCollector::collectClass($className, static::class, $this->formatAnnotation($annotation));
|
||||
}
|
||||
|
||||
public function collectMethod(string $className, ?string $target): void
|
||||
{
|
||||
$annotation = AnnotationCollector::getClassMethodAnnotation($className, $target)[static::class] ?? null;
|
||||
|
||||
AnnotationCollector::collectMethod($className, $target, static::class, $this->formatAnnotation($annotation));
|
||||
}
|
||||
|
||||
public function collectProperty(string $className, ?string $target): void
|
||||
{
|
||||
$annotation = AnnotationCollector::getClassPropertyAnnotation($className, $target)[static::class] ?? null;
|
||||
|
||||
AnnotationCollector::collectProperty($className, $target, static::class, $this->formatAnnotation($annotation));
|
||||
}
|
||||
|
||||
protected function formatAnnotation(?MultipleAnnotation $annotation): MultipleAnnotation
|
||||
{
|
||||
if ($annotation instanceof MultipleAnnotation) {
|
||||
return $annotation->insert($this);
|
||||
}
|
||||
|
||||
return new MultipleAnnotation($this);
|
||||
}
|
||||
}
|
77
src/di/src/Annotation/MultipleAnnotation.php
Normal file
77
src/di/src/Annotation/MultipleAnnotation.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Di\Annotation;
|
||||
|
||||
use Hyperf\Di\Exception\AnnotationException;
|
||||
|
||||
class MultipleAnnotation implements MultipleAnnotationInterface
|
||||
{
|
||||
/**
|
||||
* @var AnnotationInterface[]
|
||||
*/
|
||||
protected $annotations = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $className;
|
||||
|
||||
public function __construct(AnnotationInterface $annotation)
|
||||
{
|
||||
$this->annotations = [$annotation];
|
||||
$this->className = get_class($annotation);
|
||||
}
|
||||
|
||||
public function __get(string $name)
|
||||
{
|
||||
if (count($this->annotations) > 1) {
|
||||
throw new AnnotationException('MultipleAnnotation[' . $this->className() . '] has more than one annotations.');
|
||||
}
|
||||
|
||||
return $this->annotations[0]->{$name};
|
||||
}
|
||||
|
||||
public function className(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
public function insert(AnnotationInterface $annotation)
|
||||
{
|
||||
if (! $annotation instanceof $this->className) {
|
||||
throw new AnnotationException(get_class($annotation) . ' must instanceof ' . $this->className);
|
||||
}
|
||||
|
||||
$this->annotations[] = $annotation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toAnnotations(): array
|
||||
{
|
||||
return $this->annotations;
|
||||
}
|
||||
|
||||
public function collectClass(string $className): void
|
||||
{
|
||||
throw new AnnotationException('MultipleAnnotation[' . $this->className() . '] does not support collectClass()');
|
||||
}
|
||||
|
||||
public function collectMethod(string $className, ?string $target): void
|
||||
{
|
||||
throw new AnnotationException('MultipleAnnotation[' . $this->className() . '] does not support collectMethod()');
|
||||
}
|
||||
|
||||
public function collectProperty(string $className, ?string $target): void
|
||||
{
|
||||
throw new AnnotationException('MultipleAnnotation[' . $this->className() . '] does not support collectProperty()');
|
||||
}
|
||||
}
|
29
src/di/src/Annotation/MultipleAnnotationInterface.php
Normal file
29
src/di/src/Annotation/MultipleAnnotationInterface.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Di\Annotation;
|
||||
|
||||
use Hyperf\Di\Exception\AnnotationException;
|
||||
|
||||
interface MultipleAnnotationInterface extends AnnotationInterface
|
||||
{
|
||||
public function className(): string;
|
||||
|
||||
/**
|
||||
* @throws AnnotationException
|
||||
*/
|
||||
public function insert(AnnotationInterface $annotation);
|
||||
|
||||
/**
|
||||
* @return AnnotationInterface[]
|
||||
*/
|
||||
public function toAnnotations(): array;
|
||||
}
|
@ -181,9 +181,9 @@ class ProxyManager
|
||||
$defined = [];
|
||||
$annotations = AnnotationCollector::get($annotationCollectorKey, []);
|
||||
|
||||
foreach ($annotations as $k => $annotation) {
|
||||
foreach ($annotations as $name => $annotation) {
|
||||
if (is_object($annotation)) {
|
||||
$defined[] = $k;
|
||||
$defined[] = $name;
|
||||
} else {
|
||||
$defined = array_merge($defined, array_keys($annotation));
|
||||
}
|
||||
|
@ -12,14 +12,14 @@ declare(strict_types=1);
|
||||
namespace Hyperf\HttpServer\Annotation;
|
||||
|
||||
use Attribute;
|
||||
use Hyperf\Di\Annotation\AbstractAnnotation;
|
||||
use Hyperf\Di\Annotation\AbstractMultipleAnnotation;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"ALL"})
|
||||
*/
|
||||
#[Attribute]
|
||||
class Middleware extends AbstractAnnotation
|
||||
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
|
||||
class Middleware extends AbstractMultipleAnnotation
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
|
@ -22,7 +22,7 @@ use Hyperf\Di\Annotation\AbstractAnnotation;
|
||||
class Middlewares extends AbstractAnnotation
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
* @var Middleware[]
|
||||
*/
|
||||
public $middlewares = [];
|
||||
|
||||
@ -30,10 +30,10 @@ class Middlewares extends AbstractAnnotation
|
||||
{
|
||||
if (is_string($value[0])) {
|
||||
$middlewares = [];
|
||||
foreach ($value as $key => $middlewareName) {
|
||||
$middlewares['value'][] = new Middleware($middlewareName);
|
||||
foreach ($value as $middlewareName) {
|
||||
$middlewares[] = new Middleware($middlewareName);
|
||||
}
|
||||
$value = $middlewares;
|
||||
$value = ['value' => $middlewares];
|
||||
}
|
||||
$this->bindMainProperty('middlewares', $value);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ use FastRoute\Dispatcher;
|
||||
use FastRoute\Dispatcher\GroupCountBased;
|
||||
use FastRoute\RouteParser\Std;
|
||||
use Hyperf\Di\Annotation\AnnotationCollector;
|
||||
use Hyperf\Di\Annotation\MultipleAnnotationInterface;
|
||||
use Hyperf\Di\Exception\ConflictAnnotationException;
|
||||
use Hyperf\Di\ReflectionManager;
|
||||
use Hyperf\HttpServer\Annotation\AutoController;
|
||||
@ -220,27 +221,23 @@ class DispatcherFactory
|
||||
|
||||
protected function handleMiddleware(array $metadata): array
|
||||
{
|
||||
$hasMiddlewares = isset($metadata[Middlewares::class]);
|
||||
$hasMiddleware = isset($metadata[Middleware::class]);
|
||||
if (! $hasMiddlewares && ! $hasMiddleware) {
|
||||
/** @var null|Middlewares $middlewares */
|
||||
$middlewares = $metadata[Middlewares::class] ?? null;
|
||||
/** @var null|MultipleAnnotationInterface $middleware */
|
||||
$middleware = $metadata[Middleware::class] ?? null;
|
||||
if ($middleware instanceof MultipleAnnotationInterface) {
|
||||
$middleware = $middleware->toAnnotations();
|
||||
}
|
||||
|
||||
if (! $middlewares && ! $middleware) {
|
||||
return [];
|
||||
}
|
||||
if ($hasMiddlewares && $hasMiddleware) {
|
||||
if ($middlewares && $middleware) {
|
||||
throw new ConflictAnnotationException('Could not use @Middlewares and @Middleware annotation at the same times at same level.');
|
||||
}
|
||||
if ($hasMiddlewares) {
|
||||
// @Middlewares
|
||||
/** @var Middlewares $middlewares */
|
||||
$middlewares = $metadata[Middlewares::class];
|
||||
$result = [];
|
||||
foreach ($middlewares->middlewares as $middleware) {
|
||||
$result[] = $middleware->middleware;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
// @Middleware
|
||||
/** @var Middleware $middleware */
|
||||
$middleware = $metadata[Middleware::class];
|
||||
return [$middleware->middleware];
|
||||
|
||||
return array_map(function (Middleware $middleware) {
|
||||
return $middleware->middleware;
|
||||
}, $middlewares ? $middlewares->middlewares : $middleware);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace HyperfTest\HttpServer\Router;
|
||||
|
||||
use Hyperf\Di\Annotation\MultipleAnnotation;
|
||||
use Hyperf\HttpServer\Annotation\AutoController;
|
||||
use Hyperf\HttpServer\Annotation\Controller;
|
||||
use Hyperf\HttpServer\Annotation\GetMapping;
|
||||
@ -88,7 +89,7 @@ class DispatcherFactoryTest extends TestCase
|
||||
['index' => [
|
||||
GetMapping::class => new GetMapping(['path' => '/index', 'options' => ['name' => 'index.get', 'id' => 1]]),
|
||||
PostMapping::class => new PostMapping(['path' => '/index', 'options' => ['name' => 'index.post']]),
|
||||
Middleware::class => new Middleware(['middleware' => FooMiddleware::class]),
|
||||
Middleware::class => new MultipleAnnotation(new Middleware(['middleware' => FooMiddleware::class])),
|
||||
]],
|
||||
[SetHeaderMiddleware::class]
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user