简体   繁体   中英

doctrine2 queryBuilder must return only result matching with array values (ids): 0/Null and/or One and/or Many id(s) have to return One result

I have an array of collection named $configurations . This array matches of my Entity Configuration.php connected to Product.php as a ManyToMany . Now I have another entity named WorkType.php which is connected too to Configuration.php by a ManyToMany .

The goal is to recover the product who has O/Null or Many configurations for the current work type.

By default I have a product without configurations, but user could choose by checkboxes a O/Null or One or Many configurations available for a work type.

So I created this queryBuilder in my ProductRepository.php :

public function getProductByManyConfig($slug, $configurations)
  {

    $queryBuilder = $this->getEntityManager()->createQueryBuilder();

    $queryBuilder->select('p')
                 ->from('MyBundle', 'p')
                 ->join('p.workType', 'wt', 'WITH', 'wt.id = p.workType')
                 ->leftJoin('p.configurations','c');

    $queryBuilder->add('where', $queryBuilder->expr()->in('c', ':c'))
                 ->andWhere('wt.slug = :slug')
                 ->setParameters(array('slug'=> $slug, 'c'=> $configurations));

    return $queryBuilder->getQuery()
                        ->getResult();
  }

It works, but the proble is that it returns me all product matching with the array of configurations I pass to the query.

For example if the array have the id 1 and 2 of Configuration.php , the query returns me the products matching with configuration.id = 1 , configuration.id = 2 and configuration.id =1 and 2 .

So I have 3 conditions to achieve, I need only one; eg only the product which containing all the configuration.id !

I only need to return the only one product containing the ids of Configuration.php passed into the array for the current WorkType.php !

This is my controller code:

$vars = array(); //containing all values I need for recover configurations properties

$em = $this->getDoctrine()->getManager();

$var = array_values($vars);

$configurations = $this->getDoctrine()->getRepository('MyBundle:Configuration')->findByName($var);

foreach ($configurations as $conf) {
  $name = $conf->getName();
}

$slug = "the_right_database_correspondence";

$arrayProbuctConfig = $this->getDoctrine()->getRepository('MyBundle:Product')->getProductByManyConfig($slug, $configurations);

// return of the view

As the choice of configurations could change, I need to create this dynamic method. How can I return the good result ?

I had the same problem with Doctrine2 recently and I came with that answer.

If you want all Product entities that are linked with all the configurations, you need to add a where condition for every configuration.

Considering your $configurations variable is an array of Configuration entities

$queryBuilder->select('p')
             ->from('MyBundle', 'p')
             ->join('p.workType', 'wt', 'WITH', 'wt.id = p.workType')
             ->leftJoin('p.configurations','c');

$queryBuilder->where('wt.slug = :slug')->setParameter('slug', $slug);

$nbConfs = count($configurations);
  for($i = 0; $i < count($configurations); $i++){
      $queryBuilder->andWhere(":conf{$i} MEMBER OF p.configurations")->setParameter("conf{$i}", $configurations[$i]);
  }

$queryBuilder
      ->having('COUNT(c.id) =:some_count')
      ->setParameter('some_count', $nbConfs);

I had to use a for loop to create different tokens (the string preceded by : ), otherwise Doctrine doesn't add them to its internal collection of parameters.

Edit : Query modified to consider the case where you pass no configurations and want to get Product s that has no relations to Configuration s.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM