Into Sonata, I have a Booking Admin.
In this Admin I have some field stored into database like "lastname", "firstname" or "ref". I also have a field "status" which is non DB stored it's defined like this in my Booking Entity.
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
Is there a way to define this kind of filter into 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.
Assuming that the complex condition
you're talking about only contain fields that are in the database, you could do something like this:
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.
Please note that in the queryBuilder you need the $alias
to make sure you select from the right table.