it-swarm.dev

Come posso selezionare gli ID di una categoria e tutte le sue sottocategorie (n livelli)?

Accanto alla categoria principale, vorrei raccogliere in modo ricorsivo tutte le sue righe figlio.

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

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

È corretto? Quale sarà il modo più efficiente?

Anche meglio:

Esiste un metodo standard (probabilmente in ContentModelCategories) per ottenere ciò di cui ho bisogno? Dovrei usare ContentModelCategories::getItems(true)? Come posso invocarlo, dato che ho già l'ID categoria "padre"?

Un esempio funzionante sarà molto apprezzato.

1
smz

Sono riluttante a pubblicarlo come "la mia risposta" in quanto probabilmente mostrerà quanto sono cattivo PHP e programmatore Joomla sono, ma, mentre funziona ... eccolo qui:

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 funzione accetta una matrice di ID categorie come argomento e restituisce una matrice contenente tutti quegli ID e gli ID di qualsiasi categoria figlio.

Se qualcuno potesse migliorarlo, sarò sinceramente grato e cambierò la mia "risposta selezionata". Grazie!

Saluti!

sMZ

0
smz

Controlla qui la mappa dei join mysql: http://www.codeproject.com/KB/database/Visual_SQL_Joins/Visual_SQL_JOINS_orig.jpg

Uno di questi è quello che stai cercando.

2
user1507

Potresti provare a usare una subquery ... Dato che conosci l'id della tua categoria padre e che l'alias è unico, potresti provare questa idea (dovresti convertirla in PHP o codice SQL con virgolette e così via, ovviamente):

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

L'ultima parte è impedire il ritorno delle categorie padre della categoria padre. Potresti voler ottenere l'alias in una query separata per semplificare questa ed evitare la seconda subquery (che è anche ridondante). È troppo tardi per me ora per pensare a soluzioni più efficienti, lo lascerò agli altri. Il risultato probabilmente non includerà la categoria padre, ma conosci già l'id di quella, giusto.

Non testato.

modifica: usa il percorso anziché l'alias

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