我正在用ZF2和Doctrine2构建一个小应用程序。设置它的方式有很多可重用的代码和技术。然而,难以置信的是,我的InputFilter
没有自动注入到它应该关联的Fieldset
中。ZF2注入InputFilter到Fieldset不能自动工作
我已确认使用Fieldset
工作的表单(没有InputFilter
)。在调试期间,InputFilter
也可见。
问题是,我做错了什么,以及如何解决有独立的InputFilter
,加上在ZF2 Fieldset
?
图片的标题说明:
1 - 我知道,通过使用InputFilterInterface
我能有Fieldset
类内的InputFilter
与getInputFilterSpecification()
功能。但是,由于我试图保持干燥和可重用,如果要创建需要使用Entity
和InputFilter
的API,但只能将后者与Fieldset
结合使用,则无需复制它。
2 - 很多抽象类的使用,在那里使用我的片段表明他们有什么与自己相关
3 - 这个问题行是CustomerFieldsetFactory.php
==== ================================================== ===================
实体:3210
/**
* Class Customer
* @package Customer\Entity
*
* @ORM\Entity
* @ORM\Table(name="customers")
*/
class Customer extends AbstractEntity //Contains $id
{
/**
* @var string
* @ORM\Column(name="name", type="string", length=255, nullable=false)
*/
protected $name;
}
形式:CustomerForm.php
class CustomerForm extends AbstractForm
{
public function __construct($name = null, array $options)
{
parent::__construct($name, $options); // Adds CSRF
}
public function init()
{
$this->add([
'name' => 'customer',
'type' => CustomerFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
//Call parent initializer. Check in parent what it does.
parent::init(); //Adds submit button if not in form
}
}
字段集:CustomerFieldset.php
class CustomerFieldset extends AbstractFieldset //Contains EntityManager property and constructor requirement (as we're managing Doctrine Entities here)
{
public function init()
{
$this->add([ //For now id field is here, until InputFilter injection works
'name' => 'id',
'type' => Hidden::class,
'attributes' => [
'id' => 'entityId',
],
]);
$this->add([
'name' => 'name',
'type' => Text::class,
'options' => [
'label' => _('Name'),
],
]);
}
}
输入过滤:CustomerInputFilter.php
class CustomerInputFilter extends AbstractInputFilter
{
public function init()
{
parent::init();
$this->add([
'name' => 'name',
'required' => true,
'filters' => [
['name' => StringTrim::class],
['name' => StripTags::class],
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'min' => 3,
'max' => 255,
],
],
],
]);
}
}
类以上。下面的工厂
FormFactory:CustomerFormFactory.php
class CustomerFormFactory implements FactoryInterface, MutableCreationOptionsInterface
{
/**
* @var array
*/
protected $options;
/**
* @param array $options
*/
public function setCreationOptions(array $options)
{
//Arguments checking removed
$this->options = $options;
}
/**
* @param ServiceLocatorInterface|ControllerManager $serviceLocator
* @return CustomerForm
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
$form = new CustomerForm($this->options['name'], $this->options['options']);
$form->setTranslator($serviceManager->get('translator'));
return $form;
}
}
FieldsetFactory:CustomerFieldsetFactory.php
class CustomerFieldsetFactory implements FactoryInterface, MutableCreationOptionsInterface
{
/**
* @var string
*/
protected $name;
public function setCreationOptions(array $options)
{
//Argument checking removed
$this->name = $options['name'];
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator();
$fieldset = new CustomerFieldset($serviceManager->get('Doctrine\ORM\EntityManager'), $this->name);
$fieldset->setHydrator(new DoctrineObject($serviceManager->get('doctrine.entitymanager.orm_default'), false));
$fieldset->setObject(new Customer());
$fieldset->setInputFilter($serviceManager->get('InputFilterManager')->get(CustomerInputFilter::class));
//RIGHT HERE! THE LINE ABOVE IS THE ONE THAT DOES NOT WORK!!!
return $fieldset;
}
}
InputFilterFactory:CustomerInputFilterFactory.php
class CustomerInputFilterFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$repository = $serviceLocator->getServiceLocator()
->get('Doctrine\ORM\EntityManager')
->getRepository(Customer::class);
return new CustomerInputFilter($repository);
}
}
配置:module.config.php
'controllers' => [
'factories' => [
CustomerController::class => CustomerControllerFactory::class,
],
],
'form_elements' => [
'factories' => [
CustomerForm::class => CustomerFormFactory::class,
CustomerFieldset::class => CustomerFieldsetFactory::class,
],
],
'input_filters' => [
'factories' => [
CustomerInputFilter::class => CustomerInputFilterFactory::class,
],
],
'service_manager' => [
'invokables' => [
CustomerControllerService::class => CustomerControllerService::class,
],
],
我希望你可以帮我在这里。
编辑:与实际的错误
在CustomerFieldset.php
(上面)下面的行更新触发错误。
$fieldset->setInputFilter($serviceManager->get('InputFilterManager')->get(CustomerInputFilter::class));
错误:
Fatal error: Call to undefined method Customer\Fieldset\CustomerFieldset::setInputFilter() in D:\htdocs\server-manager\module\Customer\src\Customer\Factory\CustomerFieldsetFactory.php on line 57
如在上面的片段可见,输入过滤(和它的工厂)是已知的的InputFilterManager
。
错误表明它不知道Fieldset上的getInputFilter()
函数。这是正确的方式,它不存在。接下来的问题是,如何让函数存在以便注入InputFilter将工作,或者如何将此InputFilter绑定到Fieldset?
编辑2:更新基于张伯伦的回答 新增use InputFilterAwareTrait
到抽象类AbstractInputFilter
创建以下(从答案):
use Zend\InputFilter\InputFilterAwareTrait;
abstract class AbstractFieldset extends Fieldset
{
use InputFilterAwareTrait;
// ... Other code
}
证明,我有另外一个错误的(原)代码也是如此: 在文件module.config.php
input_filters
应该是input_filter_specs
。这是(使用特质后)Invalid Factory registered
错误(标题为ServiceNotCreatedException
)。
下可能是使用的人,工厂创建具有保湿,对象一个字段,并输入过滤器具有以下功能createService()
:
public function createService(ServiceLocatorInterface $serviceLocator)
{
/** @var ServiceLocator $serviceManager */
$serviceManager = $serviceLocator->getServiceLocator();
/** @var CustomerRepository $customerRepository */
$customerRepository = $serviceManager->get('Doctrine\ORM\EntityManager')->getRepository(Customer::class);
$fieldset = new CustomerFieldset($serviceManager->get('Doctrine\ORM\EntityManager'), $this->name);
$fieldset->setHydrator(new DoctrineObject($serviceManager->get('doctrine.entitymanager.orm_default'), false));
$fieldset->setObject(new Customer());
$fieldset->setInputFilter($serviceManager->get('InputFilterManager')->get(CustomerInputFilter::class, $customerRepository));
return $fieldset;
}
您是否得到了这个工作? –
您提供了大量的信息,但并未真正解释实际的*错误*。输入过滤器管理器是否找到'CustomerInputFilter'?你是否在'CustomerInputFilterFactory'中执行任何代码? – AlexP
@PurpleHexagon还没有。当前使用fieldset上的'InputFilterProviderInterface'解决这个问题,并且在'getInputFilterSpecification'函数中定义规范。 – Nukeface