Jump to content

1.7.x - Display Images of all Product Varients on Product List / Category Pages


Recommended Posts

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 by hygap (see edit history)
  • Like 1
Link to comment
Share on other sites

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

  • 1 month later...
  • 1 month later...

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

  • 5 months later...

20171013155428.png
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

  • 9 months later...

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);
}
}
  • Like 1
Link to comment
Share on other sites

  • 11 months later...

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.

  • Like 2
Link to comment
Share on other sites

  • 1 year later...

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

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

  • 2 weeks later...

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

  • 1 year later...

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

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
×
×
  • Create New...