I was planning on creating my application and use an ORM for the models, but the thing is, there's a part of the database which uses Entity-Attribute-Value Tables.
I pretty liked Doctrine ORM but I don't know if it is possible to maybe create classes that would look like any ordinary doctrine entity, when the table actually hooked up to is of EAV style.
Would it be possible to use Doctrine on this, and if so, how?
definitely possible:
Have relationships like this: Object (one to many) -> AttributeValue -> Many to One -> AttributeType
In view of EAV it seems to be obvious how to build a relation between entity
and attribute
using doctrine. In the most complicated case we deal with a Many to Many relation.
So lets say we want to map an attribute Name
to an entity User
. Assuming a user has exactly one name and each name belongs to exactly one user this link can be archived using One to One relation
But how to model the relation between attribute
and value
? The problem is that values can be of different types or even need different numbers of fields in order to save their information.
Consider the attributes name
and phone_number
. While a name might be represented by a string, an integer could be needed for the phone number. Or it is even necessary to not only the number but also the area code in a separate filed.
Because EAV requires very flexible value representation, it is not possible to store all of them within the same field in a database table (disregard blobs, data serialization an the like). Therefore most EAV implementations using different tables representing different value types.
In order to reach such flexibility, doctrine features Inheritance Mapping. It basically allows you to extend doctrine entities. Doing so you specify a discriminator
for each sub-type of your entity:
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="value_type", type="string")
* @DiscriminatorMap({"name" = "Name", "phone" = "PhoneNumber"})
*/
class Value
{
// ...
}
/** @Entity */
class Name extends Value
{
// ...
}
/** @Entity */
class PhoneNumber extends Value
{
// ...
}
The Value
class provides common implementation for all values, i.e. an id. Each subclass (i.e. Name
and PhoneNumber
) extend those common values by their specific ones, for example additional fields.
@DiscriminatorColumn
defines a column in the parent relation which stores the type of the value.@DiscriminatorMap
is used by doctrine to map the type from the @DiscriminatorColumn
to one of those classes.The relation between attribute
and value
can be specified to the parent class. Calling values from the attribute then will fetch all types of values which can be filtered (and dealt with) during runtime using for example instanceof.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With