eZ Community » Blogs » Carlos Revillo » eZ Find with Symfony controller and...

By

eZ Find with Symfony controller and Twig templates

Wednesday 19 February 2014 2:53:43 pm

  • Currently 5 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Continuing with the migration of a site from eZ Publish 4 to eZ Publish 5, here's a sample of how you can use legacy code from a Symfony controller and use Twig templates to render the response. 

In my previous post i showed you how the migration from eZ Publish 4 to eZ Publish 5 was planned and performed for sillonbol.com site. There, i said that even the site was then totally powered by the Symfony Stack, some parts of the site still relied on the Legacy Stack.

That was the case of the search page. As search topic is not fully implemented yet in the new stack, the approach i followed for the migration was just let the legacy stack do its job. And it worked really well without the need of modify anything.

 But even if search topic is not finished yet in eZ 5, we can add a “more Symfony approach” to our search pages. The idea is simple: Create a new controller for the search page, use run legacy code possibilites to call eZ Find functions and pass the results to a Twig template. 

This way, we will still be using some legacy stuff but, well, we won’t need to work with our famous search.tpl anymore. Let’s see how this can be done. 

The Controller

I’ve added a new controller for the search page. It’s quite basic as you can see in github. It just gets the search term from the request, call the Pagerfanta stuff and finally, it passes the results to the search results template. As you may notice, I only deal with searchTerms here, but with a bit of work, we could add filters, facets and all the things eZ Find offers.
 In this controller i can also set the max results per page and the offset 

To tell eZ5 that this controller has to be executed when the content/search url is requested a modification in the routing.yml was also added.

Pagerfanta

Pagerfanta is a useful Symfony bundle that will allow to add pagination to your apps in a really easy way. By the way, this is one of the goodness i find in eZ 5. The Symfony stack will allow us to reuse code in an easier way. Well, that could be also done in eZ 5 but probably you would need to add the other project inside one of your extensions. With Symfony we will only need to add the bundle and start using it! 

Pagerfanta is one of these external bundles included with the eZ5 install. It’s also used in the DemoBundle. Reading its documentation, you will learn what is a Pagerfanta Adapter. Basically, it will be a new class that will implement the AdapterInterface interface and will have two methods. getNbResults and getSlice. As reference, you can have a look to any of the adapters provided by the bundle or also have a look at the one provided by eZ Publish Kernel.

You can pass whatever you want to the constructor of your new class. In my case, I pass the kernel, the search term got from the url and the ContentService (you’ll see why later). Here is the piece of code calling the Pagerfanta

Please note that SillonbolSearchAdapter is extending from SillonbolSearchHitAdapter. This class is where the search stuff happening. In that class is where the getNbResults and getSlice methods are. (Please don’t take phpdoc in account as it’s needs to be modified)

The getNbResults function will do a request to solr vía eZFind. There is an auxiliar doSearch function where the callback stuff happens.

As you see, once i get the eZ Find results, i set the nbResults property of the adapter to the ‘SearchCount’ value.

The getSlice function is quite similar. But in this case, I also add the sort, the offset and the limit to the searchParams array in order to get only the results needed for that page

Now a tip: Maybe you are wondering (as i did)  why set the nbResults property also in the getSlice method. Jérôme helped me with this. It’s just a way to save some requests. Depending on how you build your results template, getSlice method can be called previously to getNbResults. If this is the case, we can set that property in the getSlice method and in the getNbResults we’ll just need to return it without making another call to the Solr Server. And yes, this is the same approach used by the Adapter provided in the eZ Publish Kernel.  

Going back to SillonbolSearchAdapter, you’ll notice that it has also a getSlice method. It calls the getSlice method of its parent and it will does something else with the results… 

A new ValueObject

If you take a look to one of search results pages you will notice they are almost identical to one of our listing folders pages. The only difference is we are showing the “highlight” text in the search Pages.

 

Again thanks to the suggestions and the hints of Jérôme I created a new class extending the ValueObject class. As said in the phpdoc of that class, that is “the base class for all value objects and structs”. One of the classes extending Value object is this Content class. That class represents a content object in a specific version.

My new SillonbolContentWithHighlight objects will have a content and a string property i called “highlight”. So, what our SillonbolSearchAdapter does at the end. Is receiving the result from ez Find and build new objects compounded by a Content (thas why i need the ContentService in the constructor) and the highlight.

The template

To finish, let’s take a look to the our results template. Imho this looks cleaner than our famous search.tpl. We just ask if we have posts and if so we do a loop. If not, we show the “no results message”.

Furthermore, we ask if we really need to show the pagination number list and if so, we do it. 

In the loop we just call our controller (same we use for any other views) and pass the post.highlight as a param. The controller will take care of pass it to the template

Proudly Developed with from