ti-enxame.com

Como posso selecionar os IDs de uma categoria e todas as suas subcategorias (n níveis)?

Ao lado da categoria pai, eu gostaria de coletar recursivamente todas as suas linhas filho.

(Pseudo-código) SELECT IDs FROM #_categories WHERE parent = father

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

Isso está correto? Qual será a maneira mais eficiente?

Melhor ainda:

Existe um método padrão (provavelmente em ContentModelCategories) para alcançar o que eu preciso? Devo usar ContentModelCategories::getItems(true)? Como eu o invoco, já que eu já tenho o ID da categoria "pai"?

Um exemplo de trabalho será realmente apreciado.

1
smz

Estou relutante em publicar isso como "minha resposta", pois provavelmente mostrará como sou um péssimo programador do PHP e do Joomla, mas, como funciona ... aqui 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;
}

A função usa uma matriz de IDs de categorias como argumento e retorna uma matriz contendo todos esses IDs e os IDs de qualquer categoria filho.

Se alguém puder melhorar, ficarei sinceramente agradecido e mudarei minha "resposta selecionada". Obrigado!

Felicidades!

smz

0
smz

Verifique o mapa de junção do mysql aqui: http://www.codeproject.com/KB/database/Visual_SQL_Joins/Visual_SQL_JOINS_orig.jpg

Um deles é o que você está procurando.

2
user1507

Você pode tentar usar uma subconsulta ... Como você conhece o id da categoria pai e o alias é único, convém tentar essa idéia (seria necessário convertê-la para PHP ou código SQL com aspas e assim por diante, é claro):

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))
);

A última parte é impedir o retorno das categorias pai da sua categoria pai. Convém obter o alias em uma consulta separada para simplificar esta e evitar a segunda subconsulta (que também é redundante). Agora é muito tarde para eu pensar em soluções mais eficientes, deixarei isso para os outros. O resultado provavelmente não incluirá a categoria pai, mas você já sabe o ID dessa, certo.

Não testado.

editar: use o caminho em vez do alias

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