Função para criar um array de categorias em forma de árvore
Bem, cá vai a primeira dica para o blog
Há alguns meses pediram-me para rever uma função que tinha como objectivo criar uma lista de categorias em árvore, a função até nem estava muito mal, quando apenas existia Pais e Filhos, ou seja 2 niveis de categorias. O problema era quando se inseria um 3º nivel, ou mais.
Bem apos uns dias de teste e analise consegui melhor a funçã0, com uma tabela de teste com 771 categorias a função demorava por volta de 0.51 segundos, como disse até nem esta mau, mas se pensarmos em aumentar isto para 5000 categorias, seria complicado.
Logico que poderiamos fazer isto doutra forma, atraves de ajax por exemplo, carregando as filhas apenas quando se clicasse nos pais. Mas o que se pretendia era que toda a arvore fosse carregada de inicio (objectico indexação de palavras para o google), e depois atraves de CSS ir mostrando e ocultando as filhas.
Como disse ao fim de alguns dias, reduzi a função e o resultado para 0.0016 segundos.
Aqui fica a função, ou melhor as funções. Os comentários estão em ingles mas isso não deve ser problema:
1º passo, fazer o select á base de dados e criar um array com as categorias. Esta tabela é constituida pelos seguintes campos:
id – incremental, chave primaria
parent- campo inteiro, onde guardamos qual a categoria pai
name – nome da categoria
<?php $cat_array = build_tree('categories', 'id, name, parent', 'parent ASC, name ASC', 'id'); ?>
Abaixo está a função build_tree, com os devidos comentários e explicações.
<?php /** * Function build_tree($table, $fields, $fields_order, $master='id') * * OVERVIEW: Create a MultiDimensional Array with the data off a table * * RETURNS: Returns a unique array with all the values * * EXAMPLE: $tree=build_tree('categories', 'id, name, parent_id' , 'parent_id asc, name asc', 'id'); * * @param string $table name to the database table * @param string $fields name(s) for the table fields to get * @param string $fields_order sql order condition * @param string $master name to the table unique key field, usualy id (optional if id is primary key value and unique) */ function build_tree($table, $fields, $fields_order, $master='id') { /* check if fields order is set, if not set 1st field as asc order by*/ if ($fields_order=='') { $temp=explode(',' ,$fields); $fields_order = $temp[0].' asc'; } /* build the query */ $query=mysql_query('select '.$fields.' from '.$table.' order by '.$fields_order); /* read the query and build the array */ while ($result=mysql_fetch_assoc($query)) { /* $result[$master] is the unique key value */ $tree[$result[$master]]=$result; } /* return the array */ return $tree; } ?>
2º passo, chamar a função que vai criar o array com a estrutura pais, filhos, netos, etc., usando logicamente o array criado acima, $cat_array
<?php $tree=tree_to_folders($cat_array, 0, 'parent', 'name', SORT_ASC); ?>
Aqui está a função, para converter em árvore e a respectiva ordenação:
<?php /** * Function tree_to_folders($tree, $root, $parent_var='parent', $order='id', $order_val=SORT_ASC) * * OVERVIEW: Create array with the a category tree or a map tree * * RETURNS: Returns a unique array with the tree information * * EXAMPLE: $links=tree_to_folders($tree, '0', 'parent', 'name', SORT_DESC); * * @param array $tree pre build tree array * @param string/integer $root id from the master parent we want to design the tree * @param string $parent_var name to the parent field on the array (optional - default value "padre") * @param string $order name on the field on the array to make the order (optional - defalut value "id") * @param string $order_val type or order we whant SORT_ASC/SORT_DESC (optional default value "SORT_ASC") */ function tree_to_folders($tree, $root, $parent_var='parent', $order='id', $order_val=SORT_ASC) { foreach ($tree as $id => $subarray) { if ($subarray[$parent_var] != $root) { if (isset($tree_result[$subarray[$parent_var]])) { $tree_result[$subarray[$parent_var]]['folders'][$subarray['id']]=$tree[$id]; } else { $flag=0; $valid=$id; $var=''; while ($flag==0) { if (isset($tree[$valid])) { if ($tree[$valid][$parent_var]!='0' ) { $var="['folders']['". $tree[$valid]['id']."']".$var; } else { $var='["'. $tree[$valid]['id'] .'"]'.$var; $flag=1; } $valid=$tree[$valid][$parent_var]; } else { $flag=1; } } $var='$tree_result'.$var.'=$tree[$id];'; eval($var); } } else { $tree_result[$tree[$id]['id']]=$tree[$id]; } } $tree_result=order_tree($tree_result,$order, $order_val); return $tree_result; } function order_tree($tree, $order, $order_val ){ foreach ($tree as $key => $row) { $ordered[$key] = $row[$order]; if (isset($tree[$key]["folders"])) { $tree[$key]['folders']=order_tree($tree[$key]['folders'], $order, $order_val); } } array_multisort($ordered, $order_val, $tree); return $tree; }
Agora seria apenas necessário fazer um ciclo para mostrar as categorias, mas isso fica para outro dia ![]()
Envie um comentário