使用Doctrine2 PHP在2个表之间进行双重关联

时间:2011-12-19 17:35:13

标签: php database postgresql doctrine-orm

我正在尝试使用Doctrine2(PHP)对5个对象进行关联。 我正在使用PostgreSQL。

这是数据库架构: Database schema

公司可能有许多枢纽,每个枢纽都有一个港口。 一家公司可能有很多Line,每行都有一个Linelist。 Linelist有2个Harbour。 例如,Linelist是“洛杉矶 - 西雅图”,由于Line表,多家公司可能拥有它。

我正在尝试查询一家公司的所有Hub,Harbour,Linelist和Line。 我有SQL查询:

SELECT *
FROM hub h
JOIN harbor a
ON a.id = h.harbor_id
JOIN linelist l
ON (l.harborstart_id = a.id OR l.harborend_id = a.id)
JOIN line m
ON m.linelist_id = l.id
WHERE h.company_id = 41
AND m.company_id = 41"

我正在尝试使用DQL做同样的事情。 我尝试过这个,但它不起作用:

$query = $this->getEntityManager()
->createQuery('SELECT h, a, l, m
               FROM AmGameBundle:Hub h
               JOIN h.harbor a
               JOIN a.linelist l
               JOIN l.line m
               WHERE h.company = :company_id
               AND m.company = :company_id')
->setParameter('company_id', $company_id);

因此,我只将LineList和Line对象与harborstart_id匹配,但我希望匹配harborstart_id或harborend_id。

您认为这在DQL中是否可行? 对于多对多人来说,更改港口和航线列表之间的关系可能会更好吗?

1 个答案:

答案 0 :(得分:0)

我认为这是在您的实体中定义从 harbour linelist 的2个关系的问题。我想你有类似

的东西
<?php
/**
 * @Entity
 * @Table(name="LineList")
 */
class LineList {
    /** 
     * @var object $startHarbor
     * @ManyToOne(targetEntity="Harbor", inversedBy="startHarbors")
     * @JoinColumn(name="harborstart_id", referencedColumnName="id", nullable=FALSE)
     */
    protected $startHarbor;
}

/**
 * @Entity
 * @Table(name="Harbor")
 */
class Harbor {
    /** 
     * @var object $startHarbors
     * @OneToMany(targetEntity="LineList", mappedBy="startHarbor")
     */
    protected $startHarbors;
}

这样您就可以通过 harborstart_id (您将变量命名为 linelist )将Harbors加入LineLists,但我认为现在最好更改标识符,因为会有2个引用到同一个外国表),然后如果你想 harborend_id

<?php
/**
 * @Entity
 * @Table(name="LineList")
 */
class LineList {
    /** 
     * @var object $startHarbor
     * @ManyToOne(targetEntity="Harbor", inversedBy="startHarbors")
     * @JoinColumn(name="harborstart_id", referencedColumnName="id", nullable=FALSE)
     */
    protected $startHarbor;

    /** 
     * @var object $endHarbor
     * @ManyToOne(targetEntity="Harbor", inversedBy="endHarbors")
     * @JoinColumn(name="harborend_id", referencedColumnName="id", nullable=FALSE)
     */
    protected $endHarbor;
}

/**
 * @Entity
 * @Table(name="Harbor")
 */
class Harbor {
    /** 
     * @var object $startHarbors
     * @OneToMany(targetEntity="LineList", mappedBy="startHarbor")
     */
    protected $startHarbors;

    /** 
     * @var object $endHarbors
     * @OneToMany(targetEntity="LineList", mappedBy="endHarbor")
     */
    protected $endHarbors;
}

现在您可以将DQL更改为:

$query = $this->getEntityManager()
->createQuery('SELECT h, a, sh, eh, m
               FROM AmGameBundle:Hub h
               JOIN h.harbor a
               JOIN a.startHarbors sh
               JOIN a.endHarbors eh
               JOIN l.line m
               WHERE h.company = :company_id
               AND m.company = :company_id')
->setParameter('company_id', $company_id);

这应该让你朝着正确的方向前进。如果它变得麻烦,你推测的多对多方法应该是一个记录良好的解决方案。