PHP8发布之后越发爱不释手,尤其Attribute比Annotation强大不少,Attribute可以对单个参数进行控制,这个功能很强大。演示一下控制器中通过Attribute描述字段来获得当前IP,其实一般解析器都是用来denormalize客户端POST过来的参数,但是为了用到Attribute,我用IP来举例。
<?php
namespace App\Resolver;
use Attribute;
#[Attribute(Attribute::TARGET_PARAMETER)]
final class IP
{
}
先设计一个Attribute申明,注意TARGET_PARAMETER标识作用在参数范围。
<?php
namespace App\Resolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
class IPValueResolver implements ValueResolverInterface
{
public function resolve(Request $request, ArgumentMetadata $argument): iterable
{
$argumentType = $argument->getType();
// 检查IP的Attribute
$attributes = $argument->getAttributes(IP::class);
if (count($attributes) == 0 || $argumentType !== 'string') {
return [];
}
yield $request->getClientIp();
}
}
其次,编写一个解析器,注意,Symfony 6.2开始提供ValueResolverInterface,之前版本用ArgumentValueResolverInterface。
public function resolver(#[IP] string $ip): Response
最后,便是在任何控制器的方法中,只要使用了#[IP] string $ip
就能方便的取得IP了。正确使用解析器,可以大大降低控制器中和Request对象耦合的重复代码,将预处理的流程都放在解析中!