Zend Framework 2自定义Validator注入EntityManager失败求助
问题排查与修复方案
让我帮你找出几个关键问题,这些问题导致你的依赖注入失败,$objectRepository始终为空:
1. 构造函数的选项键名大小写不匹配
你的工厂类里传递给验证器的是**objectRepository(驼峰命名)**,但验证器的构造函数里却尝试获取$options['object_repository'](下划线命名)——这两个键名完全不一致,所以$this->objectRepository自然会被赋值为空。
2. 验证器的服务配置位置错误
在Zend Framework中,自定义验证器需要注册到**validators配置节点**,而不是主service_manager的factories里。因为验证器是由ValidatorPluginManager这个独立的子服务管理器管理的,全局服务管理器不会自动处理验证器的实例化。
3. isValid方法里的错误写法
你在isValid方法里直接实例化Controller和FactoryInterface,这完全违背了依赖注入的设计原则,而且完全没必要——你已经通过工厂注入了objectRepository,直接用它查询实体即可,不需要重新获取EntityManager。
修正后的验证器代码
namespace Rentals\Validator; use Zend\Validator\AbstractValidator; use Doctrine\Common\Persistence\ObjectRepository; class ExistentialQuantification extends AbstractValidator { const NO_ENTITY_ID = 'noEntityId'; const ENTITY_NOT_FOUND = 'entityNotFound'; const INVALID_ID = 'invalidId'; protected $messageTemplates = [ self::NO_ENTITY_ID => 'The input does not contain an entity id.', self::ENTITY_NOT_FOUND => 'The entity could not be found.', self::INVALID_ID => 'The input does not contain a valid entity id.', ]; protected $objectRepository; public function __construct(array $options) { // 匹配工厂传递的驼峰键名,同时添加类型提示保证类型安全 if (isset($options['objectRepository']) && $options['objectRepository'] instanceof ObjectRepository) { $this->objectRepository = $options['objectRepository']; } parent::__construct($options); } public function isValid($value) { if ($value === null) { return true; } // 增加空值判断,避免无效ID if (!isset($value->id) || empty($value->id)) { $this->error(self::NO_ENTITY_ID); return false; } // 直接使用注入的objectRepository查询 $entity = $this->objectRepository->find($value->id); $entityClass = $this->getOption('entity_class'); if (!$entity instanceof $entityClass) { $this->error(self::ENTITY_NOT_FOUND); return false; } return true; } }
修正后的工厂代码
namespace Rentals\Validator; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\MutableCreationOptionsInterface; use Zend\ServiceManager\ServiceLocatorInterface; use Zend\Stdlib\ArrayUtils; class ExistentialQuantificationFactory implements FactoryInterface, MutableCreationOptionsInterface { protected $options = []; public function setCreationOptions(array $options) { $this->options = $options; } public function createService(ServiceLocatorInterface $serviceLocator) { // 注意:ValidatorPluginManager是子服务管理器,需要获取主服务管理器来获取EntityManager $mainServiceManager = $serviceLocator->getServiceLocator(); // 设置默认的EntityManager服务名 if (!isset($this->options['object_manager'])) { $this->options['object_manager'] = 'doctrine.entitymanager.orm_default'; } $objectManager = $mainServiceManager->get($this->options['object_manager']); $objectRepository = $objectManager->getRepository($this->options['entity_class']); return new ExistentialQuantification(ArrayUtils::merge( $this->options, [ 'objectRepository' => $objectRepository ] )); } }
修正后的模块配置
<?php return [ // 将验证器注册到validators节点下,而不是service_manager 'validators' => [ 'factories' => [ Rentals\Validator\ExistentialQuantification::class => Rentals\Validator\ExistentialQuantificationFactory::class, ], ], ]; ?>
使用示例(表单中调用验证器)
在表单的init方法中配置验证器时,传递实体类等选项:
$this->add([ 'name' => 'related_entity', 'validators' => [ [ 'name' => Rentals\Validator\ExistentialQuantification::class, 'options' => [ 'entity_class' => Your\Namespace\Entity\YourEntity::class, // 可选:如果使用自定义EntityManager,指定服务名 // 'object_manager' => 'doctrine.entitymanager.custom' ], ], ], ]);
内容的提问来源于stack exchange,提问作者user7867306
相关产品推荐
相关产品推荐

