Сегодня 13 мая, понедельник ГлавнаяНовостиО проектеЛичный кабинетПомощьКонтакты Сделать стартовойКарта сайтаНаписать администрации
Поиск по сайту
 
Ваше мнение
Какой рейтинг вас больше интересует?
 
 
 
 
 
Проголосовало: 7273
Кнопка
BlogRider.ru - Каталог блогов Рунета
получить код
Dmitriy
Dmitriy
Голосов: 0
Адрес блога: http://demiware.ru
Добавлен: 2014-01-14 07:07:16
 

Форма-фильтр на фронте в Symfony2

2014-01-10 04:00:00 (читать в оригинале)

Форма-фильтр на фронте в Symfony2

В предыдущей версии Symfony 1.4 фрэймворк для нас любезно генерил форм-фильтры. В Symfony 2.*, увы, такой халявы не стало. Конечно можно использовать какие-нибудь сторонние бандлы, но этот путь, лично для меня не показался достаточно простым и прозрачным. Ну чтож, будем сами решать данную проблему. Не все так страшно как оказалось.

Фильтр нам надо сделать чтобы данные из таблицы фильтровались по полю с датой - по периоду от начальной даты до конечной и еще по одному полю типа Entity. В моем случае таблица представляет из себя загрузки трансформаторов подстанций, там есть поле с датой и соответственно будем фильтровать по производственному объединению(ПО), которые имеют свои подстанции с этими трансформаторами.

 

Итак фильтруемый 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.


Тэги: symfony2, сайтостроение

 


Самый-самый блог
Блогер ЖЖ все стерпит
ЖЖ все стерпит
по количеству голосов (152) в категории «Истории»


Загрузка...Загрузка...
BlogRider.ru не имеет отношения к публикуемым в записях блогов материалам. Все записи
взяты из открытых общедоступных источников и являются собственностью их авторов.