ZF2,使用Vendor Module的Form类的最佳实践是什么?

Jae*_*pil 11 zend-framework2

我应该如何将自定义样式应用于供应商模块的表单或将其嵌入到我自己的View脚本中?更具体地说,我想使用EdpUser Module(https://github.com/EvanDotPro/EdpUser)提供的表单.

最简单的方法似乎是直接修改供应商的脚本.但显然这会与供应商未来的更新产生冲突.

另一种方式似乎是将Vendor的Controller复制到我自己的Module中,然后提供我自己的视图.但是,这会遇到与供应商未来更新不同步的类似问题.我必须小心命名空间.

也许我应该扩展供应商的控制器而不是复制它.这应该适用于命名空间,我应该能够很容易地访问我的控制器中的窗体.在使用我自己的视图脚本时.这是正确的方式还是有更好的方式?

谢谢

Jur*_*man 36

修改模块目录中的任何内容都不是推荐的方法,特别是那些放入的模块/vendor/.这也是必须将配置模板复制到您自己的/config/autoload/目录的原因.

模块必须提供足够的扩展点,以使其足够灵活以供您使用.这些可能性包括以下选项:

改变路线

ZfcUser模块在/ user url下注册自己.例如,如果要将其更改为/ account,只需将其添加到您的配置中:

<?php
return array(
    'di' => array(
        'instance' => array(
            'Zend\Mvc\Router\RouteStack' => array(
                'parameters' => array(
                    'routes' => array(
                        'zfcuser' => array(
                            'options' => array(
                                'route' => '/account',
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
);
Run Code Online (Sandbox Code Playgroud)

更换控制器

如果您不满意ZfcUser\Controller\UserController并且想要覆盖此控制器中的某些操作,则可以创建自定义控制器MyUser\Controller\UserController.如果您扩展ZfcUser\Controller\UserController并提供此配置,您就可以开始:

<?php
return array(
    'di' => array(
        'instance' => array(
            'Zend\Mvc\Router\RouteStack' => array(
                'parameters' => array(
                    'routes' => array(
                        'zfcuser' => array(
                            'options' => array(
                                'defaults' => array(
                                    'controller' => 'MyUser\Controller\UserController'
                                ),
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
);
Run Code Online (Sandbox Code Playgroud)

您还可以使用DI别名来覆盖zfcuserDI配置中的别名:

<?php
return array(
    'di' => array(
        'instance' => array(
            'alias' => array(
                'zfcuser' => 'MyUser\Controller\UserController'
            ),
        ),
    ),
);
Run Code Online (Sandbox Code Playgroud)

修改表单实例

例如,ZfcUser模块触发多个事件以帮助其他模块挂钩到表单创建过程.在设置所有表单元素之后,ZfcUser\Form\Loginas ZfcUser\Form\Register触发init事件.这使您有机会添加或删除元素.

use Zend\EventManager\StaticEventManager;

$events = StaticEventManager::getInstance();
$events->attach('ZfcUser\Form\Login', 'init', function ($e) {
  $form = $e->getTarget();
  $form->addElement('text', 'something-new');
});
Run Code Online (Sandbox Code Playgroud)

我需要在这里发表两点评论:

  1. 每个模块都必须提供自己的触发器.这个ZfcUser有init两种形式,但这不是每个模块的给定.您必须查看文档或源代码以了解相关信息.
  2. Zend\EventManager目前是一个重构下更换单StaticEventManagerSharedEventManager这可以通过被实例化实例Zend\Di定位器.您可以在此Pull请求中查看此重构的进度.

更改视图或表单呈现

根据此RFC,Zend\Form组件可能会发生变化.特别是对于渲染,装饰器将被移除,"只是"普通视图助手将呈现形式.有了这个,再加上覆盖视图的可能性,只需使用另一个只有一些视图脚本的模块就可以很容易地改变动作的渲染.

如果您创建自己的模块并提供此配置,则向模板路径堆栈添加新位置:

<?php
return array(
    'di' => array(
        'instance' => array(
            'Zend\View\Resolver\TemplatePathStack' => array(
                'parameters' => array(
                    'paths' => array(
                        'myuser' => __DIR__ . '/../view',
                    ),
                ),
            ),
        ),
    ),
);
Run Code Online (Sandbox Code Playgroud)

现在,您可以在模块的view目录中创建视图脚本.如果您的模块名为"MyUser"并位于其下,/modules/MyUser并且您想要覆盖ZfcUser的登录视图脚本(位于/vendor/ZfcUser/view/zfcuser/login.phtml,请在中创建您的视图脚本)/modules/MyUser/view/zfcuser/login.phtml.

  • Jurian,你的答案刚刚帮助了我 - 谢谢.只是对其他人的快速补充:覆盖View脚本似乎取决于application.config.php中模块的顺序.您要覆盖的模块必须放在*将覆盖它的模块之前*.我想这真的很有道理,但我花了一两分钟才弄清楚为什么我的视图覆盖不起作用...... (4认同)