【问题标题】:Doctrine query one entity in one-to-many unidirectional with join tableDoctrine 使用连接表以一对多单向方式查询一个实体
【发布时间】:2017-08-07 17:03:50
【问题描述】:

我有两个实体通过一对多单向连接表关联。

use Doctrine\ORM\Mapping as ORM;

/**
 * @Entity(repositoryClass="FooRepository")
 */
class Foo
{
    /**
     * @var Collection
     * @ORM\ManyToMany(targetEntity="Bar")
     * @ORM\JoinTable(
     *      name="foo_bar",
     *      inverseJoinColumns={@ORM\JoinColumn(unique=true)}
     * )
     */
    private $bars;

    /**
     * @var int
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // [...]
}
/**
 * @Entity(repositoryClass="BarRepository")
 */
class Bar
{
    /**
     * @var int
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // [...]
}

我想在我的 BarRepository 类中创建一个方法,使用 foo id 和 bar id 返回一个或 null Bar 对象。

其实我的课是这样的:

use Doctrine\ORM\EntityRepository;

class BarRepository extends EntityRepository
{
    /**
     * Finds a single bar.
     * @param int $fooId The foo identifier.
     * @param int $barId The bar identifier.
     * @return Bar|null
     */
    public function findOneByFoo($fooId, $barId)
    {
        $qb = $this->createQueryBuilder('b');
        $qb->innerJoin('Foo', 'f', Expr\Join::WITH, 'f.id = :fooId')
        ->where('b.id = :barId')
        ->setParameter('fooId', $fooId)
        ->setParameter('barId', $barId)
        ->getQuery()->getOneOrNullResult();
    }
}

但这总是返回一个 bar 对象,即使 bar id 没有关联到 foo 对象。

【问题讨论】:

    标签: php symfony doctrine-orm


    【解决方案1】:

    好的,感谢 staskrak,我像这样重写了我的“查询”,它工作正常。 FooBar 实体是相同的。 我保留了相同的查询基础,但在Foo->bars 属性和Bar 实体之间添加了一个内部连接。

    use Doctrine\ORM\EntityRepository;
    
    class BarRepository extends EntityRepository
    {
        public function findOneByFoo($fooId, $barId)
        {
            $parameters = [
                ':fooId' => $fooId,
                ':barId' => $barId
            ];
            $qb = $this->createQueryBuilder('b');
            return $qb
                ->innerJoin('Foo',    'f',  'WITH', 'f.id = :fooId')
                // below, the added inner join
                // it makes the link between the Foo->bars property and the Bar entity
                ->innerJoin('f.bars', 'fb', 'WITH', 'b.id = fb.id')
                ->where('b.id = :barId')
                ->setParameters($parameters)
                ->getQuery()
                ->getOneOrNullResult();
        }
    }
    

    【讨论】:

      【解决方案2】:
      1. 首先!这不是必需的,但我建议你总是写 注释中的完整映射。

        让我们看看你的实体。我们可以对你的下一个断言 一对多:

        一个 Foo 对象可以有多个 Bar 对象,但每个 Bar 对象都引用 只有一个,没有更多的 Foo 对象。 例如一个人可以有很多信用卡,但每一张信用卡 卡属于一个人。

      因此我们可以写下:

      /**
       * @Entity(repositoryClass="FooRepository")
       */
      class Foo
      {
           /**
            * Unidirectional One-To-Many
            * One Foo has many Bar, however Bar has only one Foo
            * 
            * @ORM\ManyToMany(targetEntity="Bar")
            * @ORM\JoinTable(
            *      name="foo_bar_table",
            *      joinColumns={@JoinColumn(name="foo_id", referencedColumnName="id")},
            *      inverseJoinColumns={@JoinColumn(name="bar_id", referencedColumnName="id", unique=true)
            */
            private $bars;
      
           /**
            * Foo constructor
            */
            public function __construct()
            {
               $this->bars = new \Doctrine\Common\Collections\ArrayCollection();
            }
      
      1. 当然,您总是会有一个带有您输入的 id 的 bar 对象。 为什么?让我们看看你的关系(表)。 Foo - 这是一个具有字段 id 的表。
        Bar - 这是一个具有字段 id 的表。 foo_bar_table - 这个表有 foo_id, bar_id。

        当您进行连接时 - 您只需将另一个表添加到一个表中。 这些表之间没有关联。所以你想要 Bar 对象 - 你明白了。
        您需要从 Bar 存储库中获取 Bar 对象。这将是 更好。

      【讨论】:

      • 谢谢你。但是使用 BarRepository 获取 Bar 对象不是更合乎逻辑吗?
      • 当然你是对的钙。这只是一个错字。我们需要从 BarRepository 中获取 Bar 对象。我已经更正了我的帖子。也谢谢你。
      猜你喜欢
      • 2016-04-10
      • 2013-01-20
      • 1970-01-01
      • 1970-01-01
      • 2016-07-02
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 2017-06-30
      相关资源
      最近更新 更多