我有一个与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
答案 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元素应该没问题。