skip to Main Content

Ok, this is the problem:

I have a search form where I have several input fields to specify a search request. I use Symfony2 forms to benefit from validation, CSRF-protection and all the good jazz.

Now, I want the URLs of the search results to be both SEO friendly and bookmarkable.
e.g.

http://www.example.com/blue-car-in-Berlin-200km/

My current approach after doing some research is building the desired search slug and redirecting to another action like so:

//some form code
if($searchForm->isValid()){
   $searchWidget = $searchForm->getData();

   if(!empty($searchWidget->getSearch())) 
       $slug = $searchWidget->getSearch();
   if(!empty($searchWidget->getPlace())) 
       $slug .= '-in-' . $searchWidget->getPlace()->getName());
   if(!empty($searchWidget->getDistance())) 
       $slug .= '-' . $searchWidget->getDistance().'km';

   return $this->redirectToRoute('app_search', array('search'=>$slug));
}

With the second controller which is basically supposed to look like this:

public function searchAction(Request $request, $search)
{
    //extract actual terms out of the $search - slug
    ....
    //find a way to inject the terms in the current request-Object (dirty)
    ...
    //do all validation again
}

As already stated in the code this feels really inefficient and cumbersome. Isn’t there a better way to do all this? Like having a URL representation which is independent of the actual logic?

Furthermore, is there even a clean solution to use all the benefits of symfony form without actual request parameters but with that request slug?.

Thanks

2

Answers


  1. I think you need SEO bundle for this.

    Login or Signup to reply.
  2. You could define the route for the search action like that (I’m using annotations here):

    /**
     * @Route("/search/{search}-in-{place}-{distance}km", name="app_search")
     * @Method({"GET"})
     */
    public function searchAction(Request $request, $search, $place, $distance)
    {
        // Your code here
    }
    

    Of course this is valid if those three search parameters are the only one needed and only if they are all three mandatory; if the search parameters are not mandatory, you have to define more routes to match all the possible combinations (and I think this is not the right way).

    A simpler solution is maybe to create a dynamic slug (it can have one or more values) with some sort of fixed formatting from which you can easily extract all the desired search values. But at this point I would like to ask: why don’t you use some simple GET parameters (something like /search?search=blue+car&place=berlin&distance=200)?

    Update

    Expanding the idea of a flexible search string, you could try something like that:

    /**
     * @Route("/search/{searchString}", name="app_search")
     * @Method({"GET"})
     */
    public function searchAction(Request $request, $searchString)
    {
        // Your code here
    }
    

    searchString can be something like that (“<…>” is a placeholder for the real data like “city-berlin”):

    city-<...>/distance-<...>/place-<...>
    

    You just have to explode by ‘/’ and then, for each piece, explode by ‘-‘ and use the first piece as ID for what to search. The first explode should return something like that:

    [
        'city-<...>',
        'distance-<...>',
        'place-<...>'
    ]
    

    The second explode on each of those elements should return

    [ 'city', '<...>' ]
    

    This method is the most flexible because the order of the search parameters doesn’t matter and no parameters is mandatory for the analysis.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search