JuanTomas Posted October 8, 2015 Share Posted October 8, 2015 (edited) (Using P-Shop 1.6.1.1) It's easy to override methods that return raw data. For instance, BlockNewProducts.php in the blocknewproducts module has the getNewProducts() method: class BlockNewProducts extends Module{ ... protected function getNewProducts() { // makes an array called $newProducts, which contains several product objects return $newProducts; } ... } So you can override like: class BlockNewProductsOverride extends BlockNewProducts{ protected function getNewProducts() { $NewProducts = array(); $BaseProducts = parent::getNewProducts(); foreach ($BaseProducts as $product){ // Add Custom Fields To Each Product Object $product['my-key']="My Most Excellent Value"; // Push modified product objects onto a new array $NewProducts[] = $product ; } // Now the template can behave differently depending on the values in each product's my-key return $NewProducts ; }} But some modules don't have a separate method like this. Consider BlockViewed.php in the blockviewed module. Its hookRightColumn() method does all the work in the class. You can skip most of the code, what's important is: * The method is longish * The method contains all the "business logic" for displaying viewed objects, and... * The method calls display() at the end. class BlockViewed extends Module{ ... public function hookRightColumn($params) { $productsViewed = (isset($params['cookie']->viewed) && !empty($params['cookie']->viewed)) ? array_slice(array_reverse(explode(',', $params['cookie']->viewed)), 0, Configuration::get('PRODUCTS_VIEWED_NBR')) : array(); if (count($productsViewed)) { $defaultCover = Language::getIsoById($params['cookie']->id_lang).'-default'; $productIds = implode(',', array_map('intval', $productsViewed)); $productsImages = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT MAX(image_shop.id_image) id_image, p.id_product, il.legend, product_shop.active, pl.name, pl.description_short, pl.link_rewrite, cl.link_rewrite AS category_rewrite FROM '._DB_PREFIX_.'product p '.Shop::addSqlAssociation('product', 'p').' LEFT JOIN '._DB_PREFIX_.'product_lang pl ON (pl.id_product = p.id_product'.Shop::addSqlRestrictionOnLang('pl').') LEFT JOIN '._DB_PREFIX_.'image i ON (i.id_product = p.id_product)'. Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').' LEFT JOIN '._DB_PREFIX_.'image_lang il ON (il.id_image = image_shop.id_image AND il.id_lang = '.(int)($params['cookie']->id_lang).') LEFT JOIN '._DB_PREFIX_.'category_lang cl ON (cl.id_category = product_shop.id_category_default'.Shop::addSqlRestrictionOnLang('cl').') WHERE p.id_product IN ('.$productIds.') AND pl.id_lang = '.(int)($params['cookie']->id_lang).' AND cl.id_lang = '.(int)($params['cookie']->id_lang).' GROUP BY product_shop.id_product' ); $productsImagesArray = array(); foreach ($productsImages as $pi) $productsImagesArray[$pi['id_product']] = $pi; $productsViewedObj = array(); foreach ($productsViewed as $productViewed) { $obj = (object)'Product'; if (!isset($productsImagesArray[$productViewed]) || (!$obj->active = $productsImagesArray[$productViewed]['active'])) continue; else { $obj->id = (int)($productsImagesArray[$productViewed]['id_product']); $obj->id_image = (int)$productsImagesArray[$productViewed]['id_image']; $obj->cover = (int)($productsImagesArray[$productViewed]['id_product']).'-'.(int)($productsImagesArray[$productViewed]['id_image']); $obj->legend = $productsImagesArray[$productViewed]['legend']; $obj->name = $productsImagesArray[$productViewed]['name']; $obj->description_short = $productsImagesArray[$productViewed]['description_short']; $obj->link_rewrite = $productsImagesArray[$productViewed]['link_rewrite']; $obj->category_rewrite = $productsImagesArray[$productViewed]['category_rewrite']; // $obj is not a real product so it cannot be used as argument for getProductLink() $obj->product_link = $this->context->link->getProductLink($obj->id, $obj->link_rewrite, $obj->category_rewrite); if (!isset($obj->cover) || !$productsImagesArray[$productViewed]['id_image']) { $obj->cover = $defaultCover; $obj->legend = ''; } $productsViewedObj[] = $obj; } } if (!count($productsViewedObj)) return; $this->smarty->assign(array( 'productsViewedObj' => $productsViewedObj, 'mediumSize' => Image::getSize('medium'))); return $this->display(__FILE__, 'blockviewed.tpl'); } return; } ... } How is it possible to override this? You'd literally have to copy the entire method into your override to add any functionality to it. That kind of override will not play well with upgrades. I think this is a violation of the MVC concept, because it couples the Model to the View so tightly that you can't floss in between. Business logic belongs in a separate method where it can be safely overridden. Any method making a display() call should be getting its input data from a separate "business logic" method. This problem is widespread in Prestashop core modules and classes. Is there something I'm missing here? Is there an elegant way to override methods like this? Edited October 8, 2015 by JuanTomas (see edit history) Link to comment Share on other sites More sharing options...
Paul C Posted October 8, 2015 Share Posted October 8, 2015 Hooks are usually a better way of overriding the business logic - when there's a suitable one available that is. Overriding the core classes themselves is also good. With these you can then manipulate the data at creation consistently. As for modules such as those in your examples - it would usually be better just implementing your own than overriding an existing one. Link to comment 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