基于这个问题和您之前关于表单、字段集和输入过滤器的问题,我认为您希望实现类似于以下用例的功能。
用例
你有一个
-
位置实体
-
-
位置有一个到一个地址的one(必需的,单向的)
要管理位置,您需要:
-
位置形式(-工厂)
-
-
LocationFieldset(-Factory)
-
LocationFieldsetInputFilter(-Factory)
-
-
AddressFieldsetInputFilter(-Factory)
要在ZF3中配置它,您必须添加以下内容
'form_elements' => [
'factories' => [
AddressFieldset::class => AddressFieldsetFactory::class,
LocationForm::class => LocationFormFactory::class,
LocationFieldset::class => LocationFieldsetFactory::class,
],
],
'input_filters' => [
'factories' => [
AddressFieldsetInputFilter::class => AddressFieldsetInputFilterFactory::class,
LocationFormInputFilter::class => LocationFormInputFilterFactory::class,
LocationFieldsetInputFilter::class => LocationFieldsetInputFilterFactory::class,
],
],
表格和;字段集
在
LocationForm
,添加您的
LocationFieldset
以及表单还需要什么,例如CSRF和submit按钮。
class LocationForm extends AbstractForm
{
public function init()
{
$this->add([
'name' => 'location',
'type' => LocationFieldset::class,
'options' => [
'use_as_base_fieldset' => true,
],
]);
//Call parent initializer. Adds CSRF & submit button
parent::init();
}
}
AbstractForm
多做一点,我建议你看看
here
,例如删除空(子字段集/集合)输入,以便不尝试在数据库中创建数据)
在
,为位置提供add输入,例如名称和
AddressFieldset
:
class LocationFieldset extends AbstractFieldset
{
public function init()
{
parent::init();
$this->add([
'name' => 'name',
'required' => true,
'type' => Text::class,
'options' => [
'label' => _('Name'),
],
]);
$this->add([
'type' => AddressFieldset::class,
'name' => 'address',
'required' => true,
'options' => [
'use_as_base_fieldset' => false,
'label' => _('Address'),
],
]);
}
}
在
地址字段集
只需为地址实体添加输入(同上,无字段集类型输入)
输入过滤器
class LocationFormInputFilter extends AbstractFormInputFilter
{
/** @var LocationFieldsetInputFilter */
protected $locationFieldsetInputFilter;
public function __construct(LocationFieldsetInputFilter $filter)
{
$this->locationFieldsetInputFilter = $filter;
parent::__construct();
}
public function init()
{
$this->add($this->locationFieldsetInputFilter, 'location');
parent::init();
}
}
(The)
AbstractFormInputFilter
添加CSRF验证程序)
->add()
接下来是
LocationFieldsetInputFilter
:
class LocationFieldsetInputFilter extends AbstractFieldsetInputFilter
{
/**
* @var AddressFieldsetInputFilter
*/
protected $addressFieldsetInputFilter;
public function __construct(AddressFieldsetInputFilter $addressFieldsetInputFilter)
{
$this->addressFieldsetInputFilter = $addressFieldsetInputFilter;
parent::__construct();
}
public function init()
{
parent::init();
$this->add($this->addressFieldsetInputFilter, 'address'); // Again, name is important
$this->add(
[
'name' => 'name',
'required' => true,
'filters' => [
['name' => StringTrim::class],
['name' => StripTags::class],
[
'name' => ToNull::class,
'options' => [
'type' => ToNull::TYPE_STRING,
],
],
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'min' => 3,
'max' => 255,
],
],
],
]
);
}
}
工厂
现在,你必须把它们绑在一起,我想这就是你关于塞特注射的问题。这是在工厂里发生的。
A.
*FormFactory
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$inputFilterPluginManager = $container->get('InputFilterManager');
$inputFilter = $inputFilterPluginManager->get(LocationFormInputFilter::class);
/** @var LocationForm $form */
$form = new LocationForm();
$form->setInputFilter($inputFilter); // The setter injection you're after
return $form;
}
A.
*FieldsetFactory
将执行以下操作(对Location和addressfieldset执行相同的操作):
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var LocationFieldset $fieldset */
// name matters! Match the object to keep it simple. Name is used from Form to match the InputFilter (with same name!)
$fieldset = new LocationFieldset('location');
// Zend Reflection Hydrator, could easily be something else, such as DoctrineObject hydrator.
$fieldset->setHydrator(new Reflection());
$fieldset->setObject(new Location());
return $fieldset;
}
A.
*FormInputFilterFactory
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$inputFilterPluginManager = $container->get('InputFilterManager');
/** @var LocationFieldsetInputFilter $locationFieldsetInputFilter */
$locationFieldsetInputFilter = $inputFilterPluginManager->get(LocationFieldsetInputFilter::class);
// Create Form InputFilter
$locationFormInputFilter = new LocationFormInputFilter(
$locationFieldsetInputFilter
);
return $locationFormInputFilter;
}
A.
*FieldsetInputFilterFactory
将执行以下操作:
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var AddressFieldsetInputFilter $addressFieldsetInputFilter */
$addressFieldsetInputFilter = $this->getInputFilterManager()->get(AddressFieldsetInputFilter::class);
$addressFieldsetInputFilter->setRequired(true);
return new LocationFieldsetInputFilter(
$addressFieldsetInputFilter
);
}
:
-
将InputFilter设置为(非)必需的是我添加的内容
here
-
我想我把这一切都说了一遍,以得到一个完整的画面。如果您对此有任何疑问,请发表评论。