Как сделать заказ на OneToMany/ManyToOne

У меня есть класс 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());

Ответ 1

в объекте Product просто адад orderBy для отношения ингредиентов

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

Ответ 2

Ну, я придумал хакерский способ. Поскольку я действительно забочусь только о сортировке на выходе, я сделал базовое расширение ветки

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');
}

Не забудьте добавить инструкцию "use" для EntityRepository

Ответ 4

Как мне было дано задание по аналогичному вопросу, вы должны написать запрос на соединение, чтобы порядок ORM работал, см. здесь для справки. http://www.krueckeberg.org/notes/d2.html

Я, однако, решил проблему с I-образным плагином сортировки на стороне клиента, jquery datatable и tinysort оба отличные: -)