简体   繁体   English

Sonata - 如何在动态属性上创建过滤器?

[英]Sonata - How to create filter on dynamic property?

Into Sonata, I have a Booking Admin. 进入索纳塔,我有一个预订管理员。

In this Admin I have some field stored into database like "lastname", "firstname" or "ref". 在此Admin中,我将一些字段存储到数据库中,如“lastname”,“firstname”或“ref”。 I also have a field "status" which is non DB stored it's defined like this in my Booking Entity. 我还有一个字段“status”,它是非DB存储的,它在我的预订实体中定义如下。

    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";
      }

I tried to define a filter on "state" field but I get: 我试图在“州”字段上定义一个过滤器,但我得到:

[Semantical Error] line 0, col 87 near 'state = :sta': Error: Class MyBundle\\Entity\\Booking has no field or association named state [语义错误]第0行,第87行附近'state =:sta':错误:类MyBundle \\ Entity \\ Booking没有字段或关联名为state

Is there a way to define this kind of filter into Sonata Admin? 有没有办法在Sonata Admin中定义这种过滤器?

Thks for help! 求救!

As Lumen already commented, all the filters work with the QueryBuilder, so trying to directly filter on something that is not in the database, is not possible. 正如Lumen已经评论过的那样,所有过滤器都与QueryBuilder一起使用,因此尝试直接过滤不在数据库中的东西是不可能的。

Assuming that the complex condition you're talking about only contain fields that are in the database, you could do something like this: 假设您所讨论的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'),  
        ));
}

Of course you can move the callback to a separate function to make the code a bit cleaner. 当然,您可以将回调移动到单独的函数,以使代码更清晰。

A big disadvantage of this, is that you get a bit of code duplication, so if your logic changes for determining the status, it needs to be changed on 2 places. 这样做的一个很大的缺点是你得到了一些代码重复,所以如果你的逻辑改变以确定状态,它需要在2个地方改变。

Please note that in the queryBuilder you need the $alias to make sure you select from the right table. 请注意,在queryBuilder中,您需要$alias以确保从右表中进行选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM