Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Zend framework2 如何在Zend Framework 2中为表单字段集使用服务?_Zend Framework2_Zend Form_Service Locator_Zend Framework Mvc_Servicemanager - Fatal编程技术网

Zend framework2 如何在Zend Framework 2中为表单字段集使用服务?

Zend framework2 如何在Zend Framework 2中为表单字段集使用服务?,zend-framework2,zend-form,service-locator,zend-framework-mvc,servicemanager,Zend Framework2,Zend Form,Service Locator,Zend Framework Mvc,Servicemanager,我有一个表单(),其中有一些嵌套的字段集()。其结构与建筑中的结构非常相似 MyForm class MyForm { public function __construct() { ... $this->add( [ 'type' => 'Storage\Form\Fieldset\FooFieldset', 'options' => [

我有一个表单(),其中有一些嵌套的字段集()。其结构与建筑中的结构非常相似

MyForm

class MyForm {
    public function __construct()
    {
        ...
        $this->add(
            [
                'type' => 'Storage\Form\Fieldset\FooFieldset',
                'options' => [
                    'use_as_base_fieldset' => true
                ]
            ]
        );
    }
}
class FooFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('foo');
        $this->setHydrator(new ClassMethodsHydrator())->setObject(new Foo()); // dependencies!
    }
}
return [
    'controllers' => [
        'factories' => [
            'Foo\Controller\My' => 'Foo\Controller\Factory\MyControllerFactory'
        ]
    ],
    'service_manager' => [
        'factories' => [
            'Foo\Form\MyForm' => 'Foo\Form\Factory\MyFormFactory',
        ],
    ],
];
namespace Foo\Form\Factory;

use ...;

class MyFormFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $form = new MyForm();
        $form->setAttribute('method', 'post')
            ->setHydrator(new ClassMethods())
            ->setInputFilter(new InputFilter());
        return $form;
    }
}
namespace Foo\Controller\Factory;

use ...;

class MyControllerFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $fooPrototype = new Foo();
        $realServiceLocator = $serviceLocator->getServiceLocator();
        // $myForm = $realServiceLocator->get('Foo\Form\MyForm'); <-- This doesn't work correctly for this case. The FormElementManager should be used instead.
        $formElementManager = $realServiceLocator->get('FormElementManager');                        
        $myForm = $formElementManager->get('Foo\Form\MyForm');
        return new MyController($myForm, $fooPrototype);
    }
}
FooFieldset

class MyForm {
    public function __construct()
    {
        ...
        $this->add(
            [
                'type' => 'Storage\Form\Fieldset\FooFieldset',
                'options' => [
                    'use_as_base_fieldset' => true
                ]
            ]
        );
    }
}
class FooFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('foo');
        $this->setHydrator(new ClassMethodsHydrator())->setObject(new Foo()); // dependencies!
    }
}
return [
    'controllers' => [
        'factories' => [
            'Foo\Controller\My' => 'Foo\Controller\Factory\MyControllerFactory'
        ]
    ],
    'service_manager' => [
        'factories' => [
            'Foo\Form\MyForm' => 'Foo\Form\Factory\MyFormFactory',
        ],
    ],
];
namespace Foo\Form\Factory;

use ...;

class MyFormFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $form = new MyForm();
        $form->setAttribute('method', 'post')
            ->setHydrator(new ClassMethods())
            ->setInputFilter(new InputFilter());
        return $form;
    }
}
namespace Foo\Controller\Factory;

use ...;

class MyControllerFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $fooPrototype = new Foo();
        $realServiceLocator = $serviceLocator->getServiceLocator();
        // $myForm = $realServiceLocator->get('Foo\Form\MyForm'); <-- This doesn't work correctly for this case. The FormElementManager should be used instead.
        $formElementManager = $realServiceLocator->get('FormElementManager');                        
        $myForm = $formElementManager->get('Foo\Form\MyForm');
        return new MyController($myForm, $fooPrototype);
    }
}
它可以工作,但fieldset类中有两个依赖项。我想给他们注射。为此,我创建了一个
FooFieldsetFactory
,并通过以下方式扩展了
/module/MyModule/config/module.config.php

'service_manager' => [
    'factories' => [
        'Storage\Form\Fieldset\FooFieldset' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory',
    ],
],
这家工厂完全被忽视了。我猜,服务定位器首先尝试按名称空间查找类,只有在没有找到任何内容的情况下,才会查看
invokables
factories
。好啊然后我创建了一个别名:

'service_manager' => [
    'factories' => [
        'Storage\Form\Fieldset\FooFieldset' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory',
    ],
],
'aliases' => [
    'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\FooFieldset',
],
。。。并尝试在我的表单类中使用它而不是
Storage\Form\Fieldset\FooFieldset
。但现在我有一个例外:

Zend\Form\FormElementManager::get无法获取或创建Storage\Form\Fieldset\Foo的实例

我也直接尝试过:

'service_manager' => [
    'factories' => [
        'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory',
    ],
],
没有效果,同样的错误

这也不起作用(同样的错误):

因此,为字段集引用服务似乎不起作用。还是我做错了什么

如何为表单字段集使用服务?


更新

通过一些调试,我发现无法找到我的
Foo
字段集工厂,因为它尚未添加到。这是一个地方:

所以我的配置

'form_elements' => [
    'factories' => [
        'Storage\Form\Fieldset\Foo' => 'Storage\Form\Fieldset\Factory\FooFieldsetFactory',
    ],
],
被忽略了。如何解决这个问题


更新其他信息,我如何创建我的
表单
对象

/module/Foo/config/module.config.php

class MyForm {
    public function __construct()
    {
        ...
        $this->add(
            [
                'type' => 'Storage\Form\Fieldset\FooFieldset',
                'options' => [
                    'use_as_base_fieldset' => true
                ]
            ]
        );
    }
}
class FooFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('foo');
        $this->setHydrator(new ClassMethodsHydrator())->setObject(new Foo()); // dependencies!
    }
}
return [
    'controllers' => [
        'factories' => [
            'Foo\Controller\My' => 'Foo\Controller\Factory\MyControllerFactory'
        ]
    ],
    'service_manager' => [
        'factories' => [
            'Foo\Form\MyForm' => 'Foo\Form\Factory\MyFormFactory',
        ],
    ],
];
namespace Foo\Form\Factory;

use ...;

class MyFormFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $form = new MyForm();
        $form->setAttribute('method', 'post')
            ->setHydrator(new ClassMethods())
            ->setInputFilter(new InputFilter());
        return $form;
    }
}
namespace Foo\Controller\Factory;

use ...;

class MyControllerFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $fooPrototype = new Foo();
        $realServiceLocator = $serviceLocator->getServiceLocator();
        // $myForm = $realServiceLocator->get('Foo\Form\MyForm'); <-- This doesn't work correctly for this case. The FormElementManager should be used instead.
        $formElementManager = $realServiceLocator->get('FormElementManager');                        
        $myForm = $formElementManager->get('Foo\Form\MyForm');
        return new MyController($myForm, $fooPrototype);
    }
}
/module/Foo/src/Foo/Form/Factory/MyFormFactory.php

class MyForm {
    public function __construct()
    {
        ...
        $this->add(
            [
                'type' => 'Storage\Form\Fieldset\FooFieldset',
                'options' => [
                    'use_as_base_fieldset' => true
                ]
            ]
        );
    }
}
class FooFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('foo');
        $this->setHydrator(new ClassMethodsHydrator())->setObject(new Foo()); // dependencies!
    }
}
return [
    'controllers' => [
        'factories' => [
            'Foo\Controller\My' => 'Foo\Controller\Factory\MyControllerFactory'
        ]
    ],
    'service_manager' => [
        'factories' => [
            'Foo\Form\MyForm' => 'Foo\Form\Factory\MyFormFactory',
        ],
    ],
];
namespace Foo\Form\Factory;

use ...;

class MyFormFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $form = new MyForm();
        $form->setAttribute('method', 'post')
            ->setHydrator(new ClassMethods())
            ->setInputFilter(new InputFilter());
        return $form;
    }
}
namespace Foo\Controller\Factory;

use ...;

class MyControllerFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $fooPrototype = new Foo();
        $realServiceLocator = $serviceLocator->getServiceLocator();
        // $myForm = $realServiceLocator->get('Foo\Form\MyForm'); <-- This doesn't work correctly for this case. The FormElementManager should be used instead.
        $formElementManager = $realServiceLocator->get('FormElementManager');                        
        $myForm = $formElementManager->get('Foo\Form\MyForm');
        return new MyController($myForm, $fooPrototype);
    }
}
/module/Foo/src/Foo/Controller/Factory/MyControllerFactory.php

class MyForm {
    public function __construct()
    {
        ...
        $this->add(
            [
                'type' => 'Storage\Form\Fieldset\FooFieldset',
                'options' => [
                    'use_as_base_fieldset' => true
                ]
            ]
        );
    }
}
class FooFieldset extends Fieldset implements InputFilterProviderInterface
{
    public function __construct()
    {
        parent::__construct('foo');
        $this->setHydrator(new ClassMethodsHydrator())->setObject(new Foo()); // dependencies!
    }
}
return [
    'controllers' => [
        'factories' => [
            'Foo\Controller\My' => 'Foo\Controller\Factory\MyControllerFactory'
        ]
    ],
    'service_manager' => [
        'factories' => [
            'Foo\Form\MyForm' => 'Foo\Form\Factory\MyFormFactory',
        ],
    ],
];
namespace Foo\Form\Factory;

use ...;

class MyFormFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $form = new MyForm();
        $form->setAttribute('method', 'post')
            ->setHydrator(new ClassMethods())
            ->setInputFilter(new InputFilter());
        return $form;
    }
}
namespace Foo\Controller\Factory;

use ...;

class MyControllerFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $fooPrototype = new Foo();
        $realServiceLocator = $serviceLocator->getServiceLocator();
        // $myForm = $realServiceLocator->get('Foo\Form\MyForm'); <-- This doesn't work correctly for this case. The FormElementManager should be used instead.
        $formElementManager = $realServiceLocator->get('FormElementManager');                        
        $myForm = $formElementManager->get('Foo\Form\MyForm');
        return new MyController($myForm, $fooPrototype);
    }
}
名称空间Foo\Controller\Factory;
使用。。。;
类MyControllerFactory实现FactoryInterface
{
公共函数createService(serviceLocator接口$serviceLocator)
{
$fooPrototype=newfoo();
$realServiceLocator=$serviceLocator->getServiceLocator();

//$myForm=$realServiceLocator->get('Foo\Form\myForm');此问题是因为您正在表单
\uuu construct()
方法中添加表单元素,而不是
init()

为了处理元素/字段集/表单中的依赖关系,可以使用工厂而不是可调用工厂

现在是第一个陷阱

如果您是通过扩展
Zend\form\form
来创建表单类,则不能在
\uuu构造中添加自定义元素,或者(正如我们在前面的示例中使用自定义元素的FQCN所做的那样),而是在
init()
方法中添加自定义元素:

原因是新表单的工厂(用于使用
add()
)创建新元素)必须具有应用程序的表单元素管理器此表单元素管理器实例包含对在
form\u elements
配置键下注册的自定义表单元素的所有引用


通过在表单
\uu construct
中调用
add()
,它将能够创建所有默认表单元素,但不了解自定义表单元素。

非常感谢您的详细回答!我将初始化逻辑从构造函数移到了
init()中
。但它不起作用。对于
表单
来说,元素就是找不到,例如:
没有名为[foo]的元素在表单
中找到。对于
字段集
s:与以前相同的错误:
Zend\form\FormElementManager::get无法获取或创建Order\form\FieldSet\Foo的实例
。我还分析了
init()
FormElementManager
的状态。因为
init()
是在构造函数之后调用的,我希望在
MyFieldset->factory->formElementManager->factories
中找到我的自定义字段集工厂。但是该属性只包含标准的Zend工厂。@automatix是否使用
$formElementManager->get('Order\form\fieldset\Foo
)创建表单
表单#init()
和我的
FooFieldsetFactory
中的字段终于被检索到了!非常感谢您的帮助!@automatix您是如何解决“没有元素的名称…”的问题的?我是
$Form->get('employee')
这给了我一个例外。我的EmployeeFieldSet在构造函数中执行:
父::_构造('employee');
在init函数中,我执行所有这些
添加
调用。在我表单的构造函数中,我执行以下操作:
父::_构造('create_employee');
和在init()中方法我添加
EmployeeFieldSet
。在config.module.php中,我有
form\u元素,但不会调用它