How do I build something like query inheritance wi

2019-06-04 22:27发布

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:

  • a 'published' field, which is boolean
  • a 'locale' field, which is a string and says 'this is only to be shown in this locale'. (The locale is passed in via the request).

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.

2条回答
一纸荒年 Trace。
2楼-- · 2019-06-04 22:38

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.

查看更多
不美不萌又怎样
3楼-- · 2019-06-04 22:48

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".

查看更多
登录 后发表回答