Let me start by outlining the scenario. I have a Note object that can be assigned to many different objects
Personally I wouldn't use a superclass here. Think there's more of a case for an interface that would be implemented by Book
, Image
and Address
:
interface iNotable
{
public function getNotes();
}
Here's Book as an example:
class Book implements iNotable {
/**
* @OneToMany(targetEntity="Note", mappedBy="book")
**/
protected $notes;
// ...
public function getNotes()
{
return $this->notes;
}
}
Note
then needs @ManyToOne
relationships going the other way, only one of which will apply for each entity instance:
class Note {
/**
* @ManyToOne(targetEntity="Book", inversedBy="notes")
* @JoinColumn
**/
protected $book;
/**
* @ManyToOne(targetEntity="Image", inversedBy="notes")
* @JoinColumn
**/
protected $image;
/**
* @ManyToOne(targetEntity="Address", inversedBy="notes")
* @JoinColumn
**/
protected $address;
// ...
}
If you don't like the multiple references to each notable class here you could use inheritance and have something like an AbstractNotable
superclass using single table inheritance. Although this might seem tidier now, the reason I wouldn't recommend it is as your data model grows you may need to introduce similar patterns that could eventually make the inheritance tree become unmanageable.
EDIT: It would also be useful to have Note
validator to ensure data integrity by checking that exactly one of $book
, $image
or $address
is set for each instance. Something like this:
/**
* @PrePersist @PreUpdate
*/
public function validate()
{
$refCount = is_null($book) ? 0 : 1;
$refCount += is_null($image) ? 0 : 1;
$refCount += is_null($address) ? 0 : 1;
if ($refCount != 1) {
throw new ValidateException("Note references are not set correctly");
}
}