ManyToOne リレーションで Doctrine の ObjectSelect を使用するのに少し問題があります。
ManyToMany を使用した以下の関係は、100% 追加および編集できます。私の編集フォームには、現在の選択内容が問題なく取り込まれています。
この問題は ManyToOne 関係で発生します。フォームに現在の選択が取り込まれていないようです。
Task エンティティをフォームにバインドする前にダンプしようとしましたが、100% 正しいように見えます。すべての関係がエンティティに取り込まれています。
ただし、バインドした後、現在の値が選択されていない状態でフォームが表示されます。
タスク エンティティ:
/**
* @ORM\Entity
* @ORM\Table(name="tasks")
*/
class Task
{
/**
* @ORM\Id
* @ORM\Column(type="integer");
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...
/**
* @ORM\ManyToOne(targetEntity="Category")
* @ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
protected $category;
...
/**
* @ORM\ManyToMany(targetEntity="ZDUser\Entity\User")
* @ORM\JoinTable(name="tasks_assigned_user_linker",
* joinColumns={@ORM\JoinColumn(name="task_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}
* )
*/
protected $assignedUsers;
/**
* Initialize
*/
public function __construct()
{
$this->assignedUsers = new ArrayCollection();
}
/**
* We need a few getters and setters
*/
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function getCategory() {
return $this->category;
}
public function setCategory(Category $category) {
$this->category = $category;
}
public function getAssignedUsers() {
return $this->assignedUsers;
}
public function addAssignedUsers(Collection $users) {
foreach ($users as $user) {
$this->assignedUsers->add($user);
}
}
public function removeAssignedUsers(Collection $users) {
foreach ($users as $user) {
$this->assignedUsers->removeElement($user);
}
}
}
私は自分のエンティティのほとんどで ManyToOne を使用しています。この方法は少し簡単で拡張性があると思います。エンティティを追加して他のエンティティにリンクするだけで、両側で関係を作成する必要はありません。
カテゴリ エンティティ
/**
* @ORM\Entity
* @ORM\Table(name="task_categories")
* @property int $id
* @property string $name
*/
class Category
{
/**
* @ORM\Id
* @ORM\Column(type="integer");
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", nullable=false)
*/
protected $name;
...
/**
* Setters and getters we need
*/
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = (int) $id;
}
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
ユーザー エンティティ:
/**
* @ORM\Entity
* @ORM\Table(name="users")
*/
class User implements UserInterface, ProviderInterface
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
...
/**
* @ORM\ManyToMany(targetEntity="ZDUser\Entity\Group")
* @ORM\JoinTable(name="users_groups_linker",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
protected $groups;
/**
* Initialies the object
*/
public function __construct()
{
$this->groups = new ArrayCollection();
}
/* Getters and setters, we must define these for the implementation to work */
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = (int) $id;
}
/* Get and add groups */
public function getGroups()
{
return $this->groups;
}
public function addGroup(Group $group)
{
$this->groups->add($group);
}
フォームコード:
class TaskForm extends Form implements ObjectManagerAwareInterface
{
protected $objectmanager;
public function __construct(EntityManager $em)
{
// we want to ignore the name passed
parent::__construct('task');
$this->setHydrator(new DoctrineHydrator($em,'TaskList\Entity\Task'));
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$this->add(array(
'name' => 'subject',
'type' => 'Text',
'options' => array(
'label' => 'Subject',
),
));
$this->add(array(
'name' => 'category',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'label' => "Category",
'object_manager' => $em,
'target_class' => 'TaskList\Entity\Category',
'property' => 'name',
),
));
$this->add(array(
'name' => 'assignedUsers',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'attributes' => array(
'multiple' => 'multiple',
),
'options' => array(
'label' => "Assigned To (User)",
'object_manager' => $em,
'target_class' => 'ZDUser\Entity\User',
'property' => 'email',
),
));
編集と追加のコントローラー:
public function addAction()
{
$this->addedit();
// Grab form
$form = new TaskForm($this->getEntityManager());
// Grab any request we may have
$request = $this->getRequest();
// If it a post ...
if ($request->isPost()) {
$task = new Task();
$form->bind($task);
// Populate data
$form->setData($request->getPost());
// Check if the form is valid
if ($form->isValid()) {
// Setup some things we need
$task->setCreated(new \DateTime("now"));
// Save
$this->getEntityManager()->persist($task);
$this->getEntityManager()->flush();
// Redirect to list of tasks
return $this->redirect()->toRoute('tasklist');
}
}
return array(
'form' => $form
);
}
public function editAction()
{
$this->addedit();
// Get ID or redirect
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('tasklist');
}
// Create a form
$form = new TaskForm($this->getEntityManager());
// Grab entity from doctrine
$task = $this->getEntityManager()->find('TaskList\Entity\Task', $id);
// Bind the form to the task
$form->bind($task);
// Check if we have a request and if its POST
$request = $this->getRequest();
if ($request->isPost()) {
// If it is, set the form data from the request
$form->setData($request->getPost());
// If the form is valid, bind the values
if ($form->isValid()) {
// Setup some things we need
$task->setLastUpdated(new \DateTime("now"));
// Flush the update
$this->getEntityManager()->flush();
// Redirect to list of tasks
return $this->redirect()->toRoute('tasklist');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
本当に単純なものが欠けていると確信しています。