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


¿Quieres comprarlo en otro sitio?

Amazon | Casa del Libro

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

6 comentarios:

  1. Hola J.Luis:

    He insertado en mi instalación de prestashop todos los productos y categorías llamando a una función desde un Servicio Web.

    Me inserta todo bien, pero los campos nleft y nright los asigna a 0.

    ¿Que procedimiento podría realizar para poder asignar a esos campos sus valores?

    Espero tu respuesta.

    Un saludo.

    Diego.

    ResponderEliminar
    Respuestas
    1. Hola Diego,

      Como comentaba en el post tienes 2 opciones:

      1) Si no vas a actualizarlas más, edita cualquiera desde el backoffice y al guardar se regenerarán los valores.

      2) Si vas a usar ese servicio web periódicamente, entonces tendrás que integrar la función "regenerateEntireNtree" que está en classes/Category.php y que es precisamente la que regenera esos valores.

      Saludos.

      Eliminar
  2. Hola!

    Gracias por el post!

    Yo estoy teniendo problemas con mi tienda que tiene más de 6000 categorías porque al insertar una nueva le cuesta regenerar el arbol muchos minutos y eso no es más que un problema...

    ¿qué consejos me darías para tener tantas categorías y poder seguir utilizando nleft y nright?

    Gracias

    ResponderEliminar
  3. Hola Jose Luis,

    Simplemente agradecerte el post, me ha sido muy útil y me ha aclarado la utilidad de estos dos campos.

    Tenía un problema de categorías en mi PS1.6 y conseguí detectar que venía por el nright y solventarlo.

    Saludos

    ResponderEliminar
  4. Genial tu artículo, andaba investigando los campos de las tablas y no entendía para que servían estos valores en el uso de categorías, ya entendí aunque no me queda claro cual es la utilidad de mantener estos rangos

    ResponderEliminar