Question

as pointed out here: Doctrine 2.1 - Map entity to multiple tables Doctrine2 does not allow mapping of one object to multiple tables.

I currently have a Mysql db setup similar to this:

base_entity: id, some_basic_data_columns
state: id, state, entity_id (FK to base_entity.id), start_time, end_time, ...

entity_one: id (FK to base_entity.id), some_specific_data
entity_two: id (FK to base_entity.id), some_specific_data
and so on...

In a way, entity_x is "extending" base_entity, and all these entities can have multiple states. To have proper foreign keys I would have to either have separate state tables (which I don't want to do because they will structurally be the same ), or do it like this.

The base entity by itself is useless, id could even be boiled down to just the id field to allow to join with each child entity to multiple states.

I do not need a BaseEntity class, but I do need for each child Entity to have a getStates() method. Of course I may actually have an abstract entity class, but concrete entities will extend it, not have it as a property like they would if I would map them as one would map other one-to-one relationships

Since Doctrine will not allow me to map EntityOne to both entity_one and base_entity table I have to ask:

  1. Is this bad design? Am I overlooking some other way to solve this elegantly? I know other DMBSs have inheritance, but for instance PostgreSql would still not allow me to join the base_entity to state if no physical base_entity exists for a child.

  2. I could do something like this on the code side:

    class EntityOne {
        // baseEntity as a property
        private $_baseEntity;
    
        // private getter for the base table
        private getBaseEntity();
    
        // and getters like this for properties in the base table
        public getStates(){ 
             return $this->getBaseEntity()->getStates();
        }
    } 
    

    This way the entity would behave like a single entity (not combined from base and child) to the outside world, but it would still require that I write a separate BaseEntity class and all the config info to connect it to other entity classes

Basically, what I'm asking is: is this a Db design issue, and I got it completely wrong from the start (and if I did, which is the "best" approach), or is this a code issue, and I should work around it with code (if so, is my approach in 2. ok, or are there better ways to deal with this), and are there ORMs which allow for multiple table mapping?

Many thanks in advance.

Was it helpful?

Solution

You could use Class Table Inheritance (see Doctrine documentation about that), defining a BaseEntity entity class, and and create EntityOne and EntityTwo extending that. You could define the relationship between the BaseEntity class and the State entity class as one-to-many association - if I understood right what you wanted, providing the needed getState() method in the BaseEntity class.

Something like this:

/**
 * @Entity
 * @Table(name="base_entity")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="entity_type", type="string")
 * @DiscriminatorMap({"entity_one"="EntityOne", "entity_two"="EntityTwo"})
 */
class BaseEntity {

    /**
     * @Id
     * @Column(type="integer")
     */
    protected $id;

    /**
     * @OneToMany(targetEntity="State", mappedBy="entity)
     **/
    protected $states;

    public function getStates() {
        return $this->states;
    }

    ...
}

/**
 * @Entity
 * @Table(name="entity_one")
 */
class EntityOne extends BaseEntity {

    ...
}

/**
 * @Entity
 * @Table(name="entity_two")
 */
class EntityTwo extends BaseEntity {

    ...
}

/**
 * @Entity
 * @Table(name="state")
 */
class State {

    /**
     * @ManyToOne(targetEntity="BaseEntity", inversedBy="states")
     * @JoinColum(name="entity_id", referencedColumnName="id")
     */
    protected $entity;

    public function getEntity() {
        return $this->entity;
    }

    ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top