我想在我的验证课程中获得ServiceLocator。我尝试从Controller实例获取它,但它返回null。
MyValidation.php
namespace Register\Validator;
use Zend\Validator\AbstractValidator;
use Register\Controller\RegisterController;
class MyValidation extends AbstractValidator {
/*
code...
*/
function isValid($value)
{
$controller = new RegisterController();
$sm = $controller->getServiceLocator();
$tableGateway = $sm->get('Register\Model\RegisterTable');
$tableGateway->myValidationMethod($value);
}
}
Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'Register\Model\RegisterTable' => function($sm) {
$tableGateway = $sm->get('RegisterTableGateway');
$table = new RegisterTable($tableGateway);
return $table;
},
'RegisterTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new RegisterUser());
return new TableGateway('table-name', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
但是我得到致命错误:在非对象上调用成员函数get()
在模型类中获取ServiceLocator的正确方法是什么?
答案 0 :(得分:7)
您应该将验证程序的依赖项注入验证程序。将验证器分配给表单字段时,可以通过options数组执行此操作。 我写了一些示例代码来证明我的意思:
注册\验证\ MyValidation:
<?php
namespace Application\Validator;
use Zend\Validator\AbstractValidator;
class MyValidation extends AbstractValidator
{
protected $tableGateway;
public function __construct($options = null)
{
parent::__constructor($options);
if ($options && is_array($options) && array_key_exists('tableGateway', $options))
{
$this->tableGateway = $options['tableGateway'];
}
}
public function isValid($value)
{
// ...
}
}
对于表单,您可以实现ServiceLocatorAwareInterface,因此它会自动注入服务定位器,或者使用表单的工厂将特定的依赖项注入表单。
以下是使用ServiceLocatorAwareInterface执行此操作的方法:
注册\表格\ MyForm的:
<?php
namespace Register\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
class MyForm extends Form implements InputFilterProviderInterface, ServiceLocatorAwareInterface
{
protected $servicelocator;
public function __construct()
{
$this->add(array(
'name' => 'myfield',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Field 1'
),
)
);
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->servicelocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->servicelocator;
}
public function getInputFilterSpecification()
{
return array(
'myfield' => array(
'required' => true,
'filters' => array(),
'validators' => array(
array(
'name' => 'Application\Validator\MyValidator',
'options' => array(
'tableGateway' => $this->getServiceLocator()->get('Application\Model\RegisterTable'),
),
),
),
),
);
}
}
另外,我不清楚为什么要在验证器类中实例化Controller。你真的不应该这样做。
答案 1 :(得分:2)
我选择了不同的方法。
不是将依赖项从表单传递给验证器,而是将其从表单传递给ValidatorManager,ValidatorManager会自动注入到实现ServiceLocatorAware接口的每个验证器上。
<?php
// Form
public function getInputFilterSpecification(){
$filter = new InputFilter();
$factory = new InputFactory();
// Inject SM into validator manager
$pm = $this->getServiceLocator()->get("ValidatorManager");
$validatorChain = $factory->getDefaultValidatorChain();
$validatorChain->setPluginManager($pm);
// Your validators here..
}
// Validator
class MyValidator extends AbstractValidator implements ServiceLocatorAwareInterface {
/**
* SM
* @var ServiceLocatorInterface
*/
private $serviceLocator;
/**
* Validate
*/
public function isValid($email){
// Get the application config
$config = $this->getServiceLocator()->getServiceLocator()->get("config");
}
/**
* ServiceLocatorAwarr method
* @param ServiceLocatorInterface $serviceLocator
* @return \Application\Module
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator){
$this->serviceLocator = $serviceLocator;
return $this;
}
/**
* ServiceLocatorAwarr method
* @return ServiceLocatorInterface
*/
public function getServiceLocator(){
return $this->serviceLocator;
}
}