Symfony提交包含类别和地区的搜索表单

时间:2017-04-09 09:35:28

标签: php forms symfony

我在页面标题中有一个搜索表单,必须提交给我的SearchController,如果用户只输入查询字符串,则必须通过searchAction进行handeld。

此表格可以在选定的类别和国家/地区搜索。

search form

因此,用户可以在所有类别和所有地区进行搜索,或选择类别和所有地区或选择类别和地区

esearch form with category and region selected

我该如何处理?当我将数据放入url时,我已经完成了实际工作的控制器操作。

这是我使用QueryBuilder的搜索类:

class SearchController extends Controller
{
/**
 * @Route("cerca/{query}", name="search")
 */
public function searchAction(Request $request,$query)
{
$results = $this->getDoctrine()
           ->getRepository('AppBundle:Ads')
           ->createQueryBuilder('p')
           ->where("p.name LIKE '%$query%'")
           ->getQuery()
           ->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);

return $this->render('search\search.html.twig', [
    //'pagination'=>$pagination,
    'query' => $query,
    'region' => 'Italia',
    'results' => $results,
    ]);
}
/**
 * @Route("cerca/{region}/{query}", name="search_regioni")
 */
public function searchRegionAction($region,$query)
{
    $results = $this->getDoctrine()
           ->getRepository('AppBundle:Ads')
           ->createQueryBuilder('p')
           ->where("p.name LIKE '%$query%'")
           ->andWhere("p.region Like '%$region%'")
           ->getQuery()
           ->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);

    $region = ucfirst($region);
    return $this->render('search/search.html.twig', [
        'region' => $region,
        'query'  => $query,
    ]);
}
/**
 * @Route("cerca/{category}/{query}", name="search_categorie")
 */
public function searchCategoryAction($category,$query)
{
    $results = $this->getDoctrine()
           ->getRepository('AppBundle:Ads')
           ->createQueryBuilder('p')
           ->where("p.name LIKE '%$query%'")
           ->andWhere("p.region Like '%$region%'")
           ->getQuery()
           ->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);

    $category = ucfirst($category);
    return $this->render('search/search.html.twig', [
        'region' => 'Italia',
        'category' => $category,
        'query'  => $query,
    ]);
}
/**
 * @Route("cerca/{category}/{region}/{query}", name="search_categorie_regioni")
 */
public function searchCategoryRegionAction($category,$region,$query)
{
    $results = $this->getDoctrine()
           ->getRepository('AppBundle:Ads')
           ->createQueryBuilder('p')
           ->where("p.name LIKE '%$query%'")
           ->andWhere("p.region LIKE '%$region%'")
           ->andWhere("p.category LIKE '%$category%'")
           ->getQuery()
           ->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);

    $category = ucfirst($category);
    $region = ucfirst($region);
    return $this->render('search/search.html.twig', [
        'region' => $region,
        'category' => $category,
        'query'  => $query,
    ]);
 }
}

如何让表单提交给此控制器?如何处理不同的案件?

我认为我的逻辑也是错误的,symfony不知道我是否搜索某个类别或国家/地区,我该如何改进?

1 个答案:

答案 0 :(得分:1)

我认为您应该提交数据并将其存储在ValueObject中,而不是采取不同的操作。一个Search对象:

class Search {
    public $query;
    public $category;
    public $region;
}

您还可以创建一个SearchType,将表单绑定到值对象,并提供一些验证和约束,例如:创建一个ChoiceLoader,从数据库中加载可用的类别,并检查所选类别是否有效。提交并验证表单输入后,您将从表单中检索搜索对象,并使用它来构建您的Doctrine-Query。如果区域是空的,例如没有选择你只是从查询中省略它:

/** @var Search $search **/
$search = $form->getData();
$queryBuilder = $this->getDoctrine()
   ->getRepository('AppBundle:Ads')
   ->createQueryBuilder('p')
$queryBuilder->where($queryBuilder->expr()->like('p.name', "%{$search->query}%");
if (null != $search->region) {
    $queryBuilder->andWhere('region = :region')
        ->setParameter('region', $search->region);
}
$results = $queryBuilder->createQuery()->getResults();

有些注意事项:

  • 不要只是将变量注入where子句。这是一个安全问题。您应该使用参数和表达式构建器来防止SQL注入。
  • 您可以在查询构建器中链接子句(如上所述)或将它们拆分,就像我在if条件中一样。
  • 由于表单已连接到Search-object,因此字段应预先填入最后插入的值,因此您不必单独传递输入。
  • 我并非100%确定LIKE - 表达式将按预期工作。这可能有点棘手。您应该搜索如何正确使用它。