我正在做一个Symfony项目,记录与股票有关的销售。
我的理由:
- 一个
- 销售项目与一个库存项目相关联
- 一个库存物料可以关联到多个销售物料
因此,我设置了一对多的销售与库存关系,如以下代码片段所示:
class Sale
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var float
*
* @ORMColumn(name="cost", type="float")
*/
private $cost;
/**
* @var DateTime
*
* @ORMColumn(name="date", type="datetime")
*/
private $date;
/**
* @ORMManyToOne(targetEntity="iCergeSalesdeckStockBundleEntityStock", inversedBy="sales")
* @ORMJoinColumn(name="sid", referencedColumnName="id")
*/
protected $stock;
...
。和。。。
class Stock
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="name", type="string", length=255)
*/
private $name;
/**
* @var DateTime
*
* @ORMColumn(name="created", type="datetime")
*/
private $created;
/**
* @var DateTime
*
* @ORMColumn(name="updated", type="datetime")
*/
private $updated;
/**
* @ORMOneToMany(targetEntity="iCergeSalesdeckSalesBundleEntitySale", 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]),如下所示:
myprogSalesProjSalesBundleEntitySale Object
(
[id:myprogSalesProjSalesBundleEntitySale:private] => 50
[cost:myprogSalesProjSalesBundleEntitySale:private] => 4.99
[date:myprogSalesProjSalesBundleEntitySale:private] => DateTime Object
(
[date] => 2015-04-18 17:12:00
[timezone_type] => 3
[timezone] => UTC
)
[stock:protected] =>
[count:myprogSalesProjSalesBundleEntitySale:private] => 5
)
如何在同一查询中成功获取销售的相关库存数据?
Doctrine 默认是延迟加载的,因此$stock
可能尚未初始化并且转储未显示它。尝试倾倒$sale->getStock()
。这告诉教义去取它。
您还可以通过选择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);
您可以使用 Doctrine 的急切加载功能。
1. 始终加载关联的对象:
如果您始终希望在加载 sale 对象时获取库存对象,您可以通过向@ManyToOne
定义添加fetch="EAGER"
来更新实体定义(请参阅@ManyToOne文档):
/**
* @ORMManyToOne(targetEntity="iCergeSalesdeckStockBundleEntityStock", inversedBy="sales", fetch="EAGER")
* @ORMJoinColumn(name="sid", referencedColumnName="id")
*/
protected $stock;
然后,Doctrine 将负责在尽可能少的查询中加载所有必需的对象。
2. 有时加载关联的对象:
如果您只想在某些查询中加载关联的对象,而不是默认加载,根据手册,您还可以告诉 Doctrine 对特定查询使用预先加载。在您的情况下,这可能如下所示:
public function fetchSale($sid){
$query = $this->createQueryBuilder('s')
->where('s.id = :sid')
->setParameter('sid', $sid)
->getQuery();
$query->setFetchMode("FQCNSale", "stock", DoctrineORMMappingClassMetadata::FETCH_EAGER);
return $query->getSingleResult();
}