2016-07-07 6 views
1

В Соната у меня есть администратор бронирования.Sonata - Как создать фильтр на динамическом свойстве?

В этом Admin У меня есть какое-то поле, хранящееся в базе данных, например, «фамилия», «первое имя» или «ref». У меня также есть поле «статус», которое не хранится в БД, оно определено как это в моем Суперинте.

public function getState(){ 
     if (/*Complex condition*/) 
      return 'canceled_not_refund'; 
     else if (/*Complex condition*/) 
      return 'canceled'; 
     else if (/*Complex condition*/) 
      return "no-payment"; 
     else if (/*Complex condition*/) 
      return "partial_payment"; 
     else if (/*Complex condition*/) 
      return "ok"; 
     else if(/*Complex condition*/) 
      return "ended"; 
     } 

Я попытался определить фильтр на поле «состояние», но я получаю:

[Semantical Error] line 0, col 87 near 'state = :sta': Error: Class MyBundle\Entity\Booking has no field or association named state

Есть ли способ определить этот вид фильтра в Sonata администратора?

За помощь!

+0

Я не вижу никакого способа. Сонате пришлось бы загружать все объекты в память и фильтровать их. Все [методы фильтрации] (https://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/filter_field_definition.html#filter-field-definition) работают с QueryBuilder. – Lumen

ответ

2

Поскольку Lumen уже прокомментировал, все фильтры работают с QueryBuilder, поэтому попытка напрямую фильтровать что-то, чего нет в базе данных, не представляется возможным.

Предполагая, что complex condition вы говорите только содержат поля, которые находятся в базе данных, вы могли бы сделать что-то вроде этого:

protected function configureDatagridFilters(DatagridMapper 
$datagridMapper) 
{ 
    $datagridMapper 
     ->add('status', 'doctrine_orm_callback', array(
      'label' => 'Payment Status', 
      'callback' => function($queryBuilder, $alias, $field, $value) { 
       if ($value['value'] == 'canceled_not_refund') { 

        $queryBuilder->andWhere($alias . '.columnA = :some_value'); 
        $queryBuilder->andWhere($alias . '.columnB = :other_value'); 
        $queryBuilder->setParameter('some_value', 'some'); 
        $queryBuilder->setParameter('other_value', 'other'); 

       } elseif ($value['value'] == 'canceled') { 

        $queryBuilder->andWhere($alias . '.columnA = :some_value'); 
        $queryBuilder->andWhere($alias . '.columnB = :other_value'); 
        $queryBuilder->setParameter('some_value', 'some'); 
        $queryBuilder->setParameter('other_value', 'other'); 

       } 

      } 
      ), 'choice', array('choices' => array(
        '' => '', // Empty option to not filter anything 
        'canceled_not_refund' => 'Canceled without refund', 
        'canceled' => 'Canceled'), 
     )); 
} 

Конечно, вы можете переместить обратный вызов в отдельную функцию, чтобы сделать код немного чище.

Большой недостаток этого заключается в том, что вы получаете немного дублирования кода, поэтому, если ваша логика изменяется для определения статуса, его необходимо изменить на 2 места.

Обратите внимание, что в queryBuilder вам понадобится $alias, чтобы убедиться, что вы выбрали нужную таблицу.