2016-07-23 60 views
2

我对来自Kohana背景的Symfony非常陌生,我有一段时间习惯了Doctrine。Doctrine的createQueryBuilder绕过Entities getter方法吗?

目前我有一个产品表,我内心使用createQueryBuilder连接其他一些表,并且需要在产品实体的getter方法中添加一些额外的逻辑。但是,似乎getter方法甚至没有被使用。下面是我的一些代码片段:

//From AppBundle\Controller\ProductController 

$repository = $this->getDoctrine()->getRepository('AppBundle:Product'); 
$products = $repository->findWithLimitNew(24); 

//From AppBundle\Repositories\ProductRepository 
public function findWithLimitNew($limit=1) 
{ 
    $em = $this->getEntityManager(); 
    $qb = $em->createQueryBuilder(); 
    $qb->select('p.name', 'p.id', 'p.slug', 'pc.name AS catname') 
     ->from('AppBundle\Entity\Product', 'p') 
     ->innerJoin(
      'AppBundle\Entity\ProductAttributes', 
      'pa', 
      \Doctrine\ORM\Query\Expr\Join::WITH, 
      'p.id = pa.productId' 
     ) 
     ->innerJoin(
      'AppBundle\Entity\ProductCategories', 
      'pc', 
      \Doctrine\ORM\Query\Expr\Join::WITH, 
      'pa.value = pc.id' 
     ) 
     ->where('pa.type = 1') 
     ->where('pa.default = 1') 
     ->setMaxResults($limit); 

    return $qb->getQuery()->getResult(); 
} 

// From AppBundle\Entity\Product 
/** 
* Get name 
* 
* @return string 
*/ 
public function getName() 
{ 
    #return $this->name; //<--Commenting this out for now 
    return 'Some stupid string'; 
} 

// From index.twig.html 
{% for product in products %} 
<h1>{{product.name}}</h1> 
{% endfor %} 

现在你可以看到我有吸气getName()方法返回一个字符串,但在视图渲染我得到的产品名称,而不是我的字符串返回。是什么赋予了?

+1

正如你怀疑的那样,当水合一个实体(即从数据库检索)时,Doctrine 2使用反射来直接设置实体属性。所有方法(包括构造函数)都被忽略。而DQL不是SQL。我很惊讶你的查询返回任何东西。 – Cerad

+0

@Cerad我的查询来自一个Doctrine网站,查询工作正常。当然,我修改了我的表名。 – pogeybait

+0

AppBundle \ Entity \ Product中的标签为pubic的是“名称”字段吗?如果是这种情况,可能是因为树枝认为该属性是公共的,并且不会打扰调用吸气剂。尽量让它变得私密并且让吸气者公开 – valepu

回答

0

@Cerad有一个观点。乍一看,你的查询看起来像DQL而不是QB。但是现在我知道你的代码是正确的,可以简化您的QueryBuilder(QB)代码相当多:

$qb->select('p') 
    ->from('AppBundle:Product', 'p') 
    ->innerJoin(
     'AppBundle:ProductAttributes', 
     'pa', 
     'WITH', 
     'p.id = pa.productId' 
) 
    ->innerJoin(
     'AppBundle:ProductCategories', 
     'pc', 
     'WITH', 
     'pa.value = pc.id' 
) 
    ->where('pa.type = 1') 
    ->andWhere('pa.default = 1') 
    ->setMaxResults($limit); 

注意我用的是“andWhere”,但你原来有一个额外的“在那里”。我感到惊讶的作品,并没有抛出和错误。

此外,我认为主要的问题是,你只需要了解返回的结果。然后在你的树枝中,你不会调用属性,而是调用如下的吸气剂:

// From index.twig.html 
{% for product in products %} 
    <h1>{{ product.getName }}</h1> 
{% endfor %} 

你可以尝试这些改变吗?我认为在树枝模板中调用getter是个问题。

这可能行不通。让我们知道如果它不。

+0

如果关系全部被映射,那么innerJoin('p.attributes','pa')就是所需要的。无需拼出含有东西,也不需要指定产品属性类。 – Cerad

+0

我明白你在说什么@Cerad和我完全同意你的评论(因此也是upvote)。这个操作对Symfony来说是新的,我只是假设他的查询按照它的方式工作。只试图帮助解决这个问题。一旦他熟悉“更简单”的方法,他可以改变他的设计。 –

+0

@AlvinBunk当我尝试更改{{product.getName}},甚至将圆括号添加到函数时,我得到了可怕的数组来转换字符串错误。根据我的理解,product.name实际上应该是调用getter getName(),但在Cerad所说的这种查询类型的情况下,它直接将结果水化为数组而不使用getter。 – pogeybait