Im trying to create a very dry and reusable resource controller for an api to cut down on re-coding implementations for a-lot of entities.
creating resource methods for show() and delete() is easy as long as you know the $id of the resource. store and update methods get a bit tricky.
Im using lumen 5.3 and laraveldoctrine for my database orm.
I have a middleware that validates requests using doctrine before they hit the controller. So only valid payloads will only ever hit the controller so in theory i should just be able to create a reusable function to store/update entities from requests regardless of what entity/controller is
so far i have something like this
public function setEntityFromPayload(array $payload, DoctrineEntity $entity)
{
$cols = $this->_em->getClassMetadata(get_class($entity))->getFieldNames();
foreach ($payload as $key => $value) {
if(array_key_exists($key,$cols)) {
$setter = 'set'.ucfirst($col);
$entity->$setter($value);
}
}
return $entity;
}
Which works for simple entities. But it get's a bit more complex when you talk about entities with associations to other entities.
It's not to hard to figure out one-to-many associations by getting the association mappings like
$this->_em->getClassMetadata(get_class($entity))->getAssociationMappings();
Looking for 'target_entity' in the array and instantiating the target entity with the value in the payload, what i can't work out is how to check if an attribute is a many-to-many or if it's an array collection, as this part of the function
if(array_key_exists($key,$cols)) {
$setter = 'set'.ucfirst($col);
$entity->$setter($value);
}
will need some logic to use an adder function on the entity like
public function addTag(Tag $tag) {
if (!$this->tag->contains($tag)) {
$this->tag->add($tag);
}
return $this;
}
I've looked through ClassMetadataInfo and cant find anything that does this.
Any one with deeper Doctrine knowledge might know if this is possible
via user618509