Symfony以一对多的关系加入实体

时间:2015-04-19 00:42:16

标签: symfony doctrine-orm one-to-many dql

我正在研究一个Symfony项目,记录与股票相关的销售情况。

我的推理:

  • 一个销售商品与一个库存商品相关联
  • 一个库存商品可以与多个销售商品相关联

因此,我设置了一对多的销售与库存关系,如以下代码段所示:

class Sale
{

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

    /**
     * @var float
     *
     * @ORM\Column(name="cost", type="float")
     */
    private $cost;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="datetime")
     */
    private $date;

    /**
     * @ORM\ManyToOne(targetEntity="iCerge\Salesdeck\StockBundle\Entity\Stock", inversedBy="sales")
     * @ORM\JoinColumn(name="sid", referencedColumnName="id")
     */
    protected $stock;
...

......和......

class Stock
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created", type="datetime")
     */
    private $created;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="updated", type="datetime")
     */
    private $updated;

    /**
     * @ORM\OneToMany(targetEntity="iCerge\Salesdeck\SalesBundle\Entity\Sale", mappedBy="stock")
     */
    protected $sales;
...

现在,如果我实现一对多关系的代码是正确的,我正尝试使用以下代码在一个查询中加载销售对象及其关联的股票数据:

public function fetchSale($sid){
        $query = $this->createQueryBuilder('s')
            ->leftjoin('s.stock', 't')
            ->where('s.id = :sid')
            ->setParameter('sid', $sid)
            ->getQuery();
        return $query->getSingleResult();
    }

fetchSale函数来自我的项目SaleRepository.php类。 查询的 leftjoin 部分是我希望成功获取相关股票信息但我没有输出( [stock:protected] ),如下所示:< / p>

    myprog\SalesProj\SalesBundle\Entity\Sale Object
(
    [id:myprog\SalesProj\SalesBundle\Entity\Sale:private] => 50
    [cost:myprog\SalesProj\SalesBundle\Entity\Sale:private] => 4.99
    [date:myprog\SalesProj\SalesBundle\Entity\Sale:private] => DateTime Object
        (
            [date] => 2015-04-18 17:12:00
            [timezone_type] => 3
            [timezone] => UTC
        )

    [stock:protected] => 
    [count:myprog\SalesProj\SalesBundle\Entity\Sale:private] => 5
)

如何成功获取销售额&#39;相同查询中的相关股票数据?

2 个答案:

答案 0 :(得分:3)

Doctrine 默认为lazy-loading,因此$stock可能尚未初始化且转储未显示。尝试转储$sale->getStock()。这告诉 Doctrine 去取它。

您也可以通过选择加载Stock来强行加载:

public function fetchSale($sid){
    $query = $this->createQueryBuilder('s')
        ->leftjoin('s.stock', 't')
        ->where('s.id = :sid')
        ->setParameter('sid', $sid)
        ->select('s', 't')
        ->getQuery();
    return $query->getSingleResult();
}

顺便说一下,fetchSale($sid)现在与调用相同:

$entityManager->getRepository('SalesBundle:Sale')->find($sid);

答案 1 :(得分:0)

您可以使用Doctrine的急切加载功能。

<强> 1。始终加载关联对象:

如果您在加载销售对象时总是想要获取库存对象,可以通过向fetch="EAGER"定义添加@ManyToOne来更新您的实体定义(请参阅@ManyToOne的文档) :

/**
 * @ORM\ManyToOne(targetEntity="iCerge\Salesdeck\StockBundle\Entity\Stock", inversedBy="sales", fetch="EAGER")
 * @ORM\JoinColumn(name="sid", referencedColumnName="id")
 */
protected $stock;
然后,

Doctrine将负责在尽可能少的查询中加载所有必需的对象。

<强> 2。有时加载相关对象:

如果您只想在某些查询中加载关联对象,而不是默认情况下加载according to the manual,您还可以告诉Doctrine在特定查询中使用预先加载。在您的情况下,这可能看起来像:

public function fetchSale($sid){
    $query = $this->createQueryBuilder('s')
        ->where('s.id = :sid')
        ->setParameter('sid', $sid)
        ->getQuery();
    $query->setFetchMode("FQCN\Sale", "stock", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER);
    return $query->getSingleResult();
}