Dan Blows
Dan Blows

Reputation: 21184

How do I build something like query inheritance with Doctrine2?

I'm building a small website with Symfony2 and Doctrine2. There are blog posts, events and press releases. Each of these is so similar that I decided to use single table inheritance (STI) with a parent table called 'Node'.

Nodes have:

By default, I only want to display published nodes that are from the current locale.

Obviously, I could create lots of queries in the repository that look something like:

$this->createQueryBuilder('Event')
     ->where('Node.published = 1')
     ->where('Node.locale = :locale')

but this doesn't seem very DRY.

So how do I build a default query which other queries can 'inherit' from? This should include default Doctrine queries based on relations.

Upvotes: 1

Views: 1646

Answers (2)

timdev
timdev

Reputation: 62894

Inheritance is probably overkill.

Why not just create a little factory method that gives you a preconfigured queryBuilder?

class NodeRepository extends Doctrine\ORM\EntityRepository {

    public function getLocalizedNodeQueryBuilder($type,$locale){
        return $this->getQueryBuilder($type)
            ->where('Node.published = 1')
            ->where('Node.locale = :locale')
            ->setParameter('locale',$locale);
    }
}

You could do the same thing, and simply override getQueryBuilder if you're sure you always want your querybuilder configured that way.

Upvotes: 4

Lee Davis
Lee Davis

Reputation: 4756

You don't need to build anything like that into your repository classes. If you set up single table inheritance with a "Discriminator Map" you'll end up with seperate classes (Entities). Doctrine will take care of filtering by your "node type" when it interacts with the DBAL.

http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/inheritance-mapping.html#single-table-inheritance

For example..

namespace MyProject\Model;

/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"node" = "Node", "blogpost" = "Blogpost", "events" = "Events"})
 */
class Node
{
    // ...
}

/**
 * @Entity
 */
class Blogpost extends Node
{
    // ...
}

/**
 * @Entity
 */
class Events extends Node
{
    // ...
}


// get me all the blogposts
$blogposts = $em->getRepository('Blogpost')->findAll();

// get me all the events
$events = $em->getRepository('Events')->findAll();

This is especially beneficially as you'll be able to encapsulate your "Blogpost" logic into its own entity, rather than trying to represent it with its parent class "Node".

Upvotes: 2

Related Questions