BooleanFilterType
CheckboxFilterType
ChoiceFilterType
CollectionAdapterFilterType
DateFilterType
DateRangeFilterType
DateTimeFilterType
DateTimeRangeFilterType
DocumentFilterType
EmbeddedFilterTypeInterface
EntityFilterType
NumberFilterType
NumberRangeFilterType
SharedableFilterType
TextFilterType
composer require lexik/form-filter-bundle
$bundles = array( ... new Lexik\Bundle\FormFilterBundle\LexikFormFilterBundle(),
lexik_form_filter: listeners: doctrine_orm: true doctrine_dbal: false doctrine_mongodb: false
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Meet * * @ORM\Table(name="meet") * @ORM\Entity(repositoryClass="AppBundle\Repository\MeetRepository") */ class Meet { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string") */ private $title; /** * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category") */ private $category; /** * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Status") */ private $status; /** * @ORM\Column(type="decimal") */ private $price = 0; /** * @ORM\Column(type="datetime") */ private $startDate; /** * @ORM\Column(type="datetime") */ private $endDate; /** * @ORM\OneToMany(targetEntity="AppBundle\Entity\Participant", mappedBy="meet") */ private $participants; /** * Get id * * @return int */ public function getId() { return $this->id; } /** * Constructor */ public function __construct() { $this->participants = new \Doctrine\Common\Collections\ArrayCollection(); } /** * Set title * * @param string $title * * @return Meet */ public function setTitle($title) { $this->title = $title; return $this; } /** * Get title * * @return string */ public function getTitle() { return $this->title; } /** * Set price * * @param string $price * * @return Meet */ public function setPrice($price) { $this->price = $price; return $this; } /** * Get price * * @return string */ public function getPrice() { return $this->price; } /** * Set startDate * * @param \DateTime $startDate * * @return Meet */ public function setStartDate($startDate) { $this->startDate = $startDate; return $this; } /** * Get startDate * * @return \DateTime */ public function getStartDate() { return $this->startDate; } /** * Set endDate * * @param \DateTime $endDate * * @return Meet */ public function setEndDate($endDate) { $this->endDate = $endDate; return $this; } /** * Get endDate * * @return \DateTime */ public function getEndDate() { return $this->endDate; } /** * Set category * * @param \AppBundle\Entity\Category $category * * @return Meet */ public function setCategory(\AppBundle\Entity\Category $category = null) { $this->category = $category; return $this; } /** * Get category * * @return \AppBundle\Entity\Category */ public function getCategory() { return $this->category; } /** * Set status * * @param \AppBundle\Entity\Status $status * * @return Meet */ public function setStatus(\AppBundle\Entity\Status $status = null) { $this->status = $status; return $this; } /** * Get status * * @return \AppBundle\Entity\Status */ public function getStatus() { return $this->status; } /** * Add participant * * @param \AppBundle\Entity\Participant $participant * * @return Meet */ public function addParticipant(\AppBundle\Entity\Participant $participant) { $this->participants[] = $participant; return $this; } /** * Remove participant * * @param \AppBundle\Entity\Participant $participant */ public function removeParticipant(\AppBundle\Entity\Participant $participant) { $this->participants->removeElement($participant); } /** * Get participants * * @return \Doctrine\Common\Collections\Collection */ public function getParticipants() { return $this->participants; } }
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Status * * @ORM\Table(name="status") * @ORM\Entity(repositoryClass="AppBundle\Repository\StatusRepository") */ class Status { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string") */ private $title; /** * Get id * * @return int */ public function getId() { return $this->id; } /** * Set title * * @param string $title * * @return Status */ public function setTitle($title) { $this->title = $title; return $this; } /** * Get title * * @return string */ public function getTitle() { return $this->title; } }
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Category * * @ORM\Table(name="category") * @ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository") */ class Category { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string") */ private $title; /** * Get id * * @return int */ public function getId() { return $this->id; } /** * Set title * * @param string $title * * @return Category */ public function setTitle($title) { $this->title = $title; return $this; } /** * Get title * * @return string */ public function getTitle() { return $this->title; } }
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * Participant * * @ORM\Table(name="participant") * @ORM\Entity(repositoryClass="AppBundle\Repository\ParticipantRepository") */ class Participant { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="participants") */ private $user; /** * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Meet", inversedBy="participants") */ private $meet; /** * Get id * * @return int */ public function getId() { return $this->id; } /** * Set user * * @param \AppBundle\Entity\User $user * * @return Participant */ public function setUser(\AppBundle\Entity\User $user = null) { $this->user = $user; return $this; } /** * Get user * * @return \AppBundle\Entity\User */ public function getUser() { return $this->user; } /** * Set meet * * @param \AppBundle\Entity\Meet $meet * * @return Participant */ public function setMeet(\AppBundle\Entity\Meet $meet = null) { $this->meet = $meet; return $this; } /** * Get meet * * @return \AppBundle\Entity\Meet */ public function getMeet() { return $this->meet; } }
namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * User * * @ORM\Table(name="user") * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") */ class User { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; }
namespace AppBundle\Filter; use Lexik\Bundle\FormFilterBundle\Filter\Query\QueryInterface; use AppBundle\Entity\Category; use AppBundle\Entity\Status; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Lexik\Bundle\FormFilterBundle\Filter\Form\Type as Filters; class MeetFilter extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setMethod('GET'); $builder ->add('category', Filters\EntityFilterType::class, [ 'data_class' => Category::class, 'class' => Category::class ]) ->add('status', Filters\EntityFilterType::class, [ 'data_class' => Status::class, 'class' => Status::class ]) ->add('startDate', Filters\DateTimeRangeFilterType::class) ->add('participant_count', Filters\NumberRangeFilterType::class, [ 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) { if (empty($values['value']['left_number'][0]) && empty($values['value']['right_number'][0])) { return null; } $start = !empty($values['value']['left_number'][0]) ? $values['value']['left_number'][0] : null; $end = !empty($values['value']['right_number'][0]) ? $values['value']['right_number'][0] : null; $paramName = sprintf('p_%s', str_replace('.', '_', $field)); $filterQuery->getQueryBuilder() ->leftJoin('meet.participants', 'pp') ->addSelect(sprintf('COUNT(pp) AS %s', $paramName)) ->addGroupBy('meet.id') ; if($start && $end) { $filterQuery->getQueryBuilder() ->having(sprintf('%s > %d AND %s < %d', $paramName, $start, $paramName, $end)); } elseif($start && !$end) { $filterQuery->getQueryBuilder() ->having(sprintf('%s > %d', $paramName, $start)); } elseif(!$start && $end) { $filterQuery->getQueryBuilder() ->having(sprintf('%s < %d', $paramName, $end)); } } ]) ->add('price', Filters\NumberRangeFilterType::class); } public function getBlockPrefix() { return 'item_filter'; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'csrf_protection' => false, 'validation_groups' => array('filtering') // avoid NotBlank() constraint-related message )); } }
$paramName = sprintf('p_%s', str_replace('.', '_', $field)); $filterQuery->getQueryBuilder() ->leftJoin('meet.participants', 'pp') ->addSelect(sprintf('COUNT(pp) AS %s', $paramName)) ->addGroupBy('meet.id') ;
if($start && $end) { $filterQuery->getQueryBuilder() ->having(sprintf('%s > %d AND %s < %d', $paramName, $start, $paramName, $end)); } elseif($start && !$end) { $filterQuery->getQueryBuilder() ->having(sprintf('%s > %d', $paramName, $start)); } elseif(!$start && $end) { $filterQuery->getQueryBuilder() ->having(sprintf('%s < %d', $paramName, $end)); }
public function indexAction(Request $request) { $repository = $this->getDoctrine() ->getRepository('AppBundle:Meet'); $form = $this->get('form.factory')->create(MeetFilter::class); if ($request->query->has($form->getName())) { $form->submit($request->query->get($form->getName())); $filterBuilder = $repository->createQueryBuilder('meet'); $this->get('lexik_form_filter.query_builder_updater')->addFilterConditions($form, $filterBuilder); $filterBuilder->join('meet.status', 's'); $query = $filterBuilder->getQuery(); $form = $this->get('form.factory')->create(MeetFilter::class); } else { $query = $repository->createQueryBuilder('meet') ->join('meet.status', 's') ->getQuery(); } $meets = $query->getResult(); }
SELECT meet, COUNT(pp) AS p_meet_participant_count FROM AppBundle\Entity\Meet meet LEFT JOIN meet.participants pp INNER JOIN meet.status s WHERE meet.category = :p_meet_category AND meet.status = :p_meet_status AND (meet.startDate <= '2017-01-31 00:00:00' AND meet.startDate >= '2017-01-01 00:00:00') AND (meet.price >= :p_meet_price_left AND meet.price <= :p_meet_price_right) GROUP BY meet.id HAVING p_meet_participant_count > 90 AND p_meet_participant_count < 256
Source: https://habr.com/ru/post/319346/
All Articles