ufucuk
ufucuk

Reputation: 475

Accessing relations of a table with inheritance

I have an Inheritance class as shown here:

Relations

As you can easily see users, buildings and hotels have addresses (more than one) and address table keeps the id of the owner in whose column.

  1. Is my logic correct?
  2. Let's say I want to get the address of user (or buildings or hotels) whose id is 2; must I run a DQL statement (and how?) or can I get it with find() function without DQL?

And I'll be happy if you give example since Doctrine documentation doesn't help much.

Thanks.

Edit: users, buildings and hotels are just symbolic names that is why they can have multiple addresses otherwise buildings and hotels would have only one address.

Edit 2:I think I couldn't make myself clear, when I talk about the Class Table Inheritance I mean entity class has the Discriminator column as

/**
 * ...
 *
 * @DiscriminatorColumn(name="classname", type="string")
 * @DiscriminatorMap({"Entities\users" = "Entities\users",
 * "Entities\buildings" = "Entities\buildings"}) ... etc
 */

Each and every subclass is related to parent (Entity) with the foreign key relation as "id". But of course doctrine creates this relation already for me.

Upvotes: 3

Views: 838

Answers (3)

Mahfuz
Mahfuz

Reputation: 11

/**
 *
 * @Entity
 * @Table(name="proposaltemplate")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="entitytype", type="string")
 * @DiscriminatorMap({"proposal" = "ProposalTemplate","page" = "PageTemplate"})
 *
 */

abstract class AbstractProposalTemplate
{
    /**
     *
     * @var integer
     * @Id
     * @Column(type="integer")
     * @generatedValue(strategy="AUTO")
     *
     */
    private  $id;
}

next

@Entity 

class ProposalTemplate extends AbstractProposalTemplate
{

      @Id
      @Column(type="integer")
      @generatedValue(strategy="AUTO")


    private  $id;

}
next another class

  @Entity

class PageTemplate extends AbstractProposalTemplate
{
   /**
     *
     * @var integer
     * @Id
     * @Column(type="integer")
     * @generatedValue(strategy="AUTO")
     *
     */
    private  $id;
}

Upvotes: 1

Lars Strojny
Lars Strojny

Reputation: 665

Usually an Address is a typical value object. Value objects are usually stored with the entity compositing the value object so it is neither about relations nor about class table inheritance. If your domain indicates otherwise (e.g. you can do something with your address, meaning), they might be an entity, than entity Hotel holds an entity Address (persisted in a n:m relation table) and entity Building holds and Address too (in a different n:m relation table).

If you go the value object route, things are different. You would store the address with the Building entity as well as with the Hotel entity (as you would do it with other value objects may it be Moneyor Email or Password). So you don’t need relations at all, just a few more fields. The issue with Doctrine 2 is, that it does not support Component mapping. Component mapping would be used to nicely store value objects. T accomplish the same thing with Doctrine 2, you would implement a @prePersist and a @postLoad handler like that:

class Hotel
{
    private ;

    /** These fields are persisted */

    /** @Column(type=string) */
    private $addressStreet;
    /** @Column(type=string) */
    private $addressCity;
    /** @Column(type=string) */
    private $addressZip;
    /** @Column(type=string) */
    private $addressCountry;

    /** @prePersist */
    public function serializeValueObjects()
    {
        $this->addressStreet = ->address->getStreet();
        $this->addressCity = ->address->getCity();
        $this->addressZip = ->address->getZip();
        $this->addressCountry = ->address->getCountry();
    }


    public function unserializeValueObjects()
    {
        $this->address = new Address(->addressStreet, ->addressCity, ->addressZip, ->addressCountry);
    }
}

As you need to serialize/unserialize Address value objects in various places, you might want to extract the serializing code into a separated class.

Upvotes: 1

timdev
timdev

Reputation: 62894

So you've got a superclass called "Entity", which has subclasses "User", "Building", and "Hotel".

Your "Entity" entity should have a OneToMany relation to Address. Let's imagine it looks like this, in your Entity definition:

/**
 * @OneToMany(targetEntity="Address", mappedBy="whose"
 */
protected $addresses;

This is a more-or-less fine approach, though the use of inheritance is a little smelly.

Then if you want to iterate over the addresses, from inside User, Building, or Hotel:

foreach($this->addresses as $address){
    //do something with adderess
}

Does that answer your question?

Upvotes: 0

Related Questions