[PHP] Listado con categorias y subcategorias

willy_chaos

Hola , pues bien me surge la duda de como hacer un listado de categorias con subcategorias.

La base de datos es esta

CREATE TABLE IF NOT EXISTS `aco_proyecto` (
  `proye_id` int(3) NOT NULL AUTO_INCREMENT,
  `proye_nombre` varchar(100) NOT NULL,
  `proye_padreid` int(3) DEFAULT NULL,
  PRIMARY KEY (`proye_id`),
  KEY `proye_padreid` (`proye_padreid`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=31 ;

--
-- Volcar la base de datos para la tabla `aco_proyecto`
--

INSERT INTO `aco_proyecto` (`proye_id`, `proye_nombre`, `proye_padreid`) VALUES
(1, 'Cursos', NULL),
(2, 'Caritas', 1),
(3, 'Electricidad', 2),
(4, 'Soldadura', 2),
(5, 'Bugaderia', 2),
(6, 'Dependiente/a de tienda', 2),
(7, 'Gestion de residuos', 2),
(8, 'Gestion de almacen', 2),
(9, 'Cursos Cruz Roja', 1),
(10, 'Cursos betula', 1),
(11, 'Cursos La Caixa', 1),
(12, 'Cursos SOC', 1),
(13, 'Cursos Generalitat', 1),
(14, 'Produccion', NULL),
(15, 'Ropa', 14),
(16, 'Recogida', 15),
(17, 'Tria', 15),
(18, 'Muebles', NULL),
(19, 'Taller de muebles', 18),
(20, 'Deixalleria', 14),
(21, 'Neteja externa e interna', 14),
(22, 'Garraf', NULL),
(23, 'Bugaderia', 22),
(24, 'Jardineria', 22),
(25, 'Rehabilitacion', 22),
(26, 'Recogida de carton', 22),
(27, 'Ropa', 22),
(28, 'Deixalleria', 22),
(29, 'Limpieza', 22),
(30, 'Cursos', 22);

La cosa es que quiero hacer un input select y que en el option me salgan tabuladas los proyectos o categorias que son hijos de otro y otra tabulacion si el padre es hijo de otro.

Dibujado seria como pongo a continuacion, asi hasta llegar a la categoria final, que no es padre de nadie.

CatPadre1
      CatPadre2
              CatHijo

Luego en otra tabla quiero guardar el arbol con sus nombres y se me habia ocurrido hacer el metodo siguiente.

Class Proyecto{
    private $id;
    private $nombre;
    private $padre;

setters y getters
metodosdiferentes

public function getTree() {
    $arbol = "";

    if ( $this->padre != NULL && $this->padre != "" ) {

        $padre = new Proyecto();
        $padre->setPadre($this->padre);
        $padre->Load();
        $arbol = $padre->getTree();
        $arbol.= " > ";
    }

        $arbol .= $this->nombre;
        return $arbol;
}

Lo ejecuto asi, pero la pagina queda cargando y al final no muestra nada ni ejecuta el codigo que hay debajo de este.

                        
$proyecto = new Proyecto(); $proyecto->setId(3); $proyecto->Load(); print $proyecto->getTree();

Alguna idea de como hacerlo?

Gracias!

Igneus

Imprime $this->padre a ver que sale, por lo que dices caes en un bucle infinito así que algo habrá mal en lo referente a esa propiedad

willy_chaos

Perdna la tardanza pero he estado intentando solucionarlo por mi cuenta pero nada...

                    $proyecto = new Proyecto();
                    $proyecto->setId(5);
                    $proyecto->Load();
                    print $proyecto->getPadre();

Al ejecutar esto, se ejecuta perfectamente, por lo que si tiene padre me aparece, si no , pues sale en blanco.

    public function getTree() {
        $arbol = "";

    if ( $this->padre != NULL && $this->padre != "" && !empty($this->padre) ) {

        $padre = new Proyecto();
        $padre->setPadre($this->padre);
        $padre->Load();
        $arbol = $padre->getTree();
        $arbol.= " > ";
    }

        $arbol .= $this->nombre;
        return $arbol;
}

Al hacer

                    $proyecto = new Proyecto();
                    $proyecto->setId(5);
                    $proyecto->Load();
                    print $proyecto->getTree();

Se queda cargando y luego pagina en blanco.

S

Buenas

Yo te lo puedo hacer rápidamente sin crear clases ni nada... si te sirve el código ya luego lo mejoras tu. Lo que hago básicamente es separar las categorías en dos array, uno tiene las maestras (las que no tienen padre) y el otro todas las demás y luego con una función recursiva busco los hijos de las categorías maestra.

<?php
$link=mysql_connect("localhost", "root", "root") or die ("Error conectando a la base de datos.");

mysql_select_db("test" ,$link) or die("Error seleccionando la base de datos.");

$sql = "SELECT * FROM `aco_proyecto`";

$result = mysql_query($sql) or die("La siguiente consulta contiene algún error:<br>nSQL: <b>$sql</b>");

$categoriasMaestras = array();
$restoCategorias = array();

while ($row = mysql_fetch_array($result)){ 
	if ($row['proye_padreid'] == '')
		array_push($categoriasMaestras, $row);
	else
		array_push($restoCategorias, $row);
}

$tree = '';

for ($i = 0 ; $i < count($categoriasMaestras) ; $i++){
	$tree .= $categoriasMaestras[$i]['proye_nombre'].'<br>';
	$tree .= getChilds($categoriasMaestras[$i]['proye_id']);
}

print $tree;

function getChilds($master_id, $sufix = ''){
	global $restoCategorias;
	
$sufix .= '-';
$tree = '';

for ($i = 0 ; $i < count($restoCategorias) ; $i++)
	if ($restoCategorias[$i]['proye_padreid'] == $master_id){
		$tree .= $sufix.$restoCategorias[$i]['proye_nombre'].'<br>';
		$tree .= getChilds($restoCategorias[$i]['proye_id'], $sufix);
	}

return $tree;
}
?>

Esto imprimiría:

Cursos
-Caritas
--Electricidad
--Soldadura
--Bugaderia
--Dependiente/a de tienda
--Gestion de residuos
--Gestion de almacen
-Cursos Cruz Roja
-Cursos betula
-Cursos La Caixa
-Cursos SOC
-Cursos Generalitat
Produccion
-Ropa
--Recogida
--Tria
-Deixalleria
-Neteja externa e interna
Muebles
-Taller de muebles
Garraf
-Bugaderia
-Jardineria
-Rehabilitacion
-Recogida de carton
-Ropa
-Deixalleria
-Limpieza
-Cursos

Pyronhell

¿ $this->padre cambia de valor alguna vez en el bucle? Me da que no y por eso se queda siempre en ejecución.

willy_chaos

Pues merci por el codigo almenos para que funcione me sirve, luego ya me peleare yo con el codigo mio.

$this->padre cambia con $padre->Load() que lo que hace es cargar todos los datos de la mysql en el objeto.

He probado hacer un

$proyecto = new Proyecto();
$proyecto->setId(2);
$proyecto->Load();
print $proyecto->getPadre();

El resultado que me devuelve es 1 (Cursos , que es padre de Caritas) por lo que en principio padre siempre tiene el valor que le toca de la linea de la mysql que extraigo.

1 respuesta
Khanser

Búsquedas jerárquicas leches, dejaos de varios arrays y árboles. Si lo puede hacer SQL, contra más simple el código php mejor.

http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

Pyronhell

#6 Pero $padre->Load() es un objeto nuevo que creas en el bucle, no en el que estás trabajando.

willy_chaos

Ostia me acabo de empanar donde estaba el error, resulta que estoy haciendo setPadre() en vez de setId() para luego hacer el Load() (vaya tonteria de error)

He cambiado eso y ha funcionado perfectamente.

public function getTree() {
        $arbol = "";

    if ( $this->padre != NULL && $this->padre != "" && !empty($this->padre) ) {

        $padre = new Proyecto();
        $padre->setId($this->padre);
        $padre->Load();
        $arbol = $padre->getTree();
        $arbol.= " > ";
    }

        $arbol .= $this->nombre;
        return $arbol;
}

Usuarios habituales