2

我正在开发我的自定义用户模块,它基本上使用 ZfcUser 作为基础。由于每个应用程序都是不同的,并且需要有关用户的不同元信息,因此我希望使用配置数组可以轻松地对其进行配置。

在我的模块的全局配置文件中,我定义了自定义表单字段,在模块的 onBootstrap 中,我使用 ZfcUser\Form\Register 的 init 事件扩展了 ZfcUser 注册表单。所以简而言之,我想做这样的事情:

$sharedEvents->attach('ZfcUser\Form\Register',
                'init',
                function($e) use ($sm)
                {
                    /* @var $form \ZfcUser\Form\Register */
                    $form = $e->getTarget();

                    // Get relevant config
                    $config = $sm->get('config');
                    if ( array_key_exists('redev_user', $config) && is_array($config['redev_user']) )
                    {
                        if ( array_key_exists('custom_fields', $config['redev_user']) && is_array($config['redev_user']['custom_fields']) )
                        {
                            foreach ($config['redev_user']['custom_fields'] as $curCustomField)
                            {
                                $form->add($curCustomField);
                            }
                        }
                    }
[...]

然后在我的配置文件中定义自定义表单字段,如下所示:

<?php
return array(
    'redev_user' => array(
        'custom_fields' => array(
            // Custom fields which will be added to the registration form
            array(
                    'name' => 'firstname',
                    'type' => 'text',
                    'options' => array(
                            'label' => 'First name',
                    ),
            ),

我对验证者做同样的事情;它们在配置文件中定义并附加到 onBootstrap 中的表单元素。

这一切都很好,花花公子,除非我需要一个 Doctrine 表单元素。在我的具体情况下,我想使用 DoctrineModule\Form\Element\ObjectSelect 作为国家选择框。在我的配置中,这看起来像这样:

array(
           'name' => 'country',
           'type' => 'DoctrineModule\Form\Element\ObjectSelect',
           'options' => array(
           'label' => 'Country',
           //'object_manager' => $sm->get('Doctrine\ORM\EntityManager'),
           'target_class'   => 'RedevUser\Entity\Country',
           'property'       => 'countryname',
           'is_method'      => false,
           'find_method'    => array(
               'name'   => 'findBy',
               'params' => array(
                               'criteria' => array(),
                                'orderBy'  => array('countryname' => 'ASC'),
                           ),
            ),
       ),
     ),

请注意 object_manager 的注释行。ObjectSelect 元素显然需要 ObjectManager。问题是如何在基于配置呈现表单时注入 ObjectManager。

我正在考虑自己渲染表单元素,然后检查它是否是某个接口的实例或 DoctrineModule\Form\Element 的基类。然而事实证明没有这样的基类或接口。这些元素唯一的共同点是它们都有一个 getProxy。现在我在 onBootstrap 中的代码如下所示:

foreach ($config['redev_user']['custom_fields'] as $curCustomField)
{
    $formElemFactory = $form->getFormFactory();
    $elem = $formElemFactory->createElement($curCustomField);

    if ($elem instanceof \DoctrineModule\Form\Element\ObjectSelect)
    {
         // Inject ObjectManager
         $elem->getProxy()->setObjectmanager($sm->get('Doctrine\ORM\EntityManager'));
    }

    $form->add($elem);
}

但我真的不想检查不同的 Doctrine 表单元素类型。而且这样做似乎有点脏。关于如何做得更好/更清洁的任何意见或想法?

4

0 回答 0