uddhava Posted May 12, 2011 Posted May 12, 2011 Since there is not any piece of decent information available written by the PS team about overriding classes files i hope that someone here can give a fully qualified answer ;-).If i want to override a class, for example FrontController.php in PS 1.4.x what do i need to do?1) do i copy the classes/FrontController.php to /override/classes 2) do i create an empty file?On the PS blog i found this bit of info , but as usual it leaves even more questions then answers.So what do i need to do and what can be used as a skeleton code?You can find the definitive answer in this post.Or read below 1 Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 So ok, thanks Angora for the brief intro on the overrides. Now i want to make it crystal clear to myself and to others on this forum. So will create an example.Example (1) i want to introduce a new Hook. (favorite question on the forum).Hookname : HOOK_HOMEBLOCKThe Hook declaration is part of the function : public function displayHeader()So i would use the following code ?? class FrontController extends FrontControllerCore { public function displayHeader() { parent::displayHeader(); $this->smarty->assign('HOOK_HOMEBLOCK', Module::hookExec('homeblock')); } } I tried this code and it doesnt work. I get a server 500 error. When i deleted the Smarty assign code then the code works but the whole layout of the shop is messed up.So do i need to copy the whole function displayHeader ? Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 Finally after searching with google on overrides i found a nice post from Rocky about override.You can read it here.But when i try this out it doesnt work for me (see above example). So maybe something has changed in the configuration of override in 1.4.2?ys Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 PS.For those who dont know how to work with hooks can find info here, here and "forget hooks - use a plugin" Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 I tried this code : class FrontController extends FrontControllerCore { public function displayHeader() { parent::displayHeader(); self::$smarty->assign(array( 'HOOK_HOMBLOCK' => Module::hookExec('homeblock') )); } } Also doesnt work, although now the layout is not messed up. Looks like i'm making progress... Share this post Link to post Share on other sites More sharing options...
BigZ Posted May 13, 2011 Posted May 13, 2011 helloyou should change the order of processing as the tpl file is parsed in the parent functionput the smarty assign before calling parent::displayHeader();if that does not work try to display the result of hookExec('homeblock') within something like die to see if the hook call works correctly, then we should work on some other solution Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 In another thread, Angora gives these answers : do I have to copy the entire process function Yes So it seems necessary to copy the whole displayHeader() code to my overriding file? Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 On its personal website from Paul C he has an excellent article about using a plugin instead of working with Hooks to display modules anywhere in your template files by using a very simple smarty opcode. (he! PS team! Read this and Implement!! pls)> Thanks Paul C and good luck making this plugin work with Smarty v3 and PS1.4.2In his example he is also overriding class files like this : class FrontController extends FrontControllerCore 08 { 09 10 function __construct() 11 { 12 parent::__construct(); 13 } 14 15 function init() 16 { 17 parent::init(); 18 19 global $smarty; 20 21 $this->smarty = $smarty; // Not really sure why, but necessary. 22 23 if (!Configuration::get('PS_FORCE_SMARTY_2')) 24 { 25 $this->smarty->registerPlugin('function', 'plugin', 'smartyEcartPlugin'); 26 } else { 27 $this->smarty->register_function('plugin', 'smartyEcartPlugin'); 28 } 29 } 30 } So from this example it seems that we need a function __construct and parent::__construct ? Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 Thanks Angora for your comments. Highly appreciated. Have you INSERTed a row to the db hook table for your new hook, as instructed in that article? Yes i did that of course. Thats why i included the extra informational post above for those readers that didnt get to that part.:-)I already had the new hook working, but i just copied the whole FrontController file. When i read more about it on the forum i understood that you only need a small part of the file to override code.So in summary you need this general code to override the FrontController and introduce a new Hook.class FrontController extends FrontControllerCore { public function displayHeader() { ORIGINAL FUNCTION CODE + EXTRA CODE FOR NEW HOOK } } Is the parent::displayHeader() then needed, and what is actually meant for?(you can guess i am not a php programmer ) Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 13, 2011 Posted May 13, 2011 (see the supplied classes/_Module.php for example. It omits the constructor) I was wondering what those _files are for in the override/classes folder ?The code seems totally different then the original file, for example the _FrontController.php . Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 15, 2011 Posted May 15, 2011 Ok, i tried all three examples. Here are the results :1) whole controller -> That obviously will work2) Original Function code + custom code -> That also works3) Call to parent + just the code. -> first Errors --> Now Successi used this code : class FrontController extends FrontControllerCore { public function displayHeader() { self::$smarty->assign(array('HOOK_HOMEBLOCK' => Module::hookExec('homeblock'))); parent::displayHeader(); } } I get these error messages :Strict Standards: Accessing static property IndexController::$smarty as non static in D:\websites\presta142\override\classes\FrontController.php on line 34Notice: Undefined property: IndexController::$smarty in D:\websites\presta142\override\classes\FrontController.php on line 34Fatal error: Call to a member function assign() on a non-object in D:\websites\presta142\override\classes\FrontController.php on line 34 I figured it out. The parents needs to be called after the new hook has been assigned to the array. Duh.. makes sense.. I changed the code above to the correct one. Share this post Link to post Share on other sites More sharing options...
uddhava Posted May 15, 2011 Posted May 15, 2011 [updated] changed text according to Angora's recommendations. [updated 8 jun 2011] Corrected code due to Payment Method errorSo after the excellent comments by Angora, which took some time to comprehend, this thread is solved for me at least. I hope that anybody looking for some good info on hooks will find this thread. To summarize this thread:Overriding class files can be done by :* create a folder with subfolders called: override/classes /controllers * copy the class or controller file you need to these folders.(in 1.4.2 these folders are already created)Then depending on your needs you can override :1) Override entire class2) Override individual functions (aka methods) of the class When you copy the whole file from the /classes file to the /override/classes folder and add/change the code then you have completed (1). But you need to extend the class. For example the file FrontController.php; change the line class FrontControllerCore to class FrontController extends FrontControllerCore 2) Just add your own code and call the parent function. Just be sure to watch the order.In my example i added a custom hook to the displayHeader() function that resides in the FrontController Class. In this case i add the new hook and then call the rest of the function with a parent call. class FrontController extends FrontControllerCore { public function displayHeader() { if (!self::$initialized) $this->init(); self::$smarty->assign(array('HOOK_HOMEBLOCK' => Module::hookExec('homeblock'))); parent::displayHeader(); } } The $this->init() code is needed otherwise an error will occur when selecting a payment method during Checkout. 1 Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 3, 2011 Posted June 3, 2011 I hope that anybody looking for some good info on hooks will find this thread. Well, be happy. This thread just saved my life !I was desperatly seeking for a SIMPLE way to add a hook by using overides.Your code works perfectly ! Thank you so much ! Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 7, 2011 Posted June 7, 2011 My solution seems not to work when you try to choose a Payment Method. It then gives the error : Fatal error: Call to a member function assign() on a non-object in D:\websites\142fin-afterupgrade\override\classes\FrontController.php on line 13 If i look at Line 13 (smarty assign) class FrontController extends FrontControllerCore { public function displayHeader() { self::$smarty->assign(array('HOOK_HOMEBLOCK' => Module::hookExec('homeblock'))); parent::displayHeader(); } } then something goes wrong. I have no idea what. When i include the whole displayHeader function in my override file then it works. So for now that will be my workaround. Share this post Link to post Share on other sites More sharing options...
Burhan BVK Posted June 7, 2011 Posted June 7, 2011 Include this in your displayHeader function: if (!self::$initialized) $this->init(); Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 8, 2011 Posted June 8, 2011 That did the trick!! Thanks Whitelighter. I have corrected my previous post with the solution. Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 8, 2011 Posted June 8, 2011 Now you can find all developer info on Rocky's personal website.This is invaluable for developers.http://www.nethercottconstructions.com/en/content/32-prestashop-development-guide Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 9, 2011 Posted June 9, 2011 This doesn't seem to work on everything.I'm trying to override _getPaymentMethods() from OrderOpcController.phpI just want to modify the text of an error message if (!$this->isLogged) return ' '.Tools::displayError('Please sign in to see payment methods').''; So I have created a OrderOpcController.php in override/controllers with the following code : <? class OrderOpcController extends OrderOpcControllerCore { public function _getPaymentMethods() { if (!self::$initialized) $this->init(); if (!$this->isLogged) return ' '.Tools::displayError('test').''; parent::_getPaymentMethods(); } } ?> And then... nothing. Presta displays the regular warning message. I even tryed to just put a "exit;" in the function, but I didn't get the white page. Just the regular one.I seek for hours, but I can't tell why it doesn't work.Someone would have any idea ?Thanks Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 10, 2011 Posted June 10, 2011 You might try to change the order. So first the parent call and then your new code.If that doesnt work, then try to copy the whole method (function) and change this particular line. Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 10, 2011 Posted June 10, 2011 Thanks for the answer.I tryed both things, but nothing happens.As I told in my previous post, it seems that the override isn't even taken in consideration by Presta.I even tryed this : <? class OrderOpcController extends OrderOpcControllerCore { public function _getPaymentMethods() { exit; } } ?> I should get a white page, but I don't. The regular page is still displaying.I tryed to remove the underscores in the function name (maybe they messed up the process) but no more success.I checked and re-checked the names of my files and every other parameter. My code should work, but it doesn't, and I really don't understand why...Could someone try on his side and tell me if the problem is the same ? Maybe it's a bug that we should report in the forge. Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 10, 2011 Posted June 10, 2011 Make sure your Caching is disabled and Force Compile is set to True...Then try to copy the whole function method and try again Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 10, 2011 Posted June 10, 2011 Cache is disabled.Force compile is on.Full function copied in the override file.I even deleted manually the files in the /smarty/compil folder, just to be sure to have a recompilation, but nothing changes.Did you tryed on your side ?Thank you for your help ! Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 10, 2011 Posted June 10, 2011 Cant try it out at the moment. I am not at home. But you could try to use my example and see if that works.I think the overriding of classes differs from overriding controllers. Just look closely at the dev guide from Rocky. (see above) Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 11, 2011 Posted June 11, 2011 Cant try it out at the moment. I am not at home. But you could try to use my example and see if that works.I think the overriding of classes differs from overriding controllers. Just look closely at the dev guide from Rocky. (see above) I tryed many things, but I can't get this to work.I'm pretty sure that OrderOpcController.php is a controller and not a class, so this is not the issue.I just don't understand why this is not working... Share this post Link to post Share on other sites More sharing options...
uddhava Posted June 11, 2011 Posted June 11, 2011 Hopefully i find the time this weekend to try out your code. But im going on vacation for a 7 days next week and dont have readily access to a computer. Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 11, 2011 Posted June 11, 2011 Thank you to confirm this Angora !!OK, I'll try you're way and let a note in the forge.Very nice to have tryed ! Thanks again ! Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 11, 2011 Posted June 11, 2011 I copy/paste the function in the override, changing just the text of an error message.It doesn't work.I more and more think this is a bug. Share this post Link to post Share on other sites More sharing options...
Paul C Posted June 11, 2011 Posted June 11, 2011 Odjavel,Firstly are you sure that you have placed the OrderOpcController.php override class in override/controllers ?Another thought is that I'm pretty sure redeclaring a protected function as public will cause a problem. Try: <?php class OrderOpcController extends OrderOpcControllerCore { protected function _getPaymentMethods() { exit; } } Paul Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 11, 2011 Posted June 11, 2011 Hi Paul.This makes no difference.Even when I copy/paste the whole exact original function.And yes my file is in the godd place.Try yourself ;-) Easy and quick to do. You will see : there's no way to override this controller.At least, no way that I found. Share this post Link to post Share on other sites More sharing options...
Paul C Posted June 12, 2011 Posted June 12, 2011 Yes, I've had a look at the code and it doesn't look like you'll be able to override it. Whether it's a bug or not could probably be debated, but it's a good example to use when learning about overriding classes in PHP The problem is that this function is only ever called from within a function defined in OrderOpcController, and the scope is limited by the "self" keyword (it's called from ::preProcess() and ::_assignPayment() in the parent OrderOpcController class using the self scope modifier).Try the following: class TestParent{ protected function _getPaymentMethods() { echo ' Function called from Parent.'; } public function testing() { echo 'Try self'; self::_getPaymentMethods(); echo 'Try $this'; $this->_getPaymentMethods(); } } class TestChild extends TestParent{ protected function _getPaymentMethods() { echo ' Function called from Child.'; } } $parent = new TestParent(); $child = new TestChild(); echo 'Parent Test'; $parent->testing(); echo 'Child Test'; $child->testing(); The output you get is: Parent Test Try self Function called from Parent. Try $this Function called from Parent. Child Test Try self Function called from Parent. Try $this Function called from Child. The "self" keyword used with the scope operator means that the "parent" version of the function will always be called when the testing function uses "self::".Now as to whether it's a bug or not.... I don't actually see why this function is called with the self:: scope modifier as the function calling it isn't declared "static", which is normally why you would use the self scope modifier. I suspect that if you replaced the "self::" with "$this->" in the preProcess and _assignPayment() functions it would work fine as you're expecting it to. Note that there are a couple of functions in that class that suffer from the same "problem"., not just this one.Paul Share this post Link to post Share on other sites More sharing options...
Odjavel Posted June 12, 2011 Posted June 12, 2011 Hi Paul,Well I tryed exactly your way and it works !But then I made another test, and it appears that it works too just by copying preProcess() and _assignPayment() in the override. No need to change every self:: by $this->. In fact, for what I want to do (editing 1 error message in _getPaymentMethods() function) it also works when you include only _assignPayment() in the override.Anyway, you made this to work, and I'm thankful for that ! Thank you for your interest in my problem ! :-)EDIT : there is still a problem. When you change a parameter like the carrier in the checkout page, the function is not overriden any more. So I'm back to your first method (the 3 functions and $this->), but the override still stops when the checkout page makes an ajax call.I'll digg to try to find something about this... Share this post Link to post Share on other sites More sharing options...
Paul C Posted June 12, 2011 Posted June 12, 2011 Yes, because by moving those two functions, "self" now refers to the child class not the parent class Ideally you don't want to have to make copies of functions in your override, but in this case at least it gets it working (until maybe the PS developers change the Core class......). I think it would be worth reporting it to the bug tracker to be looked at, because I don't believe that the way this currently works is intentional.... as I said above, it isn't just that function that will suffer from the same problem either (and maybe there are other cases in other classes).Paul Share this post Link to post Share on other sites More sharing options...
Paul C Posted June 12, 2011 Posted June 12, 2011 Well the ajax calls are handled in ::preProcess() so making a copy of that function in your override too should really sort it.Paul Share this post Link to post Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now