ZF2将InputFilter注入Fieldset无法自动工作 [英] ZF2 injecting InputFilter into Fieldset not working automatically

查看:58
本文介绍了ZF2将InputFilter注入Fieldset无法自动工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ZF2和Doctrine2构建一个小型应用程序。以具有大量可重复使用的代码和技术的方式进行设置。但是,被我的 InputFilter 不会自动注入到应该关联的 Fieldset 的事实所困扰。

I'm building a small application with ZF2 and Doctrine2. Setting it up in such a way as to have a lot of reusable code and technique. However, getting stumped by the fact that my InputFilter is not automatically injected into the Fieldset that it should get associated to.

我已经确认使用 Fieldset 的表单可以正常工作(无需 InputFilter )。 InputFilter 在调试过程中也可见。

I've confirmed that the Form that uses the Fieldset works (without the InputFilter). The InputFilter is also visible as present during debugging.

然后的问题是,我在做什么错了,如何解决将单独的 InputFilter 与< ZF2中的code> Fieldset ?

The question then, what am I doing wrong and how to fix having a separate InputFilter, coupled to a Fieldset in ZF2?

边注:

1-我知道使用 InputFilterInterface 可以得到 InputFilter Fieldset 类中,并具有 getInputFilterSpecification()函数。但是,由于我试图使其保持干燥和可重复使用,因此如果我要创建需要使用 Entity 的API,则不必复制它和 InputFilter ,但只能将后者与 Fieldset 结合使用。

1 - I am aware that by using the InputFilterInterface I could have the InputFilter inside of the Fieldset class with the getInputFilterSpecification() function. However, as I'm trying to keep it DRY and reusable, it wouldn't do to have to copy it if I were to create an API that needs to use the Entity and InputFilter, but can only have the latter coupled with a Fieldset.

2-使用了很多Abstract类,在摘要中将使用哪些摘要类来说明它们具有哪些意义

2 - A lot of Abstract classes are used, where used I'll indicate in the snippets what they have that's relevant

3-问题行位于 CustomerFieldsetFactory.php

3 - The problem line is in CustomerFieldsetFactory.php

= ================================================== ======================

=========================================================================

实体: Customer.php

/**
 * 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

Fieldset: 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'),
            ],
        ]);
    }
}

InputFilter: CustomerInputFilter.php

InputFilter: 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

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

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

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);
    }
}

Config: 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,
    ],
],






我希望你们中的一个能在这里帮助我。


I am hoping one of you can help me out here.

编辑:更新时出现实际错误

CustomerFieldset.php 中的以下行(上面)触发错误。

The following line in the CustomerFieldset.php (above) triggers the error.

$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 是InputFilter(及其工厂)。

As seen in the above snippet, the InputFilter (and it's Factory) are known the the InputFilterManager.

该错误表明它不知道Fieldset上的 getInputFilter()函数。在某种程度上是正确的,它不存在。然后的问题是,如何使函数存在以便注入InputFilter起作用,或者如何将此InputFilter绑定到Fieldset?

The error states it does not know the getInputFilter() function on the Fieldset. Which is correct in a way, it doesn't exist. The question then is, how to have the function exist so that injecting the InputFilter will work, or how to bind this InputFilter to the Fieldset?

编辑2:基于Wilt的答案进行更新
添加了使用InputFilterAwareTrait 来抽象类 AbstractInputFilter 创建以下内容(从答案中得出):

EDIT 2: Update based on Wilt's answer Added use InputFilterAwareTrait to Abstract class AbstractInputFilter to create following (from answer):

use Zend\InputFilter\InputFilterAwareTrait;

abstract class AbstractFieldset extends Fieldset
{
    use InputFilterAwareTrait;
    // ... Other code
}

原来,我有上面(原始)代码中的另一个错误:
在文件 module.config.php input_filters 应该是 input_filter_specs 。 (使用Trait之后),这是一个无效工厂注册错误(标题为 ServiceNotCreatedException )。

Turns out that I had another mistake in the (original) code above as well: In file module.config.php the input_filters should've been input_filter_specs. This was (after using the Trait) a Invalid Factory registered error (titled ServiceNotCreatedException).

以下内容可能对某人有用,工厂使用Hydrator,Object和Inputfilter创建字段集具有以下 createService()函数:

The following might be of use to someone, the Factory to create a Fieldset with Hydrator, Object and Inputfilter has the following createService() function:

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;
}


推荐答案

添加了很多信息对你的问题。建议您日后尝试缩小问题范围。在此处阅读有关指导原则的更多信息:如何创建最小,完整和可验证的示例

There is lots of information added to your question. I'd suggest you try to narrow down your question in the future. Read more on the guidelines for a good question here: How to create a Minimal, Complete, and Verifiable example.

Zend框架提供了 InputFilterAwareTrait setInputFilter getInputFilter 方法。您可以在 CustomerFieldset 类中轻松实现/使用此特征:

Zend framework provides a InputFilterAwareTrait with both the setInputFilter and getInputFilter methods. You can easily implement/use this trait inside your CustomerFieldset class:

use Zend\InputFilter\InputFilterAwareTrait;

class CustomerFieldset extends AbstractFieldset
{
    use InputFilterAwareTrait;

    //...remaining code

}

如果您希望所有扩展抽象 AbstractFieldset 类的类中的inputfilter,也可以决定在其中添加特征:

In case you want the inputfilter in all classes that extend your abstract AbstractFieldset class you could also decide to add the trait there:

use Zend\InputFilter\InputFilterAwareTrait;

class AbstractFieldset
{
    use InputFilterAwareTrait;

    //...remaining code

}

这篇关于ZF2将InputFilter注入Fieldset无法自动工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆