Как я могу отфильтровать запрос доктрины по связанному идентификатору (Symfony 4)?

В моей сущности:

  /**
  * @ORM\ManyToMany(targetEntity="Productgroup", inversedBy="fields")
  * @ORM\JoinColumn(name="productgroup", referencedColumnName="id")
  */
  private $productgroup;

  public function getProductgroup()
  {
    return $this->productgroup;
  }

  public function setProductgroup($productgroup): self
  {
    $this->productgroup = $productgroup;

    return $this;
  }

  public function __construct()
  {
    $this->productgroup = new ArrayCollection();
  }

В моем контроллере:

$group = $this->getDoctrine()->getRepository(class::fields)->findAll();

Выход:

array:2 [▼
  0 => Fields {#120842 ▼
    -id: 3
    -name: "cat"
    -unique_id: "5a38c820ed"
    -productgroup: PersistentCollection {#120846 ▼
      -snapshot: array:1 [ …1]
      -owner: Fields {#120842}
      -association: array:20 [ …20]
      -em: EntityManager {#114768 …11}
      -backRefFieldName: "fields"
      -typeClass: ClassMetadata {#119877 …}
      -isDirty: false
      #collection: ArrayCollection {#120847 ▼
        -elements: array:1 [▼
          0 => Productgroup {#120528 ▼
            -id: 6
            -name: "Animals"
            -unique_id: "9e4ef1c46f"
            -fields: PersistentCollection {#120739 ▶}
          }
        ]
      }
      #initialized: true
    }
    -type: Type {#120923 ▶}
  }
  1 => Fields {#120924 ▼
    -id: 5
    -name: "horse"
    -unique_id: "c3890b9287"
    -productgroup: PersistentCollection {#120925 ▼
      -snapshot: []
      -owner: Fields {#120924}
      -association: array:20 [ …20]
      -em: EntityManager {#114768 …11}
      -backRefFieldName: "fields"
      -typeClass: ClassMetadata {#119877 …}
      -isDirty: false
      #collection: ArrayCollection {#120926 ▼
        -elements: []
      }
      #initialized: false
    }
    -type: Type {#120927 ▶}
  }
]

Теперь я хочу отфильтровать все $group, чтобы вывести только те поля, которые не связаны с группой товаров с идентификатором 6. Мой подход:

В моем контроллере:

$group = $this->getDoctrine()->getRepository(class:fields)->filterByColletion(6);

В моем репозитории:

 public function filterByColletion($id)
    {
      return $this->createQueryBuilder('p')
      ->addSelect('f')
      ->from('App\Entity\Fields', 'f')
      ->leftJoin('f.productgroup', 'productgroup')
      ->andWhere('f.productgroup != 6')
      ->getQuery()
      ->execute();
    }

Ошибка

Недопустимое выражение пути. Ожидается StateFieldPathExpression или SingleValuedAssociationField

В результате я ожидаю, что только группа содержит horse.


person peace_love    schedule 12.02.2019    source источник


Ответы (1)


У вас есть ->andWhere('f.productgroup != 6') в вашем запросе, но f.productgroup - это не поле простого значения, а отношение. Вам нужно применить ваше условие к полю значения, так что это будет примерно так:

->leftJoin('f.productgroup', 'pg')
->andWhere('pg.id != 6')

В этом примере я использовал pg.id, но вам нужно использовать имя поля фактического значения из Productgroup объекта, к которому вы хотите применить условие.

Примечание: лучше не вставлять значение непосредственно в запрос, а вместо этого передавать его как параметр:

->leftJoin('f.productgroup', 'pg')
->andWhere('pg.id != :id')
->setParameter(':id', 6)
person Flying    schedule 12.02.2019
comment
Спасибо, я проверил ваш код, но теперь выводится только [] Полностью пустой массив. Нет сообщения об ошибке. Но я ожидаю, что в массиве есть лошадь - person peace_love; 12.02.2019
comment
Поскольку вы работаете с Symfony, я бы порекомендовал вам включить панель инструментов разработчика (если еще нет) и взглянуть на вкладку Doctrine вашего запроса. Он содержит журнал всех запросов, сделанных во время запроса, а также фактические запросы SQL, сгенерированные Doctrine. Просмотрите фактический запрос, возможно, он даст вам подсказку, что пошло не так в вашем случае. - person Flying; 12.02.2019
comment
Я проверил. Не могу найти этот запрос в списке. Я узнал, что до сих пор я должен удалить ->addSelect('f'). И если я напишу ->andWhere('pg.id = :id'), то он покажет массив, как в моем примере выше - person peace_love; 12.02.2019
comment
Я думаю, что andWhere неправильно в этом случае. Потому что мне нужно выяснить отношение - person peace_love; 12.02.2019
comment
Если вы используете createQueryBuilder() из внутреннего репозитория, вы можете опустить пункты select() и from(), потому что они применяется автоматически в этом случае - person Flying; 12.02.2019
comment
в моей базе данных это таблица fields: i.stack.imgur.com/bWLNi.png и это таблица productgroup: i.stack.imgur.com/bRNnR.png и это fields_productgroup: i.stack.imgur.com/jLp9M.png - person peace_love; 12.02.2019
comment
Вы хотите иметь отрицательное условие для отношений N:N, это не так просто. См. эту статью и этот вопрос по SO для получения дополнительной информации - person Flying; 12.02.2019
comment
Спасибо, я дам вам знать, как только найду решение - person peace_love; 12.02.2019