Question

I am trying to implement a search module with clean URLs. Something like www.website.com/search/searchterm. I have made a searchable index with EWZSearchBundle, so there is no database involved and therefore, no entity required.

public function searchAction(Request $request)
{
    $form = $this->createFormBuilder()
        ->add('query', 'text')
        ->getForm();

    if('POST' === $request->getMethod()){
        $form->bind($request);
        if ($form->isValid()) {
            return $this->redirect($this->generateUrl('search_process', array('query' => $request->query->get('query'))));
        }

    }

    return array(
        'form'   => $form->createView(),
    );
}

I created a simple form without an entity and sent the form action to itself. Where it reads a if it a POST request I validate the form and send it to search process with a clean URL (www.website.com/search/searchterm).

public function searchProcessAction($query)
{
    $search = $this->get('ewz_search.lucene');
    $results = $search->find($query);

    return array(
        'results'   => $results,
    );
}

In the search process I get the search term from the clean URL and search for it in my index and return the results. It should be a very simple process only one problem.

Since I don't need to use an Entity, it never becomes a POST request and never gets inside the if('POST' === $request->getMethod()), and now that it becomes a GET request, it also spoils my whole thing about keeping the URL clean.

I know my way makes and extra redirect, but I don't know how else to keep a clean URL for search. I'm open to any suggestions about the whole process.

Était-ce utile?

La solution 3

I managed to get it working without using the form component. I made the form manually, also accepted the query string format suggested by @moonwave99. Using the form component gives longer names like form[query] and form[_token] where it sends that form's CSRF token in the URL. Making the form manually allows better control on URL for query string format.

Note: Beware that at the same time, it removes CSRF security from that particular form.

Thanks for all the answers.

Autres conseils

Some thoughts:

  • by a rule of thumb, a search action should be performed via GET method: you aren't creating anything, you are just querying your site for some results;

  • though clean URLs are nice and all, search functions should still take advantage of good ol' query syntax [http://path.to/search?q=termToSearchFor]; this way query string never gets cached, and you are sure to always fetch updated content [without needing do specify cache behaviour server side];

  • if your concern is to protect your data from certain traffic, consider implementing either authentication or a CSRF token in the form.

  • regarding this:

Since I don't need to use an Entity, it never becomes a POST request and never gets inside the if('POST' === $request->getMethod()), and now that it becomes a GET request, it also spoils my whole thing about keeping the URL clean.

This is just plain wrong: a POST request has nothing to do with Entities, it's just a mode you specify in request headers, in order to ask the server for a specific behaviour.

Your url will still be "clean" if you define it as /search/{query}, and update you action as follows:

public function searchAction($query){ ... }

But as I said before, query syntax is perfectly fine for search behaviour, and POST should not be used for such task.

A smart reading about RESTful principles - http://tomayko.com/writings/rest-to-my-wife .

You have to submit your form with POST method.

in HTML

<form action="YOUR ACTION" method ="post">

if you want to be sure that no one will come on this link in some other way (GET), then modify routing

rule_name:
  pattern: /search/{query}
  defaults: { _controller: AcmeBundle:Search:search }
  requirements:
    _method:  POST
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top