magento-logoLavorando con Magento può accadere di aver necessità di conoscere l’esatta “discendenza” di alcune categorie. Nel mio caso mi sono imbattuto nella generazione di speciali coupon di sconto che non avessero effetto sui prodotti di una specifica categoria e, ovviamente, di tutte le categorie “figlie”. Come fare per recuperarle tutte in poche istruzioni ?

Di primo acchito sembrerebbe intuitivo l’utilizzo di una funzione da invocare ricorsivamente per scoprire le “figlie” della madre, le “figlie” delle “figlie” di primo livello, le “figlie” delle figlie di secondo livello e così via di questo passo.  Sicuramente valido come approccio ma un po’ troppo dispendioso in termini di codice da scrivere.

Al contrario, tramite l’implementazione di un semplice loop di poche righe si riesce ad ottenere un’array completo di tutte le categorie che compongono un albero avendo come radice una specifica categoria master.

Aggiornamento dell’articolo : dopo un confronto con un professionista che mi ha fatto notare come Metodo 1 sia inefficiente in termini di performance mi è stato suggerito Metodo 2 come approccio migliore. Punzecchiato sul vivo ho trovato allora la best performance possibile : Metodo 3.

Tempi di esecuzione su identico database puntando ad una categoria con 14 categorie dipendenti.

  1. Metodo 1 : 307,523 millisecondi
  2. Metodo 2 : 14,293 millisecondi
  3. Metodo 3: 0,801 millisecondi

A voi la scelta.


Metodo 1 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Creazione di un'array vuota
$categories = array();
 
// Imposizione del primo Id di categoria
// che viene considerata "root"
$categories[] = 598;
 
// Inizializzazione dei contatori e dei semafori
$i = 0;
$done = false;
$parent = Mage::getModel('catalog/category')
 
// Avvio del loop
do {
 
// Caricamento della categoria che si desidera esaminare
$parent->load($categories[$i]);
 
// Ottenimento di un array contenente gli elementi "figli"
$children = explode(",", $parent->getChildren());
 
// Verifica che ci siano effettivamente dei figli
if (count($children) > 0 && !empty($children[0])) {
 
// Accodamento degli elementi figli all'array
$categories = array_merge($categories, $children);
}
 
// Incremento del contatore
$i++;
 
// Se fuori dai limiti dell'array allora chiudo il ciclo
if ($i > count($categories) - 1) { $done = true; }
 
} while ( $done == false );

Con questo semplice ciclo avremo ottenuto un’array di ID di categorie che dipendono, a prescindere dal livello, da una data categoria master (in questo caso la 598).


Metodo 2 :

1
2
3
4
5
6
7
$category = Mage::getModel('catalog/category')
->getCollection()
->addIdFilter(598)
->addAttributeToFilter('is_active', array('in' => array(0,1)))
->setPageSize(1)
->getFirstItem();
$categories = $category->getAllChildren(true);


Metodo 3 :

1
2
3
$dbConn = Mage::getSingleton('core/resource')->getConnection("core_read");
$sql = "SELECT DISTINCT cce.entity_id FROM catalog_category_entity as cce WHERE cce.path LIKE '%598%'";
$categories = $dbConn->fetchCol($sql);