Search code examples
databasenamespacesdoctrinerelationships

Doctrine Relationship on a namespaced table


I have several doctrine models that have relationships to other models. Let's call those ItemsOne, ItemsTwo, ItemsThree. Each has a relationship defined to the Products doctrine class (products table) and the relationship is defined as:

$this->hasMany(
    'Models_Products as Products',
    array(
     'local'   => 'id',
     'foreign' => 'product_id',
    )
);

Nothing out of the ordinary there.

I also have another table (prices) which stores namespaced data. By that I mean that the particular table stores data based on a predefined key (i.e. Vinyl, CD, DVD) so the rows would show something like this:

media_namespace  entity_id  quantity    unit_price
CD               4          1000        0.99
DVD              4          2500        1.25
CD               7          3750        0.25
Vinyl            15         75          4.25

The entity_id is the id of each of the models accessing this table. So for instance CD/entity_id = 4 refers to ItemsOne model, DVD/entity_id = 4 refers to the ItemsTwo model, etc.

I want to create a relationship - and I don't know if this can be done - whereas it will be namespaced in the model. So in the above snipped for the products relationship I need something like (for the ItemsOne model):

$this->hasMany(
    'Models_Prices as Prices',
    array(
     'local'   => 'id',
     'foreign' => 'entity_id',
    )
);

However the above will return all the prices with the entity_id matching the ItemsOne table which is partly correct. In the above example if entity_id = 4, it will return the CD record but also the DVD one which is not what I need. I want it to be filtering the data based on the media_namespace table. So in short what I need is:

prices.media_namespace = 'CD' AND prices.entity_id = itemsone.id

Can the above be reflected in a hasMany relationship in Doctrine? I have searched and cannot something that would help.

Any pointers are more than appreciated!


Solution

  • You need to use Doctrine subclasses. Create a subclass for each namespace. This will let you reference a specific set of data by class name.

    • class Models_Price
      • subclass Models_Price_CD
      • subclass Models_Price_DVD
      • subclass Models_Price_Vinyl

    In the Price class, you'll need to specify the following:

    public function setUp()
    {
        parent::setUp();
    
        $this->setSubclasses(
            array(
                'Price_CD' => array(
                    'media_namespace' => 'CD',
                ),
                'Price_DVD' => array(
                    'media_namespace' => 'DVD',
                ),
                'Price_Vinyl' => array(
                    'media_namespace' => 'Vinyl',
                ),
            )
        );
    }
    

    Let's make the assumption that ItemsOne uses namespace CD, ItemsTwo uses namespace DVD, and ItemsThree uses namespace Vinyl.

    For this situation, you would add the following relationship to each class:

    ItemsOne:

    $this->hasMany(
        'Models_Price_CD as Prices',
        array(
         'local'   => 'id',
         'foreign' => 'entity_id',
        )
    );
    

    ItemsTwo:

    $this->hasMany(
        'Models_Price_DVD as Prices',
        array(
         'local'   => 'id',
         'foreign' => 'entity_id',
        )
    );
    

    ItemsThree:

    $this->hasMany(
        'Models_Price_Vinyl as Prices',
        array(
         'local'   => 'id',
         'foreign' => 'entity_id',
        )
    );
    

    Now, each of the Prices relations will return only what you expect. Doctrine, seeing the subclass, will automatically namespace all the queries you perform on that table.