web-dev-qa-db-fra.com

Comment commander par OneToMany/ManyToOne

J'ai une classe de produits contenant de nombreux champs pour ManyToMany, tels que les ingrédients, les tailles, les espèces, etc. Un total d'environ 14 champs différents Tous les champs ne sont pas pertinents pour chaque produit.

J'ai la cartographie mise en place comme ça

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;

Cela fonctionne très bien pour un manytomany/manyto one.

Le problème vient de ma table product_ingredients. J'avais besoin d'ajouter un champ supplémentaire, ce qui signifie qu'il fallait passer de ManyToMany à OneToMany/ManyToOne

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

Maintenant, mon entité ProductIngredient ressemble à ceci

 /**
     * @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;

Donc, dans ma classe de produits pour les espèces, j'utilise @ORM\OrderBy pour que les espèces soient déjà commandées. Est-il possible de le faire aussi pour mon domaine d'ingrédients? 

Ou suis-je en train de mal interpréter ma logique et que ces champs ne devraient même pas figurer dans la classe de produits et qu'ils devraient simplement être examinés par le référentiel? 

Je voulais que ce soit facile afin de pouvoir parcourir mes objets tels que $product->getIngredients() Au lieu de le faire. 

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

dans l'entité Produit, ajoutez simplement le paramètre orderBy à la relation des ingrédients

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

Eh bien, je suis venu avec une méthode de piratage .. Depuis que je me soucie vraiment de la sorte sur la sortie, j'ai fait une extension de base brindille

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

Je voudrais cependant éviter ce bidouillage et j'aimerais quand même connaître une vraie solution

6
Kris

Vous devez utiliser l'option 'query_builder' dans votre formulaire: http://symfony.com/doc/master/reference/forms/types/entity.html#query-builder .__ La valeur de l'option peut être quelque chose comme ça:

function(EntityRepository $er) {
    return $er->createQueryBuilder('i')->orderBy('i.name');
}

N'oubliez pas d'ajouter l'instruction "use" pour EntityRepository

4

Si vous utilisez le mappage XML, vous pouvez utiliser 

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

dans votre tag <one-to-many>.

0
user1077915