首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用setter注入的Zend ServiceManager

使用setter注入的Zend ServiceManager
EN

Stack Overflow用户
提问于 2018-11-14 11:20:02
回答 2查看 96关注 0票数 0

在symfony中,我可以通过call选项(容器/calls.html)为服务使用setter注入。

symfony文档中的示例:

代码语言:javascript
复制
class MessageGenerator
{
    private $logger;

    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    // ...
}

service.yml

代码语言:javascript
复制
services:
    App\Service\MessageGenerator:
        # ...
        calls:
            - method: setLogger
              arguments:
                  - '@logger'

我的zend项目需要这种行为。我想把一个InputFilter注入我的FormFieldSet

我在zend文档中没有找到关于这个的任何东西。我可以使用这样的东西或者存在一个更好的解决我在zend的问题的方法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-15 08:55:37

基于这个问题和前面关于表单、Fieldset和InputFilters的问题,我认为您希望实现类似于下面的用例。

用例

你有一个

  • 定位实体
  • 地址实体
  • 位置有一个OneToOne到一个地址(必需的,单向的)

要求

要管理位置,您需要:

  • LocationForm (-Factory)
  • LocationFormInputFilter (-Factory)
  • LocationFieldset (-Factory)
  • LocationFieldsetInputFilter (-Factory)
  • AddressFieldset (-Factory)
  • AddressFieldsetInputFilter (-Factory)

配置

要在ZF3中配置这一点,您必须添加以下内容

代码语言:javascript
复制
'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按钮。

代码语言:javascript
复制
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做得更多,我建议您看看这里,例如删除空(子字段集/集合)输入,这样就不会尝试在DB中创建数据)

LocationFieldset中,为位置(如名称)和AddressFieldset提供添加输入

代码语言:javascript
复制
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'),
            ],
        ]);
    }
}

AddressFieldset中,只需为Address实体添加输入。(与上面相同,没有Fieldset类型输入)

InputFilters

要验证表单,您可以保持它非常简单:

代码语言:javascript
复制
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();
    }
}

( AbstractFormInputFilter添加CSRF验证器)

注意,我们只是简单地->add() LocationFieldsetInputFilter,但是我们给它一个名称(第二个参数)。这个名称稍后会在完整的结构中使用,所以保持它的简单和正确是很重要的。最简单的方法是给它一个名字,使其一对一地匹配它应该验证的Fieldset的对象。

接下来,LocationFieldsetInputFilter

代码语言:javascript
复制
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,
                        ],
                    ],
                ],
            ]
        );
    }
}

工厂

现在,你必须把它们结合在一起,这就是你关于Setter注入的问题的来源。这种情况发生在工厂里。

*FormFactory将执行以下操作:

代码语言:javascript
复制
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;
}

*FieldsetFactory将执行以下操作(对Location-和AddressFieldsets也这样做):

代码语言:javascript
复制
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;
}

*FormInputFilterFactory将执行以下操作:

代码语言:javascript
复制
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;
}

*FieldsetInputFilterFactory将执行以下操作:

代码语言:javascript
复制
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
    );
}

Note

  • 将InputFilter设置为(不需要)是我添加的这里
  • 如果您的InputFilter (如AddressFieldsetInputFilter)没有子InputFilter,则可以跳过获取子InputFilter并立即返回新的InputFilter。

我想我把它全报道了一张完整的照片。如果你对此有任何疑问,请评论。

票数 2
EN

Stack Overflow用户

发布于 2018-11-15 12:24:23

您需要的是初始化器、来自Zend服务经理

初始化程序可以是在创建服务时调用的类。在该类中,您需要检查创建的服务类型,以及它是否合适的类型,而不是注入任何您想要的服务。

若要注册一个初始化器,请在service_manager键下添加配置:

代码语言:javascript
复制
'service_manager' => [
    'initializers' => [
       MyInitializer::class
    ],
]

然后创建这个类

代码语言:javascript
复制
class MyInitializer implements InitializerInterface
{
    public function __invoke(ContainerInterface $container, $instance)
    {
        // you need to check should you inject or not
        if ($instance instanceof MessageGenerator) { 
            $instance->setLogger($container->get('logger'));
        }
    }
}

您还需要在中注册MessageGenerator。这样,当您尝试从SM检索MessageGenerator时,在创建MyInitializer之后调用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53299020

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档