it-swarm.dev

¿Cómo puedo seleccionar los ID de una categoría y todas sus subcategorías (n niveles)?

Además de la categoría principal, me gustaría recopilar recursivamente todas sus filas secundarias.

(Pseudocódigo) SELECT IDs FROM #_categories WHERE parent = father

Como alternativa, SELECT IDs WHERE the first part of path is the parent's path.

¿Es esto correcto? ¿Cuál será la forma más eficiente?

Aun mejor:

¿Existe un método estándar (probablemente en ContentModelCategories) para lograr lo que necesito? ¿Debo usar ContentModelCategories::getItems(true)? ¿Cómo lo invoco, dado que ya tengo el ID de categoría "padre"?

Un ejemplo de trabajo será realmente apreciado.

1
smz

Soy reacio a publicar esto como "mi respuesta", ya que probablemente mostrará lo malo que soy PHP y el programador de Joomla que soy, pero, como funciona ... aquí está:

static function GetCategoriesWithChildren($categories) {
   $results = array();
   $db = JFactory::getDbo();
   foreach ($categories as $baseCategory)
   {
      $query = $db->getQuery(true);
      $query->select('c.path');
      $query->from('#__categories AS c');
      $query->where('c.published > 0');
      $query->where('c.id = ' . $baseCategory);
      $db->setQuery($query);
      $fathersList = $db->loadObjectList();
      foreach ($fathersList as $father)
      {
         $results[] = $baseCategory; // This adds the father only if it is published
         $query = $db->getQuery(true);
         $query->select('c.id');
         $query->from('#__categories AS c');
         $query->where('c.published > 0');
         $query->where('c.path LIKE \'' . $father->path . '/%\'');
         $db->setQuery($query);
         $children = $db->loadObjectList();
         foreach ($children as $category)
         {
            $results[] = $category->id;
         }
      }
   }
   return $results;
}

La función toma una matriz de ID de categorías como argumento y devuelve una matriz que contiene todas esas ID y las ID de cualquier categoría secundaria.

Si alguien pudiera mejorarlo, estaré sinceramente agradecido y cambiaré mi "respuesta seleccionada". ¡Gracias!

¡Aclamaciones!

smz

0
smz

Consulte el mapa de unión de mysql aquí: http://www.codeproject.com/KB/database/Visual_SQL_Joins/Visual_SQL_JOINS_orig.jpg

Uno de ellos es lo que estás buscando.

2
user1507

Podría intentar usar una subconsulta ... Dado que conoce la identificación de su categoría padre y el alias es único, es posible que desee probar esta idea (necesitaría convertirla a PHP o código SQL con comillas, etc., por supuesto):

SELECT id 
FROM categories 
WHERE path LIKE CONCAT(%,(SELECT alias FROM categories WHERE id = yourid),%) 
AND WHERE id NOT IN 
  (SELECT id 
   FROM categories 
   WHERE alias LIKE CONCAT(%,(SELECT alias FROM categories WHERE id = yourid))
);

La última parte es evitar el regreso de las categorías de padre de su categoría de padre. Es posible que desee obtener el alias en una consulta separada para simplificar esta y evitar la segunda subconsulta (que también es redundante). Ya es demasiado tarde para mí para pensar en soluciones más eficientes, se lo dejaré a los demás. El resultado probablemente no incluirá la categoría padre, pero ya conoce la identificación de esa, ¿verdad?.

No probado.

editar: use la ruta en lugar del alias

SELECT id
FROM categories
WHERE path LIKE CONCAT(
  (SELECT path 
   FROM categories
   WHERE id = yourid),%);
1
elk