形成选择父母水合作用

时间:2014-01-24 15:52:20

标签: php forms doctrine-orm zend-framework2

我有一个与doctrine一起使用的zf2应用程序。 我有以下实体:

class Role
{
    /**
     * @var int
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(type="string", length=255, unique=true, nullable=true)
     */
    protected $name;

    /**
     * @var ArrayCollection
     * @ORM\OneToMany(targetEntity="YrmUser\Entity\Role", mappedBy="parent")
     */
    protected $children;

    /**
     * @var Role
     * @ORM\ManyToOne(targetEntity="YrmUser\Entity\Role", inversedBy="children", cascade={"persist"})
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     */
    protected $parent;
}

对于这个实体,我有一个表格:

class RoleForm extends Form
{

    /**
     * [init description]
     * 
     * @return void
     */
    public function init()
    {

        $this->setHydrator(
            new DoctrineHydrator($this->objectManager, 'YrmUser\Entity\Role')
        )->setObject(new Role());

        $this->setAttribute('method', 'post');


        $this->add(
            array(
                'name' => 'name',
                'attributes' => array(
                    'type'  => 'text',
                    'placeholder' =>'Name',
                ),
                'options' => array(
                    'label' => 'Name',
                ),
            )
        );
        $this->add(
            array(
                'type' => 'DoctrineModule\Form\Element\ObjectSelect',
                'name' => 'parent',
                'attributes' => array(
                    'id' => 'parent_id',
                ),
                'options' => array(
                    'label' => 'Parent',
                    'object_manager' => $this->objectManager,
                    'property'       => 'name',
                    'is_method'      => true,
                    'empty_option' => '-- none --',
                    'target_class'   => 'YrmUser\Entity\Role',
                    'is_method'      => true,
                    'find_method'    => array(
                        'name'   => 'findBy',
                        'params' => array(
                            'criteria' => array('parent' => null),
                        ),
                    ),
                ),
            )
        );
    }
}

表单中select的水合作用,因为它只显示没有父级的其他角色。 但是在编辑现有实体时,它会在选择中显示自己,因此我可以选择自己作为其父级。 我想如果我将在表单中包含当前实体的id,我可以使用一种方法创建一个自定义repo,该方法可以检索没有父项的所有角色,并且没有当前实体ID。 但是我无法弄清楚如何从表单中获取当前编辑实体的id。

感谢任何帮助。

干杯,

YRM

1 个答案:

答案 0 :(得分:1)

您可以使用$this->getObject()来获取表单中的绑定实体。

您实际上已经使用setObject(new Role());进行了设置。不幸的是,这意味着它没有通过Doctine加载,你会遇到同样的问题,没有$id可以使用。

因此,您需要在之后添加“父角色”选项(value_options,您已通过教条绑定了加载的角色。

在控制器中,我通常从服务类请求“编辑”表单,并传入正在编辑的实体实例或ID。设置完成后,您可以在将现有表单元素传递回控制器之前对其进行修改。

// Controller
class RoleController
{
   public function editAction()
   {
     $id      = $this->params('id'); // assumed id passed as param
     $service = $this->getRoleService();
     $form    = $service->getRoleEditForm($id); // Pass the id into the getter 

     // rest of the controller...
   }  
}  

通过在获取表单时传入$id,您可以在服务中修改该特定角色的表单元素。

class RoleService implements ObjectManagerAwareInterface, ServiceLocatorAwareInterface
{
  protected function loadParentRolesWithoutThisRole(Role $role);

  public function getRoleEditForm($id)
  {
    $form = $this->getServiceLocator()->get('Role\Form\RoleEditForm');

    if ($id) {
      $role = $this->getObjectManager()->find('Role', $id);
      $form->bind($role); // calls $form->setObject() internally

      // Now the correct entity is attached to the form
      // Load the roles excluding the current
      $roles = $this->loadParentRolesWithoutThisRole($role);

      // Find the parent select element and set the options
      $form->get('parent')->setValueOptions($roles); 
    }

    // Pass form back to the controller
    return $form;
  }
}

通过在表单初始化后加载选项,您不需要当前的DoctrineModule\Form\Element\ObjectSelect。没有定义默认value_options的普通Select元素应该没问题。