我有一个产品类,上面有很多 ManyToMany的字段,例如成分、大小、物种等。总共约14个不同的领域并非所有字段都与每个产品相关。
我有这样的映射设置
Class product {
/**
* @var Species[]
* @ORMManyToMany(targetEntity="Species")
* @ORMJoinTable(name="product_species",
* joinColumns={@ORMJoinColumn(name="productId", referencedColumnName="id")},
* inverseJoinColumns={@ORMJoinColumn(name="speciesId", referencedColumnName="id")}
* )
* @ORMOrderBy({"name" = "asc"})
*/
private $species;
这适用于多对多/多对一。
问题出在我的product_ingredients表中,我需要添加一个额外的字段,这意味着需要从多对多切换到一对多/多对多所以像这样
/**
* @var ProductIngredient[]
*
* @ORMOneToMany(targetEntity="ProductIngredient", mappedBy="product")
* @ORMJoinColumn(name="productId", referencedColumnName="id")
*/
private $ingredients;
现在我的产品成分实体看起来像这样
/**
* @var IngredientType
* @ORMManyToOne(targetEntity="IngredientType", fetch="EAGER")
* @ORMJoinColumn(name="ingredientTypeId", referencedColumnName="id")
*/
private $ingredientType;
/**
* @var Ingredient
*
* @ORMManyToOne(targetEntity="Ingredient", inversedBy="products", fetch="EAGER")
* @ORMJoinColumns({
* @ORMJoinColumn(name="ingredientId", referencedColumnName="id")
* })
*/
private $ingredient;
/**
* @var Product
*
* @ORMManyToOne(targetEntity="Product", inversedBy="ingredients")
* @ORMJoinColumns({
* @ORMJoinColumn(name="productId", referencedColumnName="id")
* })
*/
private $product;
因此,在我的物种产品类中,我使用@ORM\OrderBy,以便物种已经订购。有没有办法让我也能为我的配料领域做到这一点?
还是我的逻辑做错了,这些甚至不应该是产品类上的字段,而应该只是由存储库查找?
我希望它很容易,这样我就可以像$product->getIngredients()
一样遍历我的对象而不是做
$ingredients = $this->getDoctrine()->getRepository('ProductIngredient')->findByProduct($product->getId());
在产品实体中,您只需要将 orderBy 添加到成分关系中
/**
* @ORMOrderBy({"some_attribute" => "ASC", "another_attribute" => "DESC"})
*/
private $ingredients;
使用 PHP 8 属性:
#[ORMOrderBy(['some_attribute' => 'ASC', 'another_attribute' => 'DESC'])]
private $ingredients;
好吧,我想出了一个黑客方法。由于我真的只关心输出的排序,所以我做了一个基本的树枝扩展
use DoctrineCommonCollectionsCollection;
public function sort(Collection $objects, $name, $property = null)
{
$values = $objects->getValues();
usort($values, function ($a, $b) use ($name, $property) {
$name = 'get' . $name;
if ($property) {
$property = 'get' . $property;
return strcasecmp($a->$name()->$property(), $b->$name()->$property());
} else {
return strcasecmp($a->$name(), $b->$name());
}
});
return $values;
}
我想避免这个黑客,但仍然想知道一个真正的解决方案
在表单中使用"query_builder"选项:http://symfony.com/doc/master/reference/forms/types/entity.html#query-builder该选项的值可以是这样的:
function(EntityRepository $er) {
return $er->createQueryBuilder('i')->orderBy('i.name');
}
不要忘记为 EntityRepository 添加"use"语句
如果使用 xml 映射,则可以使用
<order-by>
<order-by-field name="some_field" direction="ASC" />
</order-by>
在您的<one-to-many>
标签内。