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

Php Symfony提交包含类别和地区的搜索表单,php,forms,symfony,Php,Forms,Symfony,我在页面的标题中得到了一个搜索表单,它必须提交给我的SearchController,并由searchAction处理,以防用户只输入查询字符串 此表单可以在选定的类别和国家/地区中进行搜索 因此,用户可以在所有类别和所有区域中进行搜索,或者选择类别和所有区域,或者选择类别和区域 我该怎么办?当我把数据放在url中时,我已经做了一个实际工作的控制器动作 以下是我使用QueryBuilder的搜索类: class SearchController extends Controller { /**

我在页面的标题中得到了一个搜索表单,它必须提交给我的SearchController,并由searchAction处理,以防用户只输入查询字符串

此表单可以在选定的类别和国家/地区中进行搜索

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

我该怎么办?当我把数据放在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不知道如果我搜索一个类别或国家/地区,我该如何改进这一点?

我认为与其采取不同的行动,不如提交数据并将其存储在ValueObject中,例如搜索对象:

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

/** @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条件中一样将它们拆分。 由于表单已连接到搜索对象,因此字段应预先填充最后插入的值,因此不必单独传递输入。 我不能100%确定LIKE表达式是否会像预期的那样工作。这可能有点棘手。你应该寻找如何正确使用它。
谢谢你的回复,你能更具体一点吗?我必须把代码放在哪里?我是symfony的新手。我没有使用FormBuilder,因为表单不在单个页面上,而是在我嵌入到twig中的标题中,我是否应该切换到FB,或者创建另一个要包含在页面中的控制器?有可能做到这一点吗?如何创建呢?最佳实践建议创建FormType类,然后在扩展BaseController时使用控制器中的$this->createForm。我可能会同意。即使它是一个标题,您也可以有一个特定的控制器+操作,请参阅嵌入控制器:
/** @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();