web-dev-qa-db-fra.com

Comment sélectionner les identifiants d'une catégorie et de toutes ses sous-catégories (n niveaux)?

Outre la catégorie parente, j'aimerais collecter de manière récursive toutes ses lignes enfants.

(Pseudo-code) SELECT IDs FROM #_categories WHERE parent = father

Comme alternative, SELECT IDs WHERE the first part of path is the parent's path.

Est-ce correct? Quel sera le moyen le plus efficace?

Encore mieux:

Existe-t-il une méthode standard (probablement dans ContentModelCategories) pour obtenir ce dont j'ai besoin? Devrais-je utiliser ContentModelCategories::getItems(true)? Comment puis-je l'invoquer, étant donné que j'ai déjà l'ID de catégorie "parent"?

Un exemple de travail sera vraiment apprécié.

1
smz

Je suis réticent à publier ceci en tant que "ma réponse" car cela montrera probablement à quel point un PHP et programmeur Joomla je suis mauvais), mais, comme cela fonctionne ... le voici:

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 fonction prend comme argument un tableau d'identifiants de catégories et renvoie un tableau contenant tous ces identifiants et les identifiants de toutes les catégories enfants.

Si quelqu'un pouvait l'améliorer, je lui en serais sincèrement reconnaissant et j'y changerais ma "réponse choisie". Merci!

À votre santé!

smz

0
smz

Consultez la carte de ralliement mysql ici: http://www.codeproject.com/KB/database/Visual_SQL_Joins/Visual_SQL_JOINS_orig.jpg

L'un d'eux est ce que vous recherchez.

2
user1507

Vous pouvez essayer d’utiliser une sous-requête ... Etant donné que vous connaissez l’identifiant de votre catégorie père et que le pseudonyme est unique, vous pouvez essayer cette idée (il faudrait la convertir en PHP ou du code SQL avec des guillemets, etc.):

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 dernière partie est d’empêcher le retour des catégories de pères de votre catégorie de pères. Vous voudrez peut-être insérer l'alias dans une requête distincte pour simplifier celui-ci et éviter la deuxième sous-requête (qui est également redondante). Il est trop tard pour moi maintenant de penser à des solutions plus efficaces, je laisserai cela aux autres. Le résultat n'inclura probablement pas la catégorie père, mais vous connaissez déjà l'identifiant de celle-ci, à droite.

Pas testé.

edit: utilise le chemin au lieu de l'alias

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