Accélérer le chargement des produits avec beaucoup de déclinaisons sur Prestashop

Le chargement des déclinaisons sur Prestashop peut vraiment augmenter le ttfb.

Pour cela j’ai créé un override qui permet de mettre en cache certaines requêtes SQL qui n’ont pas besoin d’être appelées plusieurs fois.

 

Mise en place de l'accélération du chargement des déclinaisons

À la racine de votre Prestashop, il faut vérifier si le fichier existe :

/override/classes/Product.php

Si il n’existe pas créé le et ajoutez le code ci-dessous vous devriez voir une nette amélioration sur le temps de chargement de vos produits avec beaucoup de déclinaisons.

Ce type de mise en cache pour Prestashop fonctionne sur toutes les fonctions qui envoient toujours le même résultat sur un seule page et prévient uniquement pour une fonction appelée plusieurs fois sur la même page.

Cela améliore fortement le ttfb de Prestashop et permet d’éviter les time out sur vos produits avec beaucoup de déclinaisons.

N’hésitez pas à tester et à me faire vos retours 🙂

				
					<?php

class Product extends ProductCore
{

	function cacheProductAttribute(){
		$cache_id = 'cacheProductAttribute_'.$this->id;
		if (!Cache::isStored($cache_id)){
			$product_attributes = Db::getInstance()->executeS(
	            'SELECT `id_product_attribute`
	            FROM `' . _DB_PREFIX_ . 'product_attribute`
	            WHERE `id_product` = ' . (int) $this->id
	        );
	        $json = Tools::jsonEncode($product_attributes);
	        $cache = Cache::store($cache_id, $json);
		}
		$return = Tools::jsonDecode(Cache::retrieve($cache_id),true);
		return $return;

	}

	function cacheCombinationImages($id_product_attributes,$id_lang){

		$ids = implode(', ', $id_product_attributes);
		$ids_md5 = md5($ids);
		$cache_id = '_cacheCombinationImages_'.$ids_md5.'_'.$id_lang;
		if (!Cache::isStored($cache_id)){
			$result = Db::getInstance()->executeS(
	            '
	            SELECT pai.`id_image`, pai.`id_product_attribute`, il.`legend`
	            FROM `' . _DB_PREFIX_ . 'product_attribute_image` pai
	            LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (il.`id_image` = pai.`id_image`)
	            LEFT JOIN `' . _DB_PREFIX_ . 'image` i ON (i.`id_image` = pai.`id_image`)
	            WHERE pai.`id_product_attribute` IN (' .$ids. ') AND il.`id_lang` = ' . (int) $id_lang . ' ORDER by i.`position`'
	        );
	        $json = Tools::jsonEncode($result);
	        $cache = Cache::store($cache_id, $json);
		}
		$return = Tools::jsonDecode(Cache::retrieve($cache_id),true);
		return $return;

	}
	public function getCombinationImages($id_lang)
    {
        if (!Combination::isFeatureActive()) {
            return false;
        }

        $product_attributes = $this->cacheProductAttribute();

        if (!$product_attributes) {
            return false;
        }

        $ids = array();

        foreach ($product_attributes as $product_attribute) {
            $ids[] = (int) $product_attribute['id_product_attribute'];
        }

        $result = $this->cacheCombinationImages($ids,$id_lang);

        if (!$result) {
            return false;
        }

        $images = array();

        foreach ($result as $row) {
            $images[$row['id_product_attribute']][] = $row;
        }

        return $images;
    }
    public function getAttributesGroups($id_lang)
    {
        if (!Combination::isFeatureActive()) {
            return array();
        }
        $return = $this->cachegetAttributesGroups($id_lang);
        return $return;

    }
    public function cachegetAttributesGroups($id_lang){
    	$cache_id = '_cachegetAttributesGroups'.$id_lang;
		if (!Cache::isStored($cache_id)){
	    	$sql = 'SELECT ag.`id_attribute_group`, ag.`is_color_group`, agl.`name` AS group_name, agl.`public_name` AS public_group_name,
	                    a.`id_attribute`, al.`name` AS attribute_name, a.`color` AS attribute_color, product_attribute_shop.`id_product_attribute`,
	                    IFNULL(stock.quantity, 0) as quantity, product_attribute_shop.`price`, product_attribute_shop.`ecotax`, product_attribute_shop.`weight`,
	                    product_attribute_shop.`default_on`, pa.`reference`, product_attribute_shop.`unit_price_impact`,
	                    product_attribute_shop.`minimal_quantity`, product_attribute_shop.`available_date`, ag.`group_type`
	                FROM `' . _DB_PREFIX_ . 'product_attribute` pa
	                ' . Shop::addSqlAssociation('product_attribute', 'pa') . '
	                ' . Product::sqlStock('pa', 'pa') . '
	                LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_combination` pac ON (pac.`id_product_attribute` = pa.`id_product_attribute`)
	                LEFT JOIN `' . _DB_PREFIX_ . 'attribute` a ON (a.`id_attribute` = pac.`id_attribute`)
	                LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group` ag ON (ag.`id_attribute_group` = a.`id_attribute_group`)
	                LEFT JOIN `' . _DB_PREFIX_ . 'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute`)
	                LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group`)
	                ' . Shop::addSqlAssociation('attribute', 'a') . '
	                WHERE pa.`id_product` = ' . (int) $this->id . '
	                    AND al.`id_lang` = ' . (int) $id_lang . '
	                    AND agl.`id_lang` = ' . (int) $id_lang . '
	                GROUP BY id_attribute_group, id_product_attribute
	                ORDER BY ag.`position` ASC, a.`position` ASC, agl.`name` ASC';
	        $result = Db::getInstance()->executeS($sql);
	        $json = Tools::jsonEncode($result);
	        $cache = Cache::store($cache_id, $json);
        }
        $return = Tools::jsonDecode(Cache::retrieve($cache_id),true);
        return $return;
    }
}