【问题标题】:How do I search by properties of entity which do not have @Column anotation in Doctrine2?如何按 Doctrine2 中没有 @Column 注释的实体的属性进行搜索?
【发布时间】:2014-10-24 13:37:35
【问题描述】:
 /**
* @ORM\Entity
*/
class Order extends BaseEntity
{
// this is trait for @Id
use Identifier;

/**
* @ORM\Column(type="integer")
*/
protected $costPerUnit;

/**
* @ORM\Column(type="integer")
*/
protected $numberOfUnits;

// i want to search by this property
protected $totalCost;

public function getTotalCost()
{
 return $this->numberOfUnits * $this->costPerUnit;
}

}

我有一个像这样的实体,我希望能够这样做

$orderRepository->findOneByTotalCost('999')
$orderRepository->findBy(['totalCost' => '400']);

这在 Doctrine2 中可能吗?或者我会采取不同的方式吗?

【问题讨论】:

  • 您必须映射此列,否则无法映射。你是怎么做映射的?
  • @fkupper 我已经编辑了我的问题以更好地说明我要解决的问题
  • 很好,但同样没有办法在 DQL 上使用虚拟属性。至少我不知道。
  • 那我该如何解决呢?我显然不想将 $totalCost 保存在数据库中,但我希望能够通过它进行搜索。
  • 您应该创建一个对这些值求和的查询,更像是一个常见的 sql 查询。我会为此写一个答案。

标签: php orm doctrine-orm doctrine entity


【解决方案1】:

就像我在我的 cmets 中所说的那样,您很可能正在努力解决一开始就不应该发生的问题。尽管如此,使用原则将SUM 值映射到属性可能的,通过多种方式:Check the aggregate field docs 找出最能解决您的问题的方法。

在我看来,您对实体的使用比实际情况更多:实体表示数据库中的记录,Doctrine 是一个 DBAL。使用实体(或存储库)搜索数据查询数据库。您可以通过向您的实体管理器或自定义存储库类添加自定义方法来解决该问题,这些方法将查询计算所有实体的 totalCost 值所需的所有数据,并仅返回您需要的那些。或者,使用来自 DBAL 的连接来查询您所追求的 id(例如),然后使用 那些 值来获取实际实体。或者,就像我之前说的:使用聚合字段。


您展示的findOneByTotalCostfindBy 示例遇到的问题是第一个需要您自己编写一个方法调用 findOneByTotalCost。您使用findBy 的问题仅仅是您的参数格式错误:数组应该是关联的:使用映射的列名作为键,而值是您要查询的:

$repo->findBy(
    ['totalCost' => 400]
);

是您要查找的内容,而不是 ['totalCost', 400]。至于实体本身,您需要添加注释:

是的,根据您在文档块中使用@ORM\Entity 注释判断,应该这样做:

/**
 * @ORM\Column(type="string", length=255)
 */
protected $regioun = 'Spain';

更新表格,您将能够:

$entities = $repo->findBy(
    ['region' => 'Spain']
);

不要忘记,这段代码代表数据库中的一个表:您可以搜索任何字段,但使用索引,您可以通过在类定义的顶部添加注释来做到这一点:

/**
 * @ORM\Table(name="tblname", indexes={
 *  @ORM\Index(name="region", columns={"region"})
 * })
 */
class Foo
{}

一如既往:在数据库中,索引很重要

【讨论】:

  • 我特别想避免使用 Columnd 注释,因为这意味着该值是持久的。我不想保留 $totalCost,但我希望能够通过它进行搜索。
  • @user1848605:在您对此事的回答下方发表评论
【解决方案2】:

您应该在实体存储库中编写一个方法 findOneByTotalCost,类似于:

public function findOneByTotalCost ($queryParams){

    $query = 'select o
                from <yourEntity> o
               where o.numberOfUnits * o.costPerUnit = :myParam';


    $dql = $this->getEntityManager()->createQuery($query);
    $dql->setParameter('myParam', $queryParams);       

    return $dql ->execute();


}

他们,$orderRepository->findOneByTotalCost('999') 应该可以工作。

【讨论】:

  • 假设我还需要有关单个实体级别的此信息,例如 $order123->getTotalCost()。这是否意味着我必须在实体和存储库中编写相同的逻辑?这似乎不对
  • 你可以同时拥有。当您需要直接从实体获取此虚拟信息时,使用 getTotalCost() 方法,当您需要搜索时,使用存储库方法 findOneByTotalCost()
猜你喜欢
  • 2021-10-01
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 2012-09-14
  • 2015-12-15
相关资源
最近更新 更多