我正在将代码从ZF2移植到ZF3 .
在ZF2中,当我通过FormElementManager创建表单时,我可以访问init方法上的servicelocator并配置一些这样的东西:
public function init()
{
$this->serviceLocator = $this->getFormFactory()->getFormElementManager()->getServiceLocator();
$this->translator = $this->serviceLocator->get('translator');
}
这在非常大的应用中很方便 . 实际上我的所有表单都继承自BaseForm类 .
在ZF3中,这是不好的pratic和serviceLocator已被弃用 . 获得相同结果的最佳方法是哪种?一种方法是使用所需的东西注入ControllerFactory或ServiceFactory中的每个表单,但这非常繁琐 .
任何帮助都很感激 .
1 回答
首先,您不应该在Form对象中使用ServiceManager和/或它的子项(如FormElementManager) .
使用Factory模式,您应该创建功能齐全的独立Form,Fieldset和InputFilter对象 .
肯定会有一些乏味的工作,正如你所说,但你只需要做一次 .
假设您要创建一个位置 . 位置由
name
属性和OneToOne单向Address
引用组成 . 这创造了以下需求:LocationForm(-InputFilter)
LocationFieldset(-InputFilter)
AddressFieldset(-InputFilter)
以上配置
上述6个 class 中的每个 class 的工厂
在这个答案中,我将把所有内容混合到最低限度并使用我自己的存储库中的类和示例,因此对于完整代码,您可以使用here和示例here .
在创建类本身之后,我将向您展示此用例所需的配置以及将所有这些配置在一起的工厂 .
AbstractFieldset
AbstractInputFilter
AddressFieldset
AddressInputFilter
到目前为止,很容易 . 现在,我们需要创建LocationFieldset和LocationFieldsetInputFilter . 这些将使用Address(-Fieldset)类 .
LocationFieldset
LocationFieldsetInputFilter
好的,所以这还不是很令人兴奋 . 请注意,LocationFieldset使用AddressFieldset作为类型 . 相反,在InputFilter类中,需要一个完整的类对象(一个InputFilter实例) .
所以,表格 . 我还使用AbstractForm(在您的情况下为BaseForm)来处理一些默认值 . 在我完整的(在链接回购中),还有一点,但在这里这就足够了 . 这会为表单添加CSRF保护,如果表单没有,则添加提交按钮 . 只有当您调用init时Form类没有任何一个时才能完成此操作,因此您可以覆盖这些设置 .
AbstractForm
LocationForm
现在我们有了制作表格的所有内容 . 我们仍然需要验证 . 我们现在创建这些:
AddressFieldsetInputFilter
LocationFieldsetInputFilter
LocationFormInputFilter
是的,这就是所有课程本身 . 你知道它们将如何嵌套在一起吗?这会创建可重用的组件,这就是为什么我说你只需要这样做一次 . 下次需要地址或位置时,只需确保加载AddressFieldset并在Factory中设置InputFilter . 设置正确的InputFilter的后者是通过Setter Injection the Factories完成的 . 如下所示 .
AbstractFieldsetFactory
AddressFieldsetFactory
LocationFieldsetFactory
AbstractFieldsetInputFilterFactory
AddressFieldsetInputFilterFactory
LocationFieldsetInputFilterFactory
它负责FieldsetInputFilterFactory类 . 只是表格离开了 .
在我的例子中,我使用与Fieldset类相同的抽象工厂类 .
LocationFormInputFilterFactory
所以,这就是所有课程 . 这是一个完整的设置 . 您可能会遇到一些错误,因为我修改了自己的代码以删除getter / setter,代码注释/提示,错误,属性和变量检查而不进行测试 . 但它应该工作;)
但是,我们差不多完成了 . 我们还需要:
配置
控制器中的
用法
打印/使用视图中的表单
配置很简单:
而已 . 这有点将所有上述类别联系在一起 .
要将表单转换为控制器,您可以在工厂中执行以下操作:
一个典型的“编辑”动作就像这样(介意,这个使用Doctrine的EntityManager作为保湿器):
View Partial看起来像这样(基于上面动作中的
return
):表格($ form)?>
就是这样了 . 完全成熟,可重复使用的课程 . 单一设置 . 最后,控制器工厂只有一行 .
请注意:
如果您对此工作原理有任何疑问,请先阅读我首先链接的回购文件中的文档,然后再询问此问题 . 还有更多可以帮助你更多,例如集合处理 .