I have a list of items to display on a page, with a search form above it to filter these items, like in any usual backend. The problem is that I don't know how to add the search criteria to an existing query with joins... Here's what I have:
I use a specific method on the repository associated to the entity to add joins on the query (in order to avoid many queries). The controller looks like this:
class ModelController extends Controller
{
public function indexAction(Request $request)
{
// ...
$em = $this->getDoctrine()->getManager();
$query = $em->getRepository('AcmeDemoBundle:Item')->getList();
}
}
The getList
method on the repository looks like this:
use Doctrine\ORM\EntityRepository;
// ...
class ItemRepository extends EntityRepository
{
public function getList()
{
$queryBuilder = $this
->createQueryBuilder('i')
->innerJoin('i.brand', 'b');
return $queryBuilder->getQuery();
}
}
I created a ItemSearchType
form object with several fields to search for items.
How can I easily add the search criteria from the data provided in the search form to display the filtered items?
This is what's in my controller concerning the search form:
class ModelController extends Controller
{
public function indexAction(Request $request)
{
// ...
if ($request->getMethod() === 'POST') {
$searchForm->bindRequest($request);
if ($searchForm->isValid()) {
$searchCriteria = $searchForm->getData();
// Do something with this data! ...but I don't know how
}
}
}
Thanks!
Here's what i would try:
public function getListBy($criteria)
{
$qb = $this->createQueryBuilder('i');
$qb->innerJoin('i.brand', 'b');
foreach ($criteria as $field => $value) {
if (!$this->getClassMetadata()->hasField($field)) {
// Make sure we only use existing fields (avoid any injection)
continue;
}
$qb ->andWhere($qb->expr()->eq('i.'.$field, ':i_'.$field))
->setParameter('i_'.$field, $value);
}
return $qb->getQuery()->getResult();
}
Here I posted an answer for this, I use LexikFormFilterBundle filterTypes and QueryBuilder, plus a TypeGuesser I made that abstracts the filterForm creation process.
you can install both services as separate Bundles with Composer. The resulting code is cleaner
From the README, in case you don't want to navigate to github :P
/**
* Creates a Filter form to search for Entities.
*
* @param AbstractType|string $formType The `generate:doctrine:form` generated Type or its FQCN.
*
* @return \Symfony\Component\Form\Form The filter Form
*/
private function createFilterForm($formType)
{
$adapter = $this->get('dd_form.form_adapter');
$form = $adapter->adaptForm(
$formType,
$this->generateUrl('document_search'),
array('fieldToRemove1', 'fieldToRemove2')
);
return $form;
}
It's broken for SF >= 2.8 Need a fix here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With