指尖上的记忆指尖上的记忆
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub
首页
  • 基础
  • Laravel框架
  • Symfony框架
  • 基础
  • Gin框架
  • 基础
  • Spring框架
  • 命令
  • Nginx
  • Ai
  • Deploy
  • Docker
  • K8s
  • Micro
  • RabbitMQ
  • Mysql
  • PostgreSsql
  • Redis
  • MongoDb
  • Html
  • Js
  • 前端
  • 后端
  • Git
  • 知识扫盲
  • Golang
🌟 gitHub

symfony7.2控制器参数自动reslove的使用:

https://symfony.com/doc/current/controller/value_resolver.html#controller-argument-value-resolver
  
其中有一句描述很重要:
This tag is automatically added to every service implementing ValueResolverInterface, but you can set it yourself to change its priority or name attributes.
                  
To ensure your resolvers are added in the right position you can run the following command to see which argument resolvers are present and in which order they run:
root@ca4989b3147e:/app# php bin/console debug:container debug.argument_resolver.inner --show-arguments
  
Information for Service "debug.argument_resolver.inner"
=======================================================

 Responsible for resolving the arguments passed to an action.

 ---------------- ----------------------------------------------------------------------------------------------------- 
  Option           Value                                                                                                
 ---------------- ----------------------------------------------------------------------------------------------------- 
  Service ID       debug.argument_resolver.inner                                                                        
  Class            Symfony\Component\HttpKernel\Controller\ArgumentResolver                                             
  Tags             -                                                                                                    
  Public           no                                                                                                   
  Synthetic        no                                                                                                   
  Lazy             no                                                                                                   
  Shared           yes                                                                                                  
  Abstract         no                                                                                                   
  Autowired        no                                                                                                   
  Autoconfigured   no                                                                                                   
  Arguments        Service(argument_metadata_factory)                                                                   
                   Iterator (25 element(s))                                                                             
                   - Service(.debug.value_resolver.security.user_value_resolver)                                        
                   - Service(.debug.value_resolver.security.security_token_value_resolver)                              
                   - Service(.debug.value_resolver.doctrine.orm.entity_value_resolver)                                  
                   - Service(.debug.value_resolver.argument_resolver.backed_enum_resolver)                              
                   - Service(.debug.value_resolver.argument_resolver.datetime)                                          
                   - Service(.debug.value_resolver.argument_resolver.request_attribute)                                 
                   - Service(.debug.value_resolver.argument_resolver.request)                                           
                   - Service(.debug.value_resolver.argument_resolver.session)                                           
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver)                 
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\CustomFieldCreateUpdateDtoResolver)           
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\DiscountCreateUpdateDtoResolver)              
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\EventContributionTypeDtoResolver)             
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\EventPublicationOptionDtoResolver)            
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\EventReviewOverallRecommendationDtoResolver)  
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\EventSubmissionMarkingSchemeDtoResolver)      
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\ProcessPaymentDtoResolver)                    
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\ProposalCreateUpdateDtoResolver)              
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\RegistrationInformationDtoResolver)           
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\SectionCreateUpdateDtoResolver)               
                   - Service(.debug.value_resolver.App\Model\Dto\Resolver\TicketCreateUpdateDtoResolver)                
                   - Service(.debug.value_resolver.App\ValueResolver\FileUploadResolver)                                
                   - Service(.debug.value_resolver.argument_resolver.service)                                           
                   - Service(.debug.value_resolver.argument_resolver.default)                                           
                   - Service(.debug.value_resolver.argument_resolver.variadic)                                          
                   - Service(.debug.value_resolver.argument_resolver.not_tagged_controller)                             
                   Service(.service_locator.ubj5Sie)                                                                    
  Usages           debug.argument_resolver                                                                              
 ---------------- ----------------------------------------------------------------------------------------------------- 


 ! [NOTE] The "debug.argument_resolver.inner" service or alias has been removed or inlined when the container was       
 !        compiled.                                       



  
原来使用的是:
#[MapRequestPayload] 来实现参数自动映射功能, 
和
#[MapEntity(id: 'eventId')] 实现Entity映射功能
  
上面这两个都extends ValueResolver
  
不同的是,现在使用的是ValueResolverInterface, 这个是 use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
  
Symfony的Resolver注入原理主要基于依赖注入和参数解析机制:
  
类型自动识别:
根据控制器方法的参数类型
自动匹配对应的ValueResolver
通过类型注入和推断实现参数解析
  
我自己测试发现,只要这样定义
class EventSessionCreateEditDtoResolver extends AbstractRequestDtoResolver // 最终implemanets ValueResolverInterface
那么 EventSessionCreateEditDto 都可以被自动注入
  
//查看指定resolver的注入情况:
root@ca4989b3147e:/app# php bin/console debug:container App\Model\Dto\Resolver\EventSessionCreateEditDtoResolver
  
Information for Service "App\Model\Dto\Resolver\EventSessionCreateEditDtoResolver"
==================================================================================

 ---------------- -------------------------------------------------------------------------------- 
  Option           Value                                                                           
 ---------------- -------------------------------------------------------------------------------- 
  Service ID       App\Model\Dto\Resolver\EventSessionCreateEditDtoResolver                        
  Class            App\Model\Dto\Resolver\EventSessionCreateEditDtoResolver                        
  Tags             controller.argument_value_resolver                                              
  Public           no                                                                              
  Synthetic        no                                                                              
  Lazy             no                                                                              
  Shared           yes                                                                             
  Abstract         no                                                                              
  Autowired        yes                                                                             
  Autoconfigured   yes                                                                             
  Usages           .debug.value_resolver.App\Model\Dto\Resolver\EventSessionCreateEditDtoResolver  
 ---------------- -------------------------------------------------------------------------------- 


 ! [NOTE] The "App\Model\Dto\Resolver\EventSessionCreateEditDtoResolver" service or alias has been removed or inlined   
 !        when the container was compiled.                                                                     

  
Symfony会自动注入。核心机制是:
  
通过EventSessionCreateEditDtoResolver专门处理EventSessionCreateEditDto类型
控制器方法参数声明了Dto\Input\EventSessionCreateEditDto类型
ArgumentResolver会调用匹配的Resolver
Resolver负责创建或解析该对象实例
  
解析流程:
  
匹配参数类型
调用对应Resolver
创建EventSessionCreateEditDto实例
注入到控制器方法
  
  
  
其实最主要的一个方法是:
public function resolve(Request $request, ArgumentMetadata $argument): iterable
    {
        if ($argument->getType() !== $this->getSupportedType()) {
            return [];
        }

        $deserializedDto = $this->serializer->deserialize($request->getContent(), $this->getSupportedType(), 'json');
        $dtoObject = $this->postResolve($deserializedDto);

        $violations = $this->validator->validate($dtoObject);
        if (\count($violations)) {
            throw new HttpException(Response::HTTP_UNPROCESSABLE_ENTITY, implode("\n", array_map(static fn ($e) => $e->getMessage(), iterator_to_array($violations))), new ValidationFailedException($request->getPayload(), $violations));
        }

        return [$dtoObject];
  }
  
  
其中:
if ($argument->getType() !== $this->getSupportedType()) {
            return [];
        } 
  
这个$this->getSupportedType() 决定了,当前这个resolver会对哪个控制器的参数生效,如果没有这个判断,就会对所有的参数生效,这也是symfony的一个特色。和 EventSessionCreateEditDtoResolver 这个类名没关系,可以任意命名,最后都可以被请求到。我一直是根据这个类命名来决定处理哪个Dto的,其实不是的,就是根据上面的判断来决定对哪个类型($argument->getType())生效。
  
再来看文档中的这句:
This tag is automatically added to every service implementing ValueResolverInterface. 说明只要定义了resolver, 实现了ValueResolverInterface,都会被注入,最后对哪个Dto生效,取决于前面的if 类型判断。
  
有人出现郭这个问题:
https://stackoverflow.com/questions/79060922/symfony-7-x-custom-resolver-always-called
  
  
  
同时还可以在service.yaml文件下配置(而不影响使用和之前一样的效果):
App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver:
    tags:
        - controller.argument_value_resolver:
              name: addon_dto //取个名字
              priority: 150 //设置优先级
  
  
// 再次查看
root@ca4989b3147e:/app# php bin/console debug:container App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver
  
Information for Service "App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver"
=============================================================================

 ---------------- --------------------------------------------------------------------------- 
  Option           Value                                                                      
 ---------------- --------------------------------------------------------------------------- 
  Service ID       App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver                        
  Class            App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver                        
  Tags             controller.argument_value_resolver (name: addon_dto, priority: 150)        
                   controller.argument_value_resolver                                         
  Public           no                                                                         
  Synthetic        no                                                                         
  Lazy             no                                                                         
  Shared           yes                                                                        
  Abstract         no                                                                         
  Autowired        yes                                                                        
  Autoconfigured   yes                                                                        
  Usages           .debug.value_resolver.App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver  
 ---------------- --------------------------------------------------------------------------- 


 ! [NOTE] The "App\Model\Dto\Resolver\AddonCreateUpdateDtoResolver" service or alias has been removed or inlined when   
 !        the container was compiled.                                                                   
  
  
证明了文档的这句:
but you can set it yourself to change its priority or name attributes.
  
  
总结:
这个功能和larvel下自定义request验证类似,都可以提前获取参数,以及格式化参数(添加或者删除部分参数).