我正在用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