Reputation: 1183
is it possible to create a relation to a generic table/class whith Doctrine?
Here is some code to make it easier to understand:
// class Log...
// TODO:
// It could be useful to have a reference to
// the element mentioned by the log, the issue is
// we don't know what kind of entity it is.
/**
* @ORM\ManyToOne(targetEntity="???")
*/
private $elementId
Maybe instead of using targetEntity
I could just use an int that is the id of the element located in the unknow table.
Upvotes: 2
Views: 114
Reputation: 3135
There is no built-in possibility now.
Let me propose a work around using Doctrine Lifecycle Events :
Create 3 properties :
/*
* @ORM\Column(name="element_class", type="string")
*/
private $elementClass
/*
* @ORM\Column(name="element_id", type="integer")
*/
private $elementId
// Not mapped
private $element
public function setElement($element)
{
$this->element = $element;
$this->elementClass = get_class($element);
$this->elementId = $element->getId();
}
public function getElement()
{
return $this->element;
}
// You need these for the PostLoad event listener :
public function hydrateElementPostLoad($element)
{
$this->element = $element;
}
public function getElementClass()
{
return $this->elementClass;
}
public function getElementId()
{
return $this->elementId;
}
Then create a PostLoadListener able to hydrate the element property :
namespace AppBundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use AppBundle\Entity\Log;
class PostLoadListener
{
public function postLoad(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if($entity instanceOf Log){
$em = $args->getEntityManager();
$entity->hydrateElementPostLoad(
$this->em->getRepository($entity->getElementClass())->findOneById($entity->getElementId())
);
}
}
}
And register this event in your services.yml :
services:
places.listener:
class: AppBundle\EventListener\PostLoadListener
tags:
- { name: doctrine.event_listener, event: postLoad }
That's also how the most famous Bundle for logging works (The Gedmo DoctrineExtensions Logger)
To retrieve all logs for an entity, create a repository method for your Log entity :
getLogs($entity)
{
return $this->_em->findBy(array(
'element_id'=>$entity->getId(),
'element_class'=>get_class($entity)
));
}
Upvotes: 2
Reputation: 2048
You are trying to manage some abstraction of one or more of your entities in the database level which is a headache,
Doctrine already has proposed Somme solutions to manage this kind of abstractions by using Inheritance Mapping
A mapped superclass is an abstract or concrete class that provides persistent entity state and mapping information for its subclasses, but which is not itself an entity. Typically, the purpose of such a mapped superclass is to define state and mapping information that is common to multiple entity classes.
For more information check this
Upvotes: 2