首页 > 解决方案 > symfony 3.4 基于用户输入的路由注释需求

问题描述

我希望允许用户使用此 URL 执行搜索查询 mydomain.com/search/my+search

问题是我无法path()在 twig 中使用来生成表单 url 的操作,因为我无法猜测用户的搜索并且我收到了这个错误。

缺少一些强制参数(“全文”)来生成路由的 URL

我希望这条路线只有在用户尝试搜索某些东西时才可用,所以 searchquery 参数不能empty既不是null.

有没有办法使用 symfony 来实现?我确实可以使用 javascript 来动态更改表单的操作,但它不会阻止用户在mydomain.com/search/不提交表单的情况下访问。

搜索.html.twig

<form action="{{ path('search') }}" method="get">
  <input type="text" class="form-control" placeholder="search" name="searchQuery">
  <input class="btn btn-primary" type="submit" value="search" />
</form>

搜索控制器.php

/**
 * @Route("/search/{searchquery}", name="search", methods={"GET"}, requirements={
 *   "searchquery" = "([\w' \x22-\+]+)"
 * })
 */
 public function searchAction(Request $request){
  // Do stuff
 }

标签: phpsymfony

解决方案


无需猜测参数。/search您可以通过处理表单提交到基本路由来实现您想要的。我使用这两个模板创建了一个虚拟示例(索引具有搜索表单):

// index
{% block body %}
    <h1>You are on the main page</h1>
    <form action="{{ path('search') }}" method="post">
        <input type="text" class="form-control" placeholder="search" name="searchQuery">
        <input class="btn btn-primary" type="submit" value="search" />
    </form>
{% endblock %}

请注意,我已将表单方法更改为 POST 以避免将查询参数附加到带有?.

// search
{% block title %} Search {% endblock title %}
{% block body %}
    <p>You have searched for <b>{{ searchQuery }}</b></p>
{% endblock %}

控制器中的操作:

/**
 * @Route("/", name="index")
 */
public function index()
{
    return $this->render('index.html.twig');
}

/**
 * @Route(
 *     "/search/{searchQuery}",
 *     name="search",
 *     defaults={"searchQuery" = ""},
 *     requirements={"searchQuery"=".+"}
 * )
 */
public function search(string $searchQuery, Request $request)
{
    // here we handle the form submission
    if ($request->isMethod('POST')) {
        $searchQuery = $request->request->get('searchQuery');
        // checking this condition in case an empty field is submitted
        // though really the form should be validated to prevent this
        if ($searchQuery === '') {
            return $this->redirectToRoute('index');
        }
        // redirecting to the same action but with slug
        // to get an url with the desired form
        return $this->redirectToRoute(
            'search',
            ['searchQuery' => urlencode($searchQuery)]
        );
    }
    // this prevents accessing "/search/" path without a search query
    if ($searchQuery === '') {
        return $this->redirectToRoute('index');
    }
    // display search page if we actually have a search
    return $this->render(
        'search.html.twig',
        ['searchQuery' => urldecode($searchQuery)]
    );
}

这样,如果直接在 url 中输入搜索查询,它将被 slug 拾取,例如/search/military+equipment将输出:

您搜索过军事装备

提交表单时,从请求中提取参数,然后我们将用户重定向到一个形状,就好像搜索查询已作为 slug 输入一样,并且发生了同样的事情。

requirements={"searchQuery"=".+"}选项告诉 Symfony 匹配任何字符(这允许捕获路径/search/search//search/something)。由于defaults={"searchQuery" = ""},前两个将被视为 slug 是一个空字符串(因此根据我们在搜索操作中的说明重定向到主页)。

这只是一个快速而肮脏的概念证明(具有糟糕的用户体验),您可以根据自己的愿望和需求优化应用程序的流程。


推荐阅读