質問

I'm building a website which needs the ability to filter villa's based on their options. So for example: A villa has the options: Wi-Fi, Pool, Animals allowed.

When filtering I'm giving the options: Wi-Fi and Pool. I now need a filtered list of villa's based on BOTH these options. So I only want the villa's that have both Wi-Fi AND a Pool.

My Villa Entity looks like this:

class Object
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

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

/**
 * @ORM\manyToMany(targetEntity="Option", mappedBy="objects")
 */
private $options;

//...
}

And my Option Entity looks like this:

class Option
{

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=255)
 */
private $tag;

/**
 * @ORM\manyToMany(targetEntity="Object", inversedBy="options")
 * @ORM\JoinTable(name="Object_Options")
 */
private $objects;

//...
}

I have an array of filter ids $filters with which I need to filter.

I just can't seem to figure out how to accomplish this.

I now have this

$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select("o")->from("Object", "o");

if ($filters && count($filters) > 0) {
    $qb->innerJoin("o.options", "f");
    $qb->andWhere($qb->expr()->in("f.id", $filters));
}

$query = $qb->getQuery();

but this actually does the opposite of what I need. This filters villa's based on the options but uses OR instead of AND. So this gives me results for where a Villa has Wi-Fi OR a Pool.

So in pseudo code I need:

get all Objects that have every given option (and maybe more)

Can any one shed some light on this?

役に立ちましたか?

解決

SOLVED:

Allright, so I figured it out. I was on the right track with my IN statement, but it needed a bit more salt. Apparently after you have selected all the options, you need to check if the amount of filters is the same as the amount of filters you've given. Which actually made sense when i tried this step by step in MySQL.

$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select("DISTINCT o")->from("Object", "o");

if ($filters && count($filters) > 0) {
    $qb->innerJoin("o.options",
                   "f", 
                   "WITH", 
                   "f.id IN (:filters)")->setParameter("filters", $filters);

    $qb->groupBy("o.id");

    $qb->having("COUNT(DISTINCT f.id) = :count")
       ->setParameter("count", count($filters));
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top