I have two entities Rental
and Item
. Item
s are associated to Rental
s via a join table including some metadata, so that the join table effectively becomes a third entity RentedItem
.
Because a RentedItem
can be identified by its associated Rental
and Item
, it doesn't need its own ID but uses a compound key consisting of those two foreign keys as primary key instead.
/**
* @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;
// ...
}
A Rental
can be created or altered via a RESTful API, including some of its related objects. The corresponding controller uses the DoctrineObject
hydrator of the ZF2 DoctrineModule to hydrate the rental object with the given form data. The new data is passed to the hydrator as an array of the form
$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
]
]
];
Usually the hydrator sets up the references correctly, even for completely new entities and new relations. However, with this complex association, hydrating the Rental
fails. The code
$hydrator = new \DoctrineModule\Stdlib\Hydrator\DoctrineObject($entity_manager);
$rental = $hydrator->hydrate($data, $rental);
fails with the following exception
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
Do I have to manually set up the references for the rented items? Or may this be caused by a faulty configuration or something?