【问题标题】:Where-ing in discriminated tables区分表中的位置
【发布时间】:2013-02-13 10:39:03
【问题描述】:

如何选择一位特定作者的所有项目?这种方式可能吗?或者,如果我想要许多项目类型和项目包(项目有很多项目),我该如何编辑实体?

物品

/**
 * @ORM\Table()
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({
 * "cd"   = "ItemCD",
 * "dvd"   = "ItemDVD",
 * "pack" = "ItemPack",
 * })
 */
class Item
{

    /**
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=250, nullable=false)
     */
    private $name;

}

物品CD

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class ItemCD extends Item
{

    /**
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="item")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     */
    private $author;

}

物品DVD

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class ItemDVD extends Item
{

    /**
     * @ORM\ManyToOne(targetEntity="Author", inversedBy="item")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     */
    private $author;

}

物品包

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class ItemPack extends Item
{

    /**
     * @ORM\ManyToMany(targetEntity="Item", inversedBy="item")
     * @ORM\JoinTable()
     */
    private $items;

}

作者

/**
 * @ORM\Table()
 * @ORM\Entity
 */
class Author
{

    /**
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     *
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=250, nullable=false)
     */
    private $name;

}

【问题讨论】:

    标签: php doctrine doctrine-orm dql


    【解决方案1】:

    您必须查询特定元素。这是一个已知的(并且想要的)限制,因为 DQL 是一种静态类型语言:请参阅 http://www.doctrine-project.org/jira/browse/DDC-16

    相关:how to access fields in inherited table in doctrine2 / dql query

    一种解决方法是在 DQL 中使用 2 个子查询:

    SELECT
        i
    FROM
        Item i
    WHERE
        i.id IN(
            SELECT 
                i2.id
            FROM
                ItemDvd i2
            WHERE
                i2.author = :author
        )
        OR
        i.id IN(
            SELECT
                i3.id
            FROM
                ItemCd i3
            WHERE
                i3.author = :author
        )
    

    如您所见,您必须手动提取每个可能的子类型的标识符。

    编辑:要从给定作者那里获取所有包(以及单个 DVD 或 CD),查询会变得更糟:

    SELECT
        i
    FROM
        Item i
    WHERE
        i.id IN(
            SELECT 
                i2.id
            FROM
                ItemDvd i2
            WHERE
                i2.author = :author
        )
        OR
        i.id IN(
            SELECT
                i3.id
            FROM
                ItemCd i3
            WHERE
                i3.author = :author
        )
        OR
        i.id IN(
            SELECT
                i4.id
            FROM
                ItemPack i4
            JOIN
                i4.items i5
            WHERE
                i5.id IN (
                    SELECT
                        i6.id
                    FROM
                        Item i6
                    WHERE
                        i6.id IN(
                            SELECT 
                                i7.id
                            FROM
                                ItemDvd i7
                            WHERE
                                i7.author = :author
                        )
                        OR
                        i6.id IN(
                            SELECT
                                i8.id
                            FROM
                                ItemCd i8
                            WHERE
                                i8.author = :author
                        )
                )
        )
    

    【讨论】:

      【解决方案2】:

      在 Item 中创建 $author 并使 ItemPacks $author 值始终为空。然后你可以这样做:

      $em->findBy("Item", array("author" => $author));
      

      而且您总是会得到 ItemDVDItemCD 的实例。

      【讨论】:

      • 您不能按“作者”搜索,因为“作者”不是“项目”的属性。
      • 啊,对 :\ 虽然这基本上(从逻辑的角度)为包分配了一个作者。从 OOP 的角度来看,这又很奇怪
      • 但这是最简单的解决方案。
      • 它仍然需要使用子查询,而且你引入了一个在 OOP API 级别会跟随你的问题
      • 好吧,我显然没有包含包含指定作者的包。好吧,您的解决方案以这种方式更好,但我仍然会选择这种方法。
      【解决方案3】:

      这个答案既棘手又冗长。 我认为实体方法是可以的,通过查询项目实体你会得到你想要的。 现在对于表单,您可能需要每个子项一个 FormType,然后使用表单集合的方法 (http://symfony.com/doc/2.1/cookbook/form/form_collections.html),我确信您需要挂钩到 pre-bind 事件来准备数据。

      这是一个快速的想法,也许它可以帮助你。

      【讨论】:

      • 好的,我认为你错过了主实体中作者和项目之间的许多关系。我的意思是,您可能应该将连接放在 ITEM 中,而不是放在每个子项中
      • 如果 ItemPack 是一个项目,则包“属于”一个作者,但包内的项目属于多个作者。那个案子适合你吗?如果不是,可能是 ItemPack 不应该是 Item 的一部分
      猜你喜欢
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      • 2019-08-06
      相关资源
      最近更新 更多