2016-07-20 5 views
1

У меня есть продукт, который может иметь один или несколько тегов.Symfony: Как отсортировать ArrayCollection в соотношении OneToMany (3 объекта)?

по определенной причине, у меня есть 3 лица, которые соответствуют:

  • Product
  • Tag
  • ProductTag (отношение):

Я хочу заказать по типа мой ArrayCollection тегов. Эта коллекция содержит ProductTag объектов.

Сложность в том, что у меня нет type недвижимости в ProductType, это свойство находится в Tag entity.

Продукт

/** 
* @ORM\OneToMany(targetEntity="ProductTag", mappedBy="product", cascade={"persist", "remove"}) 
* @Assert\Valid 
*/ 
private $tags; 

Tag

/** 
* @ORM\Column(type="string", length=15) 
*/ 
private $type; 

ProductTag

/** 
* @ORM\Column(name="Product_id", type="integer") 
* @ORM\Id 
*/ 
private $product_id; 

/** 
* @ORM\Column(name="Tag_id", type="integer") 
* @ORM\Id 
*/ 
private $tag_id; 

/** 
* @ORM\ManyToOne(targetEntity="Product", inversedBy="tags") 
* @ORM\JoinColumn(name="Product_id", referencedColumnName="Product_id") 
*/ 
private $product; 

/** 
* @ORM\ManyToOne(targetEntity="Tag") 
* @ORM\JoinColumn(name="Tag_id", referencedColumnName="Tag_id") 
*/ 
private $tag; 

Решение ниже не может работать, потому чтоProductTag не имеет ни type свойства:

// Product entity 

/** 
* @ORM\OneToMany(targetEntity="ProductTag", mappedBy="product", cascade={"persist", "remove"}) 
* @ORM\OrderBy({"type" = "ASC"}) 
* @Assert\Valid 
*/ 
private $tags; 

Я хотел бы сделать что-то вроде этого @ORM\OrderBy({"tag.type" = "ASC"}).

Любая идея?

Спасибо.

--- EDIT ---

В PhpMyAdmin, я создал представление, которое получает данные тегов и идентификатор продукта для каждого тегов.

Затем, в Symfony, я создал объект, который соответствует моему представлению. В репозитории этого объекта я создал запрос, который объединяет мои теги по их типу.

public function findByProductGroupByType($productId) 
{ 
    return $this->getEntityManager() 
     ->createQuery(
      'SELECT v.tagTypeCode, v.tagType, 
       GROUP_CONCAT(v.tagCode) as tagCode, 
       GROUP_CONCAT(v.tagName) as tagName, 
       GROUP_CONCAT(v.picto) as tagPicto 
       FROM AppBundle:ProductTagView v 
       WHERE v.productId = :id 
       GROUP BY v.tagTypeCode 
       ORDER BY v.tagType ASC' 
     )->setParameter('id', $productId) 
     ->getResult(); 
} 

Так что это работает, необходимо установить this bundle так, что Symfony распознает GROUP_CONCAT.После установки, добавьте это в config.yml:

doctrine: 
    orm: 
     dql: 
      string_functions: 
       group_concat: DoctrineExtensions\Query\Mysql\GroupConcat 

Полный список здесь: https://github.com/beberlei/DoctrineExtensions/blob/master/config/mysql.yml

Запрос возвращает что-то вроде этого:

array (size=2) 
    0 => 
    array (size=5) 
     'tagTypeCode' => string 'KFEAT' (length=5) 
     'tagType' => string 'Key Feature' (length=11) 
     'tagCode' => string 'double_sanglage' (length=15) 
     'tagName' => string 'double sanglage' (length=15) 
     'tagPicto' => string 'double_sanglage.jpg' (length=19) 
    1 => 
    array (size=5) 
     'tagTypeCode' => string 'SIZE' (length=4) 
     'tagType' => string 'Size' (length=4) 
     'tagCode' => string 'h26_ceintures,h21_ceintures' (length=27) 
     'tagName => string 'ceintures h26cm,ceintures H21 cm' (length=32) 
     'tagPicto' => string 'h26_ceintures.jpg,h21_ceintures.jpg' (length=35) 

теги типа SIZE сцепляются с , сепаратором ,

+0

Добавить '' 'getTagType()' '' для вашего объекта ProductType, а затем '' '@ORM \ OrderBy ({" tagType "=" ASC "})' '' должен работать. –

ответ

0

Вы не можете сделать это напрямую. Но есть обходной путь.

  • Добавить упорядоченный теги свойство вам сущность продукта:

    private $orderedTags; 
    
    public function __construct() 
    { 
        //... 
        $this->orderedTags = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 
    
  • Создать новую доктрину Event Listener и зарегистрировать в в services.yml

    services: 
        my.listener: 
         class: AppBundle\EventListener\OrderedTagsListener 
         arguments: ["@doctrine.orm.entity_manager"] 
         tags: 
          - { name: doctrine.event_listener, event: postLoad } 
    
    
    
    // src/AppBundle/EventListener/OrderedTagsListener.php 
    namespace AppBundle\EventListener; 
    
    use Doctrine\ORM\Event\LifecycleEventArgs; 
    use AppBundle\Entity\Product; 
    
    class OrderedTagsListener 
    { 
        private $em; 
    
        public function __construct($em) 
        { 
         $this->em = $em; 
        } 
    
        public function postPersist(LifecycleEventArgs $args) 
        { 
         $product = $args->getEntity(); 
    
         // Retrieve your tags ordered with a query defined in your tags repository 
         $orderedTags = $this->em->getManager()->getRepository('AppBundle:Tags')->getOrderedTags($product); 
    
         $product->setOrderedTags(); 
        } 
    } 
    
+0

Спасибо за ваш ответ, я не тестировал его, но это кажется правильным решением. Тем временем я создал представление в PhpMyAdmin, которое получает все необходимые мне данные. Затем в Symfony я создал объект, который соответствует этому представлению, и я создал запрос в репозитории с GROUP_CONCAT, GROUP BY и ORDER BY, чтобы сортировать мои теги. Я отредактирую свое сообщение с этим решением. – Felurian

+0

ОК, не забудьте отметить ответ как «принятый», чтобы другие люди не искали решение. – Alsatian

 Смежные вопросы

  • Нет связанных вопросов^_^