У меня есть две сущности Rental
а также Item
, Item
с связаны с Rental
через таблицу соединения, включающую в себя некоторые метаданные, так что таблица соединения фактически становится третьей сущностью RentedItem
,
Потому что RentedItem
может быть идентифицировано его связанным Rental
а также Item
ему не нужен собственный идентификатор, но вместо этого он использует составной ключ, состоящий из этих двух внешних ключей, в качестве первичного ключа.
/**
* @ORM\Entity
*/
class Rental
{
// ...
/**
* @ORM\OneToMany(targetEntity="RentedItem", mappedBy="rental", cascade={"all"})
* @var ArrayCollection $rented_items
*/
protected $rented_items;
// ...
}
/**
* @ORM\Entity
*/
class Item
{
// ...
// Note: The Item has no notion of any references to it.
}
/**
* @ORM\Entity
*/
class RentedItem
{
// ...
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Rental", inversedBy="rented_items")
* @var Rental $rental
*/
protected $rental;
/**
* @ORM\Id
* @ORM\ManyToOne(targetEntity="Item")
* @var Item $item
*/
protected $item;
/**
* @ORM\Column(type="boolean")
* @var bool $is_returned
*/
protected $is_returned = false;
// ...
}
Rental
может быть создан или изменен через RESTful API, включая некоторые связанные с ним объекты. Соответствующий контроллер использует DoctrineObject
Гидратор модуля ZF2 DoctrineModule для гидратации объекта аренды с данными данной формы. Новые данные передаются в гидратор в виде массива вида
$data = [
// We only use the customer's ID to create a reference to an
// existing customer. Altering or creating a customer via the
// RestfulRentalController is not possible
'customer' => 1,
'from_date' => '2016-03-09',
'to_date' => '2016-03-22',
// Rented items however should be alterable via the RestfulRentalController,
// because they don't have their own API. Therefore we pass
// the complete array representation to the hydrator
'rented_items' => [
[
// Again, just as we did with the customer,
// only use the referenced item's ID, so that
// changing an item is not possible
'item' => 6,
'is_returned' => false
// NOTE: obviously, the full array representation of
// a rented item would also contain the 'rental' reference,
// but since this is a new rental, there is no id yet, and
// the reference should be implicitly clear via the array hirarchy
],
[
'item' => 42,
'is_returned' => false
]
]
];
Обычно гидратор устанавливает ссылки правильно, даже для совершенно новых объектов и новых отношений. Тем не менее, с этой сложной ассоциацией, увлажнение Rental
выходит из строя. Код
$hydrator = new \DoctrineModule\Stdlib\Hydrator\DoctrineObject($entity_manager);
$rental = $hydrator->hydrate($data, $rental);
терпит неудачу со следующим исключением
Doctrine\ORM\ORMException
File:
/vagrant/app/vendor/doctrine/orm/lib/Doctrine/ORM/ORMException.php:294
Message:
The identifier rental is missing for a query of Entity\RentedItem
Нужно ли вручную устанавливать ссылки для арендуемых предметов? Или это может быть вызвано неправильной конфигурацией или чем-то еще?
Задача ещё не решена.
Других решений пока нет …