提交后的Symfony3丑陋URL路径(url重写或ruting)

时间:2016-05-27 19:37:56

标签: php search doctrine-orm symfony symfony-2.8

我正在使用:

  • Symfony v3.0.6;
  • Doctrine v2.5.4

我在学说查询中使用LIKE构建了网站搜索。

// My search query 
$query = $em->createQueryBuilder()
    ->select('i')
    ->from('AppBundle:Item', 'i')
    ->where('i.name_lv LIKE :term')
    ->andWhere('i.description_lv LIKE :term')
    ->setParameter('term', '%' . $term . '%')
    ->orderBy('i.price', 'DESC')
    ->getQuery();

如果我手动将请求写入浏览器地址栏,它可以正常工作。

例如:

返回包含已搜索产品的页面。

问题:

虽然我在表单中使用搜索按钮(就像每个用户一样)

// Relevant part of twig template showing my search form
<div class="search-box row clearfix text-center">
    <form id="search-form" method="GET">
        <fieldset>
            <p>{{ "goods.msg.searchSomething"|trans }}</p>
            <input type="text" class="input-term" name="term" />
            <p>{{ msg }}</p>
            <input type="submit" class="input-submit button small success" value="{{ "goods.button.search"|trans }}" />
        </fieldset>
    </form>
</div>

我遇到路径问题 - 因为

然后我会得到像这样丑陋的网址:

我怀疑,这可能是网址重写路由问题

我总是需要漂亮的网址 - 不仅在手动输入网址时,而且在使用表单搜索产品时也是如此。

以下是搜索控制器的相关代码:

// start of function: searchAction
// getting GET parameter
$term = $request->get('term');

// end of function: searchAction
// rendering template with additional parameters 
return $this->render('search/search.html.twig', array(
    'search_items' => $search_items,
    'msg' => '', 
    'term' => $term
));

这是我的路线:

goods_search_show:
    path: /{_locale}/search-show/{id}/{term}
    defaults: { _controller: 'AppBundle:Search:searchShow', id: 1, term: '' }
    requirements:
        _locale: lv|en|ru
        id: \d+

goods_search_no_term:
    path:     /{_locale}/search
    defaults: { _controller: 'AppBundle:Search:search' }
    requirements:
        _locale: lv|en|ru

goods_search:
    path:     /{_locale}/search/{term}
    defaults: { _controller: 'AppBundle:Search:search', term: '' }
    requirements:
        _locale: lv|en|ru

请指教。 感谢您的时间和知识。

更新1:

我需要传递GET参数,因为我有两个页面:[1] search和[2] searchShow(只显示一个项目的详细视图),并且在该页面上有链接返回页面[1]需要&#34;术语&#34;参数,以便显示具有相同参数的搜索

一个例子:

  • 在我按下提交按钮的搜索页面[1]上,在搜索字词中写完后,我会收到http://localhost:8000/en/search?term=productName
  • 这样的网址
  • 在包含搜索结果列表的同一页面上,有一些指向详细信息页面的链接[2]。使用path()函数

    进行链接
    <li><a class="button secondary small" href="{{ path('goods_search_show', {'id': search_item.id, 'term': term}) }}">{{ "goods.button.view"|trans }}</a></li>
    

    并生成类似http://localhost:8000/en/search-show/162/productName

  • 的网址
  • 在此页面[2]我必须创建链接回搜索页面[1],搜索参数term在搜索页面[1]的链接中传递。为此,我再次使用path()函数

    <li><a class="button secondary small" href="{{ path('goods_search', app.request.get('_route_params')|merge({'term': term})) }}">{{ "goods.button.backToList"|trans }}</a></li>
    

    并获取http://localhost:8000/en/search/productName

  • 等网址
  • 现在 - 在该链接之后,我回到搜索页面[1]并显示以前的搜索结果。

  • 然后,当尝试另一个搜索词并按下提交按钮时,我得到了网址[A]而不是[B]或[C]

    [A] http://localhost:8000/en/search/productName?term=anotherProductName 
    [B] http://localhost:8000/en/search/anotherProductName
    [C] http://localhost:8000/en/search?term=anotherProductName
    
  • 正如您从路由中看到的那样 - 路由转到goods_search。搜索是针对productName执行的,但anotherProductName完全被忽略(实际上term是网址的一部分两次)。

我觉得必须有比使用POST或在会话中传递term更好的解决方案。也许Apache服务器的.htaccess文件的一些附加参数可以解决错误的URL变得很好。

更新2:

我从 Alvin Bunk 获取建议并实施表单和更新模板以使用表单小部件而不是基本的html。

不幸的是,当我按下搜索而不是很好的URL时,我得到了这个

`http://localhost:8000/ru/search?term=productName&submit=&_token=IvGAvN-nCR40-PKm--rA92AzGXTbI94y2rDCPZxa5D0`

当我将术语更改为otherProductName时,我得到了

`http://localhost:8000/ru/search/productName?term=otherProductName&submit=&_token=IvGAvN-nCR40-PKm--rA92AzGXTbI94y2rDCPZxa5D0`

所以问题保持不变 - 意味着term是网址的两倍。

所以也许这个问题真的是路由或URL重写问题? (问题中提到了我使用的路由,并且.htaccess文件是Symfony3附带的默认文件。)

我的表格

{{ form_start(form, {'attr': {'id': 'search-form'}, 'action': path('goods_search', {'_locale': lang, 'term': term}), 'method': 'GET'}) }}
    <fieldset>
        {{ form_row(form.term, {'name': term, 'attr': {'class': 'input-term'}}) }}
        {{ form_row(form.submit, {'attr': {'class': 'input-submit small success'}}) }}
    </fieldset>
{{ form_end(form) }}

这是ItemType

<?php

namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class ItemType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('term', TextType::class, array('mapped' => false, 'label' => false))
            ->add('submit', SubmitType::class, array('label' => 'Test label for SUBMIT button'))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Item',
        ));
    }

    public function getBlockPrefix()
    {
        return null;
    }
}

这就是我在SearchController

中创建表单的方法
$item = new Item();
$form = $this->createForm(ItemType::class, $item);

return $this->render('search/search_show.html.twig', array('term' => $term, 'form' => $form->createView()));

更新3:

为我的问题找到了几个解决方法,在应用这两个网站后似乎按预期工作。

替代方法1

简单地省略表单的操作属性会使URL工作并覆盖URL中的term,而不是显示两次。

我现在的表格

{{ form_start(form, {'attr': {'id': 'search-form'}, 'method': 'GET'}) }}
    <fieldset>
        {{ form_row(form.term, {'name': term, 'attr': {'class': 'input-term'}}) }}
        {{ form_row(form.submit, {'attr': {'class': 'input-submit small success'}}) }}
    </fieldset>
{{ form_end(form) }}

替代方法2

在第二页上,链接返回搜索页面,其中包含term

等网址中的search?term=productName

因此,在第二个搜索页面模板中,我使用以下代码创建自定义丑陋网址

{% set link_back = path('goods_search') ~ '?term=' ~ term %}
<li><a href="{{ link_back }}">link back to main search page</a></li>

而不是将term与路线参数合并

{% set link_back = path('goods_search', app.request.get('_route_params')|merge({'term': term})) %}
<li><a href="{{ link_back }}">link back to main search page</a></li>

2 个答案:

答案 0 :(得分:0)

使用GET方法获得此类URL是正常的,请尝试使用POST。

但最好的方法是使用Ajax。

答案 1 :(得分:0)

您可以在树枝模板中执行以下操作:

{{ form_start(form, 
    {'action': path('/en/search-show',
        {'id':search_items.getID,
        'term':term}),
    'method': 'GET'}) }}

然后,我喜欢在我的控制器中使用注释(而不是YAML文件)并执行类似的操作来处理参数:

/**
 * @Route("/search-show/{id}/{term}",
 *  defaults={"id" = 0,"term" = 0},
 *  name="submitPetHasProgram")
 */
public function searchShowAction($id, $term, Request $request){
...

然后网址如下: http://localhost:8000/lv/search/someId/someTerm

我展示&#34; someId&#34;和&#34; someTerm&#34;,但它将是来自树枝模板传递的实际ID和术语。