Necesitas mi libro "Claves para abrir una tienda online y que venda" y lo sabes...


¿Quieres comprarlo en otro sitio?

Amazon | Casa del Libro

Mostrando entradas con la etiqueta nested set model. Mostrar todas las entradas
Mostrando entradas con la etiqueta nested set model. Mostrar todas las entradas

Organización de las categorías en Prestashop

Las categorías en Prestashop se organizan internamente con el "nested set model"  o modelo de conjunto anidado.

Es un algoritmo de recorrido de árbol o jerarquías y es una forma de almacenamiento de datos jerárquicas dentro de bases de datos relacionales.

Un árbol es una estructura de datos que contiene un número de nodos vinculados y un nodo padre puede conectarse a varios nodos secundarios, repitiéndose esta organización a través de varios niveles.

Cada nueva inserción, borrado o modificación implicar volver a numerar los nodos.

En versiones anteriores a Prestashop 1.6, se podían dejar en blanco los campos nLeft y nRight de la tabla ps_category, respetando el resto de campos imprescindibles como el id_parent y el level_depth, pero en la versión 1.6 si no se completan estos campos, las categorías no aparecerán en el frontoffice o parte pública, ni tampoco saldrán organizadas desde el backoffice en el formulario de alta de un artículo cuando se asocia a una categoría desde la opción de "Expand" o mostrar todo el árbol de categorías.

Cada elemento del árbol termina con dos valores, nLeft para la izquierda y nRight para la derecha, que se puede utilizar para identificarlos e indicar su relación con los otros elementos del árbol o estructura jerárquica. 

Por ejemplo, si una subcategoría X tiene un valor de 2 y 15 para nLeft y nRight respectivamente todos los nodos que con valores superiores a 2 y los valores inferiores a 15 son dependientes de la subcategoría X. 


Todo esto es un aspecto importante a tener en cuenta siempre que existan procesos externos de actualización o importación de artículos (en mi caso más de 2.000 categorías desde un ERP).

Si la inserción es puntual (ej: una importación de una estructura de catálogo), al modificar cualquier categoría desde el backoffice (aunque no se haya modificado realmente nada), se regeneran los valores de los campos nLeft y nRight, la función que se utiliza en este proceso es "regenerateEntireNtree"

El código de esta función "regenerateEntireNtree" está en classes/Category.php:

/**
              * Re-calculate the values of all branches of the nested tree
              */
            public static function regenerateEntireNtree()
            {
                       $id = Context::getContext()->shop->id;
                       $id_shop = $id ? $id: Configuration::get('PS_SHOP_DEFAULT');
                       $categories = Db::getInstance()->executeS('
                       SELECT c.`id_category`, c.`id_parent`
                       FROM `'._DB_PREFIX_.'category` c
                       LEFT JOIN `'._DB_PREFIX_.'category_shop` cs
                       ON (c.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.')
                       ORDER BY c.`id_parent`, cs.`position` ASC');
                       $categories_array = array();
                       foreach ($categories as $category)
                                   $categories_array[$category['id_parent']]['subcategories'][] = $category['id_category'];
                       $n = 1;

                       if (isset($categories_array[0]) && $categories_array[0]['subcategories'])
                                   Category::_subTree($categories_array, $categories_array[0]['subcategories'][0], $n);
            }

            protected static function _subTree(&$categories, $id_category, &$n)
            {
                       $left = $n++;
                       if (isset($categories[(int)$id_category]['subcategories']))
                                   foreach ($categories[(int)$id_category]['subcategories'] as $id_subcategory)
                                               Category::_subTree($categories, (int)$id_subcategory, $n);
                       $right = (int)$n++;

                       Db::getInstance()->execute('
                       UPDATE '._DB_PREFIX_.'category
                       SET nleft = '.(int)$left.', nright = '.(int)$right.'
                       WHERE id_category = '.(int)$id_category.' LIMIT 1');
            }





Referencias:

http://www.slickpalm.com/cual-es-el-modelo-anidado-set/
http://en.wikipedia.org/wiki/Nested_set_model