Again, I believe the easiest way to explain how it works is to look at what happens from the Prestashop front-end point of view, taking an actual situation as an example. Let’s start with the screen shot of my previous article.
In the welcome page of the shop, if the customer clicks « See the whole catalog », he actually sends the following URL:
The Dispatcher gets the URL and invokes the CategoryController who in turn takes care of building the page shown in the screen cap above.
CategoryController calls the hooks attached to positions he’s responsible for. In this case, the hooks I’ve attached to displayNavFullWidth and to displayTop: pd_tsearchbar and pd_tcnav, respectively. When there is no tractor filter active, these modules don’t perform anything specific. Pd_tcnav works as the ps_categorytreeview, from which it’s derived.
Now, let’s have a look at what happens if the user has selected a tractor. He could have typed in a model number in the search box (2c). For example « 6320 » which is id_tractor=159 in the database. The URL will become:
This time, the CategoryController, will know that the customer wants to filter the catalog. It will create an instance of the class « tractor » and store it as one of its property, along with an instance of the class « category » (id_category=1001). But wait! Now Prestashop CategoryController knows about tractors? Yes, because I’ve created an override of the native Prestashop CategoryController. Very basic override: I’ve just overridden two methods: init() and getBreadcrumbLinks() and added one property, tractor.
- Init(): if there parameter &id_tractor= is present in the URL, it creates an instance of the class tractor (Pd_TcNavTractor), stores id_tractor in the cookie for later use, then calls parent::init() method so that the normal processing of Prestashop happens.
- getBreadcrumbLinks(): because the user could click on the breadcrumb to navigate, I needed to add the &id_tractor= parameter to each underlying URL so that it’s passed back to the controller.
Now, there are three important implication of having a tractor object property in my current instance of CategoryController:
- During it’s processing, CategoryController will call the function hooked to displayLeft position (my pd_tcnav module) and displayNavFullWidth (pd_tsearchbar module). Thus, when pd_tcnav->hookDisplayLeft() is called, I check if the controller calling the function has a function named getTractor(). If the calling controller is CategoryController, because I’ve overridden it, it has this function. I call it and see if it returns a tractor object. Yes: then I know that there is a filter by tractor. I can retrieve and display the category tree view accordingly.
- When pd_tsearchbar->hookDisplayFullNavWidth() is called, I can do the same and, if needed, display the tractor model (area 2b on the screen shot).
- My pd_tcnav module provides a ProductSearchProvider. When a hook is registered to this non-displayable hook, the controller will call the function hookProductSearchProvider() when it needs to retrieve product from the database… allowing me to filter the product displayed in area 7 (see screen shot).
We’re almost done. Assume the customer now clicks on a product miniature (one of the box in area 7), then the URL could be:
And… we’ve lost the tractor filter! I need to keep the id_tractor so that when control returns to the CategoryController, this one knows that a tractor filter was active. Otherwize, he will consider that there is no filter and display the whole catalog, which the user doesn’t expect.
Thus, our link must become
To achieve this, I need to override the ProductController as well. Again, I’ve simply overridden the init() method to check if a id_tractor= parameter is in the URL. If yes, I store the id_tractor in a property. I’ve added a public getid_tractord() method. I’ve also altered the getBreadcrumbLinks() method to add the &id_tractor= parameter to the URL.
Here is a UML sequence diagram showing the overall mechanism of the CategoryController in the Prestashop front-end (not exhaustive, but shows enough to understand how it works):