hygap Posted January 24, 2017 Share Posted January 24, 2017 (edited) Hi, Looking for some advice on best practises on Presashop 1.7.x. I am looking to include at least one image of each product's colour on the product list / category page on a modification I am making to the Prestashop 1.7.0.4 starter theme. (Either to list them next to each other on the page or to have the product image thumbnail change when you hover over the various colour swatches). I can see that the products array is passed in the $listings object in Smarty. The individual product array contains a main_variants attribute which has almost all the info I need (url / colour / id_product_attribute / e.t.c) It would seem the best option would be to add an override that would addan image url to each varrient on the array. However I am not sure on best practises as to achieving this? Looking though the code i can see this array is populated in the addMainVariantsInformation() function in the ProductPresenter class in /src/Core/Product/ProductPresenter.php. This function is called by the controller class ProductListingFrontController on the function prepareProductForTemplate(array $rawProduct) As far as I can gather there isn't a mechanism to override functions in the Symfony framework code (/ProductPresenter.php) so we don't want to be making changes to the code in there. As such I think I will have to override the controller function (prepareProductForTemplate) and just add another attribute to the product class maybe main_variants_color and add my info here (once I work out how to get it ). Would this be current best practise or have I totally missed something on how to do this? --- Going forward I could see this being a pretty common type of modification theme designers might want to make to the product list page. Are there any plans to include this info in the default products listing object going forward? --- On a wide point I can see a lot of the logic is being shunted into the Symfony codebase on Prestashop. While I am totally on board with Prestashops push to hand off the dirty gubins of their platform to an established framework I wonder if they have a solid plan to give the same flexibility to override aspects of the framework that allow upgrades in the same way as current overrides mechanism? The only output on this I have seen so far is submit a change request and we will factor it into a future release. That kind of answer is likely to raise the hairs on the back of the neck of any sales manager offering theme dev or support on presatshop :/ --- Thanks in advice on any advice on the above points. Edited January 24, 2017 by hygap (see edit history) 1 Link to comment Share on other sites More sharing options...
hygap Posted January 25, 2017 Author Share Posted January 25, 2017 Just thought I would update. I achieved what I was looking for by overriding prepareProductForTemplate in the CategoryController: private function prepareProductForTemplate(array $rawProduct) { $product = (new ProductAssembler($this->context))->assembleProduct($rawProduct); $presenter = $this->getProductPresenter(); $settings = $this->getProductPresentationSettings(); $productOut = $presenter->present($settings, $product, $this->context->language); foreach ($productOut['main_variants'] as &$varient) { $imgs = Image::getImages($this->context->language->id, $varient['id_product'], $varient['id_product_attribute']); $varient['image_url'] = ''; if(count($imgs) > 0) { $varient['image_url'] = $this->context->link->getImageLink($productOut['link_rewrite'], $product['id_product'] . '-' . $imgs[0]['id_image'], 'home_default'); } } return $productOut; } There would then need to be code in the smarty template to pick up on the new var $product.main_variants[x].image_url Still needs a bit of work to pass alt and data-full-size-image-url but hopefully you get the idea. --- Any comment on if this is the best approach still welcome. Link to comment Share on other sites More sharing options...
casperravn Posted March 12, 2017 Share Posted March 12, 2017 Thanks for the update, it helped me enormously! I found the prepareProductForTemplate function In ProductListingFrontController though. Link to comment Share on other sites More sharing options...
hygap Posted May 4, 2017 Author Share Posted May 4, 2017 Thanks, yes it is in ProductListingFrontController.php as you state. Since then I have run into a bug where the overide seems not to be called on search results pages. I have submitted a bug as I really don't have a clue why this is happening. http://forge.prestashop.com/browse/BOOM-2994 If anyone has any ideas, I'm all ears? Link to comment Share on other sites More sharing options...
casperravn Posted May 4, 2017 Share Posted May 4, 2017 Thanks, yes it is in ProductListingFrontController.php as you state. Since then I have run into a bug where the overide seems not to be called on search results pages. I have submitted a bug as I really don't have a clue why this is happening. http://forge.prestashop.com/browse/BOOM-2994 If anyone has any ideas, I'm all ears? This should get you started: https://www.prestashop.com/forums/topic/601723-override-controller-function-does-not-apply/?do=findComment&comment=2529579 Link to comment Share on other sites More sharing options...
jecisa Posted October 13, 2017 Share Posted October 13, 2017 i use multi color function ,When I click black button, only one image is displayed, i just want to know ,pre 1.6.x support display all images founction ,prestashop 1.7 of new version don't have 'display all images' in products page.prestashop 1.7 how to display all images in products page. Link to comment Share on other sites More sharing options...
Bruno G Posted July 18, 2018 Share Posted July 18, 2018 I don't know how you can override the prepareProductForTemplate method since its private (I.E. can't be called by a parent or a child class). The Prestashop override is made by extending core classes (here ProductListingFrontController extends ProductListingFrontControllerCore) which means that you cant override private methods. The solution would be to also override the method prepareMultipleProductsForTemplate which calls this method and is protected... IN the code : abstract class ProductListingFrontController extends ProductListingFrontControllerCore { protected function prepareProductForTemplateWithCombinations(array $rawProduct) { ... } protected function prepareMultipleProductsForTemplate(array $products) { return array_map(array($this, 'prepareProductForTemplateWithCombinations'), $products); } } 1 Link to comment Share on other sites More sharing options...
hygap Posted June 21, 2019 Author Share Posted June 21, 2019 I'm back! Nothing like find your own two year old thread when trying to fix a new bug in the code your wrote... Presatshop 1.7.5 which now throws this exception using the above fix Quote Notice: Indirect modification of overloaded element of PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductListingLazyArray has no effect Lucky I have worked out how to hammer this override back into shape, see below: private function prepareProductForTemplate(array $rawProduct) { $product = (new ProductAssembler($this->context))->assembleProduct($rawProduct); $presenter = $this->getProductPresenter(); $settings = $this->getProductPresentationSettings(); $productOut = $presenter->present($settings, $product, $this->context->language); // Force delete this value from the ProductListingLazyArray > ProductLazyArray. Cya! $productOut->offsetUnset('main_variants', true); // Regenerate (performance hit). $mainVs = $productOut->getMainVariants(); // This time we can play around with the 'main_variants' var however we like foreach ($mainVs as &$varient) { $imgs = Image::getImages($this->context->language->id, $varient['id_product'], $varient['id_product_attribute']); $varient['image_url'] = ''; if (count($imgs) > 0) { $varient['image_url'] = $this->context->link->getImageLink($productOut['link_rewrite'], $product['id_product'] . '-' . $imgs[0]['id_image'], 'home_default'); } } // Put it back (using their method, because why not). $productOut->__set('main_variants', $mainVs); return $productOut; } Hope this helps. P.S. They also seem to have fixed the bug with it not working on the search pages that i filed. Nice work PS! P.S. P.S I still think this would be done better by inserting a custom smarty function that uses Image::getImages & getImageLink to get the info you need directly. If anyone does this please post it up here. 2 Link to comment Share on other sites More sharing options...
Bilboquet Posted January 6, 2021 Share Posted January 6, 2021 A big thanks for the solution ! I searched this for a long time how can we use it in the homepage, I display newproduct, popular and sales in the home page but it doesn't seems that the [image_url] is in main_variants array of the products in the homepage. It appear only in the categories pages... should i call productlistingfrongcontroller in ps_newproduct.php, ps_specials.php or there is a hook for this? Maybe an other function to include this script? Thank you for your time Link to comment Share on other sites More sharing options...
Bilboquet Posted January 6, 2021 Share Posted January 6, 2021 sorry it's not in main_variants array but variant[image_url], it appear only in product-list but not in product page or home page... I don't know if i'm clear lol. Link to comment Share on other sites More sharing options...
hygap Posted January 11, 2021 Author Share Posted January 11, 2021 Hi Which version of Prestashop are you running? I have it in 1.7.6.9 and it seems to work ok if you just put it in the function prepareProductForTemplate in the ProductListingFrontControler.php For previous versions i think there were some issues with the override not being called by some front end display modules as you list. You might want to try modify the core itself to see if it works on these pages when you edit the core prepareProductForTemplate function. Most places that display product set it up using the ProductListingFrontControler but if it doesn't i would work your way up the stack from that front area (e.g. specials.php ) to see how the product objects being displayed are created. Once you to the point the product is being put through $presenter->present(... you are at the point you can can in the main_variants Hope that helps Link to comment Share on other sites More sharing options...
Bilboquet Posted January 21, 2021 Share Posted January 21, 2021 Hello hygap, Thank you for your answer, it really help me I am using prestashop 1.7.6.9 and i will maybe use it with JS and replace image on hover when mouse is on color link, something like this :(i use ybc_productimagehover module) $(document).ready(function () { var variant = $('.variant-links a'); var imgPrinc = $('.product-thumbnail .second_img img'); var imgPrinc2 = imgPrinc.attr('src'); console.log(imgPrinc2); variant.mouseenter(function(){ $(this).addClass('active'); var imgReplace = $('.variant-links'); var elements = imgReplace.find('.active').attr('src'); imgPrinc.attr('src', elements); }); }); other solution: I put a foreach in product.tpl for having all declinations images but the problem was the faceted search because of the search color... all declinations where display even if it's the wrong color, also all 4 images when i have 4 declinations for 1 product... I will think of the best way when i had time for this Thank you for your solution !! Link to comment Share on other sites More sharing options...
TomSoiree Posted February 1, 2022 Share Posted February 1, 2022 in ps_special.php change if (is_array($products)) { foreach ($products as $rawProduct) { $products_for_template[] = $presenter->present( $presentationSettings, $assembler->assembleProduct($rawProduct), $this->context->language ); } } to if (is_array($products)) { foreach ($products as $rawProduct) { $presentedProduct = $presenter->present( $presentationSettings, $assembler->assembleProduct($rawProduct), $this->context->language ); $mainVariants = $presentedProduct['main_variants']; $presentedProduct->offsetUnset('main_variants', true); foreach ($mainVariants as $key => $variant) { $imgs = Image::getImages($this->context->language->id, $variant['id_product'], $variant['id_product_attribute']); $mainVariants[$key]['image_url'] = ''; if(count($imgs) > 0) { $mainVariants[$key]['image_url'] = $this->context->link->getImageLink($presentedProduct['link_rewrite'], $presentedProduct['id_product'] . '-' . $imgs[0]['id_image'], 'home_default'); } } $presentedProduct->__set('main_variants', $mainVariants); $products_for_template[] = $presentedProduct; } } 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