Итак фильтруемый entity выглядит примерно так:
class TransPeregruz { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var transformator * * @ORM\ManyToOne(targetEntity="transformator", inversedBy="peregruzs") * @ORM\JoinColumns({ * @ORM\JoinColumn(name="transformator_id", referencedColumnName="id", onDelete="SET NULL", nullable=true) * }) */ private $transformator; .................................................... /** * @var \DateTime * * @ORM\Column(name="PikDt", type="datetime") */ private $pikDt; .................................................... }
В нем нас будут интересовать свойства transformator(трансформатор) и pikDt(дата пикового значение нагрузки). Форму фильтр для этого дела, правильней было бы сделать отдельным файлом в папочке Form моего бандла, но я, как человек иногда ленивый, делаю ее прямо в контроллере фильтруемой сущности "на лету". Выношу создание формы в функцию CreateFilterForm, также привожу вашему вниманию код
class TransPeregruzController extends Controller { private function CreateFilterForm($po, $dt_from = NULL, $dt_to = NULL) { if (!isset($dt_from) || !isset($dt_to)) { $dt1 = new \DateTime(); $dt1->sub(new \DateInterval('P1D')); $dt2 = new \DateTime(); $dt_to = $dt2; $dt_from = $dt1; } $data = array('PO' => $po,'date_from' => $dt_from,'date_to' => $dt_to); $pos = $this->getDoctrine()->getManager()->getRepository('BpBundle:Po')->findAll(); $poChoices = array(); foreach ($pos as $po_obj) { $key = $po_obj->getId(); $value = $po_obj->getShortName(); $poChoices[$key] = $value; } $fb = $this->createFormBuilder($data, array('csrf_protection' => false)); $formFilter = $fb ->add('PO','choice', array( 'label' => 'ПО', 'choices' => $poChoices, 'empty_value' => 'Все ПО', 'required' => false, 'attr' => array('class' => 'input-small')) ) ->add('date_from','datetime',array('label' => 'Период начиная с:', 'widget' => 'single_text', 'format' => 'dd.MM.yyyy HH:mm', 'attr' => array('class' => 'input-medium dtp'))) ->add('date_to','datetime',array('label' => 'до:', 'widget' => 'single_text', 'format' => 'dd.MM.yyyy HH:mm', 'attr' => array('class' => 'input-medium dtp'))) ->getForm(); return $formFilter; } ............................................... public function indexAction() { $session = $this->getRequest()->getSession(); $po = $session->get('PO'); $dt1 = new \DateTime(); $dt1->sub(new \DateInterval('P1D')); $dt2 = new \DateTime(); $dt_to = $session->get('date_to',$dt2); $dt_from = $session->get('date_from',$dt1); $em = $this->getDoctrine()->getManager(); $repository = $em->getRepository('BpBundle:TransPeregruz'); $queryBuilder = $repository->createQueryBuilder('p') ->leftJoin('p.transformator', 'ts') ->leftJoin('ts.podst', 'ps') ->leftJoin('ps.groupPodst', 'gps') ->leftJoin('gps.po', 'po') ->where('p.pikDt>=:dtfrom AND p.pikDt<=:dtto') ->orderBy('p.pikDt','DESC') ->setParameter('dtfrom', $dt_from) ->setParameter('dtto', $dt_to); if (isset($po)) $queryBuilder->andWhere('po.id = :po') ->setParameter('po', $po); $entities = $queryBuilder->getQuery()->getResult(); $formFilter = $this->CreateFilterForm($po, $dt_from, $dt_to); return array( 'entities' => $entities, 'form' => $formFilter->createView(), ); } public function filterAction(Request $request) { $session = $request->getSession(); $po = $session->get('PO'); $formFilter = $this->CreateFilterForm($po, $dt_from, $dt_to); $formFilter->handleRequest($request); if ($formFilter->isValid()) { $data = $formFilter->getData(); if (isset($data['PO'])) $session->set('PO', $data['PO']); else { $session->remove('PO'); } $session->set('date_from', $data['date_from']); $session->set('date_to', $data['date_to']); return $this->redirect($this->generateUrl('peregruz')); } return $this->render('BpBundle:TransPeregruz:filter.html.twig', array( 'form' => $formFilter->createView(), )); } ..............................................................................................
Давайте проясним сразу некоторые моменты. Не буду разбирать построчно, думаю вы способны на это сами, отделаюсь общими словами. По умолчанию date_to и date_from устанавливаются в текущую дату минус сутки, то есть если пользователь еще ничего не выбрал мы ему подставляем в фильтр период за последние 24 часа. спасибо DateTime классу, который позволяет это легко сделать. Другой виджет фильтра заполняем сущностями из таблицы ПО. После того как пользователь определил свой выбор данных для виджетов фильтра, сохраняем их в сессии, чтобы при регенерации страницы была возможность их снова показать.
Роуты (..\Resources\config\routing.yml):
.............. peregruz: pattern: /peregruz defaults: { _controller: BpBundle:TransPeregruz:index } methods: [GET|POST] peregruz_filter: pattern: /peregruz_filter defaults: { _controller: BpBundle:TransPeregruz:filter } requirements: _method: POST ..............
Twig-шаблон filter.html.twig:
{% block body -%} <form action="" method="post"> {{ form_errors(form) }} <div class="control-group"> {{ form_label(form.PO) }} {{ form_errors(form.PO) }} {{ form_widget(form.PO) }} </div> <div class="control-group"> {{ form_label(form.date_from) }} {{ form_errors(form.date_from) }} {{ form_widget(form.date_from) }} </div> <div class="control-group"> {{ form_label(form.date_to) }} {{ form_errors(form.date_to) }} {{ form_widget(form.date_to) }} </div> <p> <br> <button class="btn btn-primary" type="submit">Фильтровать</button> </p> </form> {% endblock %}
Twig-шаблон index.html.twig (частично):
......................... {% block sidebar %} <div class="container-fluid"> <div btn-group-vertical"> <a href="http://demiware.ru/{{ path('bp_mod_zt') }}" class="btn btn-info"> <i class="icon-home"></i> Модуль загрузки трансформаторов </a> </div> <ul class="nav nav-pills nav-stacked"> <li> <a href="http://demiware.ru/{{ path('prognoz') }}">Отчет по превышению прогнозов загрузки без ТУ</a> <li class="active"> <a href="http://demiware.ru/{{ path('peregruz') }}">Отчет по превышению загрузки трансформаторов</a> </li> </ul> <hr> <div id="filter"> <form action="{{ path('peregruz_filter') }}" method="post" {{ form_enctype(form) }} class="form-horizontal"> {% include 'BpBundle:TransPeregruz:filter.html.twig' with { 'form': form } %} </form> </div> </div> {% endblock %} ......................... {% block javascripts %} <script type="text/javascript"> $( '.dtp' ).datetimepicker({showButtonPanel: true}); </script> {% endblock %}
Обратим внимание, что для виджетов dat_to и date_from при создании формы в контроллере, я задал класс dtp, а здесь мы на него навешиваем красивый JQuery контрол DateTimePicker.