Jump to content

[HOWTO] How to override controllers in PrestaShop v1.4


rocky
 Share

Recommended Posts

I just figured out how to override a controller in PrestaShop v1.4, so I thought I'd let everyone know how I did it, since there is no documentation on it yet. I wanted to modify category.php and add a new hook I could use in product-list.tpl. In PrestaShop v1.3.2, I had to actually modify category.php and be careful to add those changes again every time I upgraded PrestaShop. Now, in PrestaShop v1.4, I simply created the file override/controllers/CategoryController.php with the following code:

 

<?php

class CategoryController extends CategoryControllerCore
{
   public function process()
   {
       parent::process();

       self::$smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));
   }
}

?>

 

After adding the category hook to the database, I can now use {$HOOK_CATEGORY} in product-list.tpl and I don't to have to worry about accidentally overwriting the change the next time I upgrade PrestaShop!

  • Like 4

Share this post


Link to post
Share on other sites

  • 2 weeks later...
  • 2 months later...

Hello,

Thanks Rocky for this howTo. Very usefull.
I can now understand the use of this new feature.

Could you give an example for classes ?

i.e. : let's say I want to include a "require_once" virtually on top of /classes/Tools.php. What I want is Presta to understand that it should require a specific file before loading the rest of Tools.php.

Is it possible ? How ?

Thank you in advance ! As I didn't see any documentation for the new features yet, it's not easy to start the upgrade work from 1.3 to the 1.4 to come.

Share this post


Link to post
Share on other sites

Try creating override/classes/Tools.php with the following:

require_once('yourfile.php');

class Tools extends ToolsCore
{

}



Ooops...

I just found out that this change gives me a full white page when I call a page in BO.

I have deleted everything in "yourfile.php". I just left a dummy code like this :
<?
// 123
?>



Same thing (white page in BO).

Then I tried to the same in the Tools.php I have now in override/classes.
Same thing.

Does it do the same with you ?

Share this post


Link to post
Share on other sites

Why are you including the yourfile.php? Is it to declare other classes or to declare functions, variables, constants etc.?

The problem is that if you declare anything in your external php file that might conflict with the Prestshop namespace, then you may well get an error. I had a similar problem when working with including the Wordpress core - it worked in the front office fine, but caused errors in the back office because there were name conflicts between Prestashop global functions and Wordress functions i.e. the second attempt at declaring the same function fails with an error.

Ah just re-read your message and noticed you'd deleted the contents of yourfile.php, so it isn't a conflict then.....

I've overridden several classes and haven't experienced this though..... strange. I suggest turning on error logging to find out what's going on. You can enable it in .htaccess usually and set a file location for the error_log.

Can I ask why you;re trying to override the Tools class anyway? Most methods are declared static in that class and inheritance won't apply anyway. You may be better just to extend Prestashop itself with a new "core" class.

MyTools.php in /classes

class MyToolsCore
{

 public static function myutility($param)
 {
      // Clever code in here
 }

}



You should then be able to use it via:

MyTools::myutility('foo');



Paul

Share this post


Link to post
Share on other sites

yes, it's to include home made functions.

Untill now (before v1.4), I used to group all my personnal functions in a file (easier to find back and edit if a change is needed), and declare it at the begining of Tools.php with a require_once.

Maybe this is not the best way to do now... With the overrides, we'll have to change some of our habits.
In fact, while I'm writing this message, I feel a bite stupid because I just realise I should just put my stuff in the

class Tools extends ToolsCore
{
my functions
}


instead of doing the way I'm used to.

I just tested, and it works. It's cleaner and simpler than the way I did untill now.

And now, guess what... i've got my BO back. I really don't know how.

I'm looking forward an official tutorial on how to exactly use overrides, because I'm a bite confused with this concept. I'm really not a good programmer, so it's getting harder and harder to mod my shop as Presta core is more and more complex.

Anyway, thank you for your answer, Paul !!

Share this post


Link to post
Share on other sites

I just figured out how to override a controller in PrestaShop v1.4, so I thought I'd let everyone know how I did it, since there is no documentation on it yet. I wanted to modify category.php and add a new hook I could use in product-list.tpl. In PrestaShop v1.3.2, I had to actually modify category.php and be careful to add those changes again every time I upgraded PrestaShop. Now, in PrestaShop v1.4, I simply created the file override/controllers/CategoryController.php with the following code:

<?php

class CategoryController extends CategoryControllerCore
{
   public function process()
   {
       parent::process();

       $this->smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));
   }
}

?>



After adding the category hook to the database, I can now use {$HOOK_CATEGORY} in product-list.tpl and I don't to have to worry about accidentally overwriting the change the next time I upgrade PrestaShop!



Hello to you all

New to prestashop and php... C# is the language i use primary, but you never get to old to learn.

I´m developing two modules for verion 1.4 and i would like to use the possibility to use the override. So let see if i got it.

If i would like to create a new payment module and i need to override the validateorder in paymentmodulecore.

1. Create my new override class in override/classes and let it extend PaymentModuleCore
2. Add my version of the validateOrder as a function. (Do i need to override as in C# or. Can´t find any good text on override, any one that know abot one?)
3. Create my module and use the function in myclass instead of creating a function in the module/mypaymod.php
4. There is a hook that i can use to present my payment module as in version 1.3. But should i do it in some other way in 1.4?
5. How do i move the file to override/classes direcotry? Does Prestashop do that when installing the module some how or do i have to setup that for my self in the code?

Any comments?!?

If i am going to make changes in the AdminOrders Tab... Same way or? Is there any developer guide any where?!

Share this post


Link to post
Share on other sites

There's no need to use the new 1.4 overrides for payment modules; they are a kind of special case.

A payment module is just a specific type of "module" - you can get a primer on writing a basic Prestashop module and skeleton module code from my site by following my How to write a Prestashop module articles.

Payment modules are slightly different and come in two flavours:
1. Synchronous - All control at every step is on your site e.g. cheque payment, bankwire etc.
2. Asynchronous - You implement some form of callback to receive payment status updates e.g. PayPal

I would suggest that you look at writing a basic "Hello World" module to get the hang of the Prestashop conventions, then extend the PaymentModule class instead of the Module class in your module later to start work on your creation. It may be useful to dissect the existing modules that are provided with the core to see how the flow works.

Modifying the admin area is different again. I would always strongly advise looking into the Prestashop "hook" system to see if you can extend things via a module that way rather than changing the core code (something you really need to avoid at all costs). In the case of the admin tab it calls the hooks "adminOrder" and "invoice" passing the order_id in both cases to give you a chance to do some additional output or processing.

Good Luck!

Paul

Share this post


Link to post
Share on other sites

Hello Paul

I have followed your guide and i have also created a version of my payment module and it works. So i will leave it as it is for version 1.4. The Plugin for version 1.4, is that one only for situations when there is no hook. Or do i gain any thing if i always use it?

Roger

Share this post


Link to post
Share on other sites

Roger,

It's work in progress and I'll be updating it shortly - several problems when it came to "real world" use!! Nothing that can't be easily solved though ;)

It's a way of easily adding the output from a single module, avoiding the need to mess about with the Prestashop core adding a custom hook. It also has the advantage that the module doesn't need to care where the output is (left, right, header, top etc.); if you have an encrypted paid module that you can't adapt for another hook, then this will be a solution. I'm using it for other little things now too with some success (e.g. using CMS pages as editable blocks in the theme), looking good so far and shouldn;t have much if any performance impact (may even be less overhead calling it this way in many cases).

I'll update the site when I've done more research.

Paul

Share this post


Link to post
Share on other sites

Hi all from France,

It seems there is the right place to post...
I'd really like to master overrides even before 1.4 is in final state.
(many modules done for customers to port and new ones to code)

From what i see told by rocky , this works and really looks clear and easy to understand :

<?php

class CategoryController extends CategoryControllerCore
{
   public function process()
   {
       parent::process();

       $this->smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));
   }
}

?>



So i did think it would be the very same for any method of any controller or class

Unfortunately, this is what i tried and just doesn't work :

file /overrides/classes/_Cart.php

<?php
class Cart extends CartCore
{
   function getOrderShippingCost($id_carrier = NULL, $useTax = true)
   {
          my own stuff here
   }
}
?>



Any changes in getOrderShippingCost doesn't change anything in FO

Do you have a clue why it fails ? isn't this feature done in order to be able to override "f" function of "c" class ?

Last question was already asked by adata :

5. How do i move the file to override/classes direcotry? Does Prestashop do that when installing the module some how or do i have to setup that for my self in the code?


I think this is a very good question : is there any auto mechanism in install process wich copies needed files in right places, maybe in modules's xml install files, as in joomla, for example ?

Thanx.
Regards

Share this post


Link to post
Share on other sites

Well i just found what i was doing wrong.
The override just works nicely ! Great feature !
Thx Paul for your answer cause you confirmed me i was doing it properly, so i found the error ... in the overrided function itself (yeah i'm a stupid guy too).

Edit : for those who would like to now, or would have temporarily joined the "Stupid guys Club" , i just had forgotten to replace one of

 $this->a_function()

calls by

parent::a_function()

Share this post


Link to post
Share on other sites

Last question was already asked by adata :

5. How do i move the file to override/classes direcotry? Does Prestashop do that when installing the module some how or do i have to setup that for my self in the code?
I think this is a very good question : is there any auto mechanism in install process wich copies needed files in right places, maybe in modules’s xml install files, as in joomla, for example
?


Well i can now answer this one myself.
As far as i could dig into 1.4 core, i could not find any kind of such mechanism.
Developpers will have to copie the files themselves (same for css modules overrides), unless this feature is added before final release or planned to be added.
This his somehow a bit annoying, because prestashop 1.4 installation , as far as i know, doesn't check the overrride directories 'writability'
It would have benn very nice to be able to specify files to copy in each dir , in config.xml
Maybe a feature to ask for to the team ?

Share this post


Link to post
Share on other sites

  • 1 month later...

Yes, you can override admin tabs, but not from the overrides directory. You must override them using a module. For example, my AJAX Sliding Categories module overrides the product editor to load only the top level of categories, then loads the remaining ones using AJAX when required, which speeds up the loading when there are many categories. To do this, I copied admin/tabs/AdminProducts.php to modules/blockcategoriesnc/AdminProducts.php (and AdminCatalog.php and AdminCategories.php in my case), then modified the file as needed. I then tell PrestaShop to use this tab instead of the default one by going to Employees > Tabs, editing the Catalog tab, then entering "blockcategoriesnc" in the "Module" field. Actually, I do this automatically using an SQL query, but you don't need to do that unless you are releasing a module.

Share this post


Link to post
Share on other sites



It would have benn very nice to be able to specify files to copy in each dir , in config.xml
Maybe a feature to ask for to the team ?


I really agree, but... what if more than one module need to override the same classe ?
For example, 2 modules need to override the Product.php. How do you manage this ? The second module should not overwrite the changes made by the first one.

Then you will say : yes, but if Product.php alreaddy exists in /override/classes, the second module will just have to automatically edit this file, and add the modified function of the Product class it needs to change.

Ok, but what if 2 modules need to edit the same function of the same class ??

You see ? This problem will be a bite tricky to solve.


Does anyone know if there’s a way to do this with admin classes ?

I would like to do the same with admin tab classes to override some Prestashop functionality.

Thanks.


As far as I know, admin classes cannot be overcharged. At least, I didn't find a way to do this yet.
If somebody has a solution to do that, please share ! ;)


EDIT : ouch ! 6 minutes faster, Rocky ! :vampire:

Share this post


Link to post
Share on other sites

Yes, you can override admin tabs, but not from the overrides directory. You must override them using a module. For example, my AJAX Sliding Categories module overrides the product editor to load only the top level of categories, then loads the remaining ones using AJAX when required, which speeds up the loading when there are many categories. To do this, I copied admin/tabs/AdminProducts.php to modules/blockcategoriesnc/AdminProducts.php (and AdminCatalog.php and AdminCategories.php in my case), then modified the file as needed. I then tell PrestaShop to use this tab instead of the default one by going to Employees > Tabs, editing the Catalog tab, then entering "blockcategoriesnc" in the "Module" field. Actually, I do this automatically using an SQL query, but you don't need to do that unless you are releasing a module.

Thank you very much, Rocky !!!!

I was looking for a way to do this.
Ready to try it this afternoon.

Thanks again!!!

Share this post


Link to post
Share on other sites

I really agree, but… what if more than one module need to override the same classe ?
For example, 2 modules need to override the Product.php. How do you manage this ? The second module should not overwrite the changes made by the first one.

Then you will say : yes, but if Product.php alreaddy exists in /override/classes, the second module will just have to automatically edit this file, and add the modified function of the Product class it needs to change.

Ok, but what if 2 modules need to edit the same function of the same class ??

You see ? This problem will be a bite tricky to solve.


I fully agree: as soon as more than one override is needed , that leads to an issue.
That's why i do think that an 'override install tools' would be nice.
The installer would first check if an override already exists. In case it does , then return an error/warning like
"Override class already exists. You can't install this module, except if you uninstall xxx module."
As in my mind , the installer could keep the override's owner for each class in a dedicated table , as it does for modules...

Share this post


Link to post
Share on other sites

Yes, you can override admin tabs, but not from the overrides directory. You must override them using a module. For example, my AJAX Sliding Categories module overrides the product editor to load only the top level of categories, then loads the remaining ones using AJAX when required, which speeds up the loading when there are many categories. To do this, I copied admin/tabs/AdminProducts.php to modules/blockcategoriesnc/AdminProducts.php (and AdminCatalog.php and AdminCategories.php in my case), then modified the file as needed. I then tell PrestaShop to use this tab instead of the default one by going to Employees > Tabs, editing the Catalog tab, then entering "blockcategoriesnc" in the "Module" field. Actually, I do this automatically using an SQL query, but you don't need to do that unless you are releasing a module.


BRAVO !

I would never have found this just by myself !
Very interesting method.
My fingers are already warming and get ready to do some tests !

Thanks for having shared that !

By the way, rocky, your Product Attribute module works like a charm.
I hope it will be 1.4 compatible soon. Clearly, you have the skills to do that ! ;-P

Share this post


Link to post
Share on other sites



I fully agree: as soon as more than one override is needed , that leads to an issue.
That's why i do think that an 'override install tools' would be nice.
The installer would first check if an override already exists. In case it does , then return an error/warning like
"Override class already exists. You can't install this module, except if you uninstall xxx module."
As in my mind , the installer could keep the override's owner for each class in a dedicated table , as it does for modules...


This could be indeed useful.

In fact, I really think that the overrides should be able to manage lines replacements and not only whole functions.

If 2 modules could override the same function, but not the same part of this function, this could increase the compatibility rate between overrider modules.

But this is just feature wishes. I'm really not going to develop such a tool myself. This has to come directly from the team and be implemented natively in a futur PS release.

Share this post


Link to post
Share on other sites

I thought the originator of this was talking about copying the css and tpl files into a theme automatically. Even that isn't really essential in my opinion, it's more a case that the module will use the default ones (in the module directory) unless a user wishes to override the look/behaviour as necessary in their theme, at which point they should copy the modified files into the appropriate directory in their theme directory. Even if it were to be done automatically, you would have to do it for all themes which seems pointless really, unless there's a need to.

On the overrides folder (classes and controllers) it would be easier to manage the class that the new one extends, rather than trying to merge changes but I'm not sure that even this is practical. I see hooks (and modules) as a way of adding (optional) additional functionality and the overrides as a way of replacing or modifying functionality globally. So you would use a module to add an additional step into the authentication process (an additional check perhaps) whereas an override would replace the authentication process completely. Seen in this way, then replacing a replacement makes less sense. Modules should really be self-contained and not depend on changes being made elsewhere. Overrides by their nature are not self-contained and will likely require manual changes to be made to the theme to support them (where they have an impact on the front-end).

I suggest that you only want to add an override if it is the only option other than modifying a core file i.e. it doesn't replace modules and hooks. As a developer I also feel that you should minimise the use of both to when absolutely necessary.

Paul

Share this post


Link to post
Share on other sites

  • 3 weeks later...

In my case when my module needs to modify a core class I just extend the class I want, for example, MyProduct extends ProductCore
and use MyProduct in my modules
but I coundnt find a way to extend admin/tabs/admin*.php files , I just modified the files and replace them

Share this post


Link to post
Share on other sites

  • 2 weeks later...

I use:

Db::getInstance()->Execute("UPDATE `"._DB_PREFIX_."tab` SET `module` = 'blockcategoriesnc' WHERE `class_name` = 'AdminCatalog'");



This switches the Catalog tab with the one specified in the blockcategoriesnc module.

  • Like 1

Share this post


Link to post
Share on other sites

  • 1 month later...
Yes, you can override admin tabs, but not from the overrides directory. You must override them using a module. For example, my AJAX Sliding Categories module overrides the product editor to load only the top level of categories, then loads the remaining ones using AJAX when required, which speeds up the loading when there are many categories. To do this, I copied admin/tabs/AdminProducts.php to modules/blockcategoriesnc/AdminProducts.php (and AdminCatalog.php and AdminCategories.php in my case), then modified the file as needed. I then tell PrestaShop to use this tab instead of the default one by going to Employees > Tabs, editing the Catalog tab, then entering "blockcategoriesnc" in the "Module" field. Actually, I do this automatically using an SQL query, but you don't need to do that unless you are releasing a module.


hi!

How can I override AdminProducts in that way?

Thanks,

Share this post


Link to post
Share on other sites

Copy AdminCatalog.php and AdminProducts.php to your module's directory, then modify them as necessary, then edit the Catalog tab on Employees > Tabs tab and enter your module's directory in the "Module" field, or use the code in my previous post to automatically update it. For example, my AJAX Sliding Categories module overrides the includes in AdminCatalog.php to read the AdminCategories.php and AdminProducts.php files from my module's directory:

include_once(PS_ADMIN_DIR.'/../classes/AdminTab.php');
/*** Original Code
include(PS_ADMIN_DIR.'/tabs/AdminCategories.php');
include(PS_ADMIN_DIR.'/tabs/AdminProducts.php');
***/
/*** Start of AJAX Sliding Categories Changes ***/
include(PS_ADMIN_DIR.'/../modules/blockcategoriesnc/AdminCategories.php');
include(PS_ADMIN_DIR.'/../modules/blockcategoriesnc/AdminProducts.php');
/*** End of AJAX Sliding Categories Changes ***/

Share this post


Link to post
Share on other sites

  • 2 months later...

I just figured out how to override a controller in PrestaShop v1.4, so I thought I'd let everyone know how I did it, since there is no documentation on it yet. I wanted to modify category.php and add a new hook I could use in product-list.tpl. In PrestaShop v1.3.2, I had to actually modify category.php and be careful to add those changes again every time I upgraded PrestaShop. Now, in PrestaShop v1.4, I simply created the file override/controllers/CategoryController.php with the following code:<br/><br/>

<br/><?php<br/><br/>class CategoryController extends CategoryControllerCore<br/>{<br/>    public function process()<br/>    {<br/>        parent::process();<br/><br/>        $this->smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));<br/>    }<br/>}<br/><br/>?><br/>

<br/><br/>After adding the category hook to the database, I can now use {$HOOK_CATEGORY} in product-list.tpl and I don't to have to worry about accidentally overwriting the change the next time I upgrade PrestaShop!

 

 

This doesn't work me in prestashop 1.4.4.1. I created the new hook in the database and only then add this file to override/controllers/CategoryController.php but when I try to assign a module to this hook in productlist.tpl does nothing

 

I use {$HOOK_CATEGORY} in product-list.tpl

Share this post


Link to post
Share on other sites

I compared the code in this post to the code I was successfully using on my own website and it turns out the code has changed since PrestaShop v1.4. In the latest version, you must use self::$smarty instead of $this->smarty. I've updated the code. Hopefully, it will work for you now.

Share this post


Link to post
Share on other sites

I compared the code in this post to the code I was successfully using on my own website and it turns out the code has changed since PrestaShop v1.4. In the latest version, you must use self::$smarty instead of $this->smarty. I've updated the code. Hopefully, it will work for you now.

 

 

Ok , now yes. Work for my now.

Thanks

Share this post


Link to post
Share on other sites

  • 7 months later...

I just figured out how to override a controller in PrestaShop v1.4, so I thought I'd let everyone know how I did it, since there is no documentation on it yet. I wanted to modify category.php and add a new hook I could use in product-list.tpl. In PrestaShop v1.3.2, I had to actually modify category.php and be careful to add those changes again every time I upgraded PrestaShop. Now, in PrestaShop v1.4, I simply created the file override/controllers/CategoryController.php with the following code:

 

<?php

class CategoryController extends CategoryControllerCore
{
public function process()
{
	parent::process();

	self::$smarty->assign('HOOK_CATEGORY', Module::hookExec('category'));
}
}

?>

 

After adding the category hook to the database, I can now use {$HOOK_CATEGORY} in product-list.tpl and I don't to have to worry about accidentally overwriting the change the next time I upgrade PrestaShop!

 

Thank you, thank you, thank you!!!!!!!!

Share this post


Link to post
Share on other sites

  • 1 year later...

Yes, you can override admin tabs, but not from the overrides directory. You must override them using a module. For example, my AJAX Sliding Categories module overrides the product editor to load only the top level of categories, then loads the remaining ones using AJAX when required, which speeds up the loading when there are many categories. To do this, I copied admin/tabs/AdminProducts.php to modules/blockcategoriesnc/AdminProducts.php (and AdminCatalog.php and AdminCategories.php in my case), then modified the file as needed. I then tell PrestaShop to use this tab instead of the default one by going to Employees > Tabs, editing the Catalog tab, then entering "blockcategoriesnc" in the "Module" field. Actually, I do this automatically using an SQL query, but you don't need to do that unless you are releasing a module.

It is goode way, but have some problem:

1) you couldn't controll cookes

2)you couldn't controll sessions

and bad guy can brouke you shop sending queryes to your module that can modify your db

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More