【问题标题】:Symfony submit a search form with categories and regionSymfony 提交包含类别和区域的搜索表单
【发布时间】:2017-04-09 09:35:28
【问题描述】:

我在页面标题中有一个搜索表单,如果用户只输入查询字符串,它必须提交给我的 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不知道我搜索的是category还是country region,我该如何改进呢?

【问题讨论】:

    标签: php forms symfony


    【解决方案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 条件中所做的那样。
    • 由于表单已连接到搜索对象,因此应使用最后插入的值预先填充字段,因此您不必单独传递输入。
    • 我不能 100% 确定 LIKE-表达式会按预期工作。这可能有点棘手。您应该搜索如何正确使用它。

    【讨论】:

    • 感谢您的回复,您能说得更具体点吗?我必须把这段代码放在哪里?我是 symfony 的新手。
    • 我没有使用 FormBuilder,因为表单不在单个页面上,而是在我嵌入树枝的标题中,我应该切换到 FB 并创建另一个控制器以包含在页面中吗?有可能做到这一点吗?以及如何?
    • 最佳实践建议创建 FormType-classes,然后在 Controller 中使用 $this->createForm()(当它扩展 BaseController 时)。我可能会同意。即使它是一个标题,你也可以有一个特定的控制器+动作,请参阅嵌入控制器:symfony.com/doc/current/templating/embedding_controllers.html
    猜你喜欢
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 2018-10-03
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多