【问题标题】:How to OrderBy on OneToMany/ManyToOne如何在 OneToMany/ManyToOne 上订购
【发布时间】:2012-09-18 14:01:17
【问题描述】:

我有一个 Product 类,上面有很多字段用于 ManyToMany,例如成分、尺寸、物种等。总共大约 14 个不同的字段 并非所有字段都与每个产品相关。

我有这样的映射设置

Class product {
/**
 * @var Species[]
 * @ORM\ManyToMany(targetEntity="Species")
 * @ORM\JoinTable(name="product_species",
 *      joinColumns={@ORM\JoinColumn(name="productId", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="speciesId", referencedColumnName="id")}
 *      )
 * @ORM\OrderBy({"name" = "asc"})
 */
private $species;

这非常适合多对多/多对一。

问题出在我的 product_ingredients 表中,我需要添加一个附加字段,这意味着需要从 ManyToMany 切换到 OneToMany/ManyToOne 就这样

/**
     * @var ProductIngredient[]
     *
     * @ORM\OneToMany(targetEntity="ProductIngredient", mappedBy="product")
     * @ORM\JoinColumn(name="productId", referencedColumnName="id")
     */
    private $ingredients;

现在我的 ProductIngredient 实体看起来像这样

 /**
     * @var IngredientType
     * @ORM\ManyToOne(targetEntity="IngredientType", fetch="EAGER")
     * @ORM\JoinColumn(name="ingredientTypeId", referencedColumnName="id")
     */
    private $ingredientType;


    /**
     * @var Ingredient
     *
     * @ORM\ManyToOne(targetEntity="Ingredient", inversedBy="products", fetch="EAGER")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="ingredientId", referencedColumnName="id")
     * })
     */
    private $ingredient;

    /**
     * @var Product
     *
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="ingredients")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="productId", referencedColumnName="id")
     * })
     */
    private $product;

所以在我的物种产品类中,我使用@ORM\OrderBy 以便物种已经被订购.. 有没有办法我也可以在我的成分字段中做到这一点?

或者我做错了我的逻辑,这些甚至不应该是产品类上的字段,而应该只是在存储库中查找?

我希望它变得简单,这样我就可以遍历我的对象,例如 $product->getIngredients() 而不是做

$ingredients = $this->getDoctrine()->getRepository('ProductIngredient')->findByProduct($product->getId());

【问题讨论】:

    标签: symfony doctrine-orm


    【解决方案1】:

    在 Product 实体中,只需将 orderBy 添加到成分关系中

    /**
     * ...
     * @ORM\OrderBy({"some_attribute" = "ASC", "another_attribute" = "DESC"})
     */
    private $ingredients;
    

    【讨论】:

    • 这会引发错误(无法识别的字段:名称),因为“名称”在 ProductIngredient 中不存在它在成分实体中。
    • 你能举个例子吗?我的产品实体连接到 ProductIngredient,后者连接到成分。我尝试在 productioningredient 类中进行 orderby,但由于它是多方的,因此被忽略
    • 您可能还需要在执行此操作后清除缓存。我遇到了这个问题,直到刷新缓存后它才真正应用订单:php console.php orm:clear-cache:metadata && php console.php orm:clear-cache:query && php console.php orm:clear-cache:result
    • 因为这里的名字很有意义(ingredientType vs ingredient_type),我认为重新排列你的 sn-p 以符合 OP 的 sn-p 可能会有所帮助
    • 有没有办法按连接列排序?例如,如果您有一个 Car 的集合 - 每辆车都与一个 Model 相关。是否可以使用注解按model.name 订购?
    【解决方案2】:

    好吧,我想出了一个 hackish 方法。因为我真的只关心输出的排序,所以我做了一个基本的 twig 扩展

    use Doctrine\Common\Collections\Collection;
    
    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;
    }
    

    我想避免这种黑客攻击,但仍然想知道一个真正的解决方案

    【讨论】:

    • 喜欢它,这样的东西非常方便,以防你想随机订购不同的时间
    【解决方案3】:

    您应该在表单中使用“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 添加“使用”语句

    【讨论】:

    • @ORM\OrderBy 对我不起作用,因为我的关系是 ManyToOne 这就是我需要的!而且我还可以添加我的WHERE 子句!!!谢谢
    【解决方案4】:

    如果你使用xml映射,你可以使用

            <order-by>
                <order-by-field name="some_field" direction="ASC" />
            </order-by>
    

    在您的 &lt;one-to-many&gt; 标签内。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 2011-07-30
      • 2016-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多