Ver Mensaje Individual
  #3 (permalink)  
Antiguo 06/08/2014, 08:23
chefote
 
Fecha de Ingreso: mayo-2012
Ubicación: Madrid
Mensajes: 7
Antigüedad: 12 años
Puntos: 0
Respuesta: Ordenación de categorías

Bueno.
Lo primero, quiero agradecerte que te hayas tomado tiempo para ver el código y darme tu opinión, que siempre es bueno compartir ideas.
Lo de poner mis iniciales fue una forma que se me ocurrio de "exclusivizar" los nombres de las funciones para que no surja error si, por casualidad, tu código define una función que use el mismo nombre. Es como un prefijo para que no surjan conflictos de nombres. Podría haber usado un namespace, pero he ido a simplificar.

En cuanto al código, ahi va:

Clase class.ordenarCategorias.php

Código PHP:
Ver original
  1. <?php
  2. /***************************************************************************************************************************
  3. ****************************************************************************************************************************
  4. ****************************************************************************************************************************
  5. ***************                                                                                              ***************
  6. ***************            Clase para ordenación de matrices en base a categorías.                           ***************
  7. ***************            Versión 1.4                                                                       ***************
  8. ***************            Desarrollada por José López Quijado.                                              ***************
  9. ***************            Es de libre uso, distribución y modificación.                                     ***************
  10. ***************                                                                                              ***************
  11. ****************************************************************************************************************************
  12. ****************************************************************************************************************************
  13. ***************************************************************************************************************************/
  14.  
  15.     class ordenarCategorias{
  16. // Se definen las propiedades que tendrán los objetos de esta clase.
  17.         public $matriz = array(); //Matriz a procesar.
  18.         public $idItem; //Código de la categoria del elemento.
  19.         public $nombreItem; //Nombre de la categoria.
  20.         public $idPadre; //Codigo de la categoria de la que depende.
  21.         public $nuevaPosicionGeneral = 0; //Indicador de posicion del elemento con respecto a otros.
  22.         public $salidaTabulada = false; //Salida tabulada o con lista completa escalada de jerarquias (opción por defecto).
  23.         public $idPadreBase = 0; //La id de padre base puede cambiar, según se establezca en la llamada.
  24.         public $cadenaDeSeparacion = " > "; //Separación entre elementos en la lista por jerarquías.
  25.         public $tabulacion = "&nbsp;&nbsp;&nbsp;&nbsp;"; //Tabulación por nivel, en la lista tabulada.
  26.  
  27. /* El siguiente método ajusta la id de padre de los registros a 0 en los de más alto nivel,
  28. si no es 0 previamente. */
  29.         function JLQ_idPadreCero(){
  30.             if ($this->idPadreBase == 0) return;
  31.             foreach ($this->matriz as $clave=>$valor) if ($valor[$this->idPadre] == $this->idPadreBase) $this->matriz[$clave][$this->idPadre] = "0";
  32.         }
  33.  
  34. /* El siguiente método recupera el id de padre original, por si no era 0. */
  35.         function JLQ_restaurarPadreBase(){
  36.             if ($this->idPadreBase == 0) return;
  37.             foreach ($this->matriz as $clave=>$valor) if ($valor[$this->idPadre] == "0") $this->matriz[$clave][$this->idPadre] = $this->idPadreBase;
  38.         }
  39.  
  40. /* El siguiente método añade un campo numérico a cada elemento de la matriz.
  41. Este se empleará para realizar la ordenación por categorías pero, de momento,
  42. se inicializa a cero.*/
  43.         function JLQ_agregarPosVertical(){
  44.             foreach ($this->matriz as $clave=>$valor) $this->matriz[$clave]["posVertical"] = 0;
  45.         }
  46.  
  47.  
  48. /* El siguiente método coloca valores en los campos numéricos añadidos a la matriz, en base a las
  49. relaciones entre el código de cada categoría y el código de aquella de la que desciende cada una. */
  50.         function JLQ_ponerPosiciones ($categoriaPadre = 0) {
  51.             $matrizNueva = array();
  52.             foreach($this->matriz as $elemento){
  53.                 if ($elemento[$this->idPadre] == $categoriaPadre && $elemento["posVertical"] == 0){
  54.                     $matrizNueva[] = $elemento;
  55.                 }
  56.             }
  57.  
  58.             foreach ($matrizNueva as $elemento){
  59.                 $this->nuevaPosicionGeneral ++;
  60.  
  61.                 foreach ($this->matriz as $clave=>$item){
  62.                     if ($item[$this->idItem] == $elemento[$this->idItem]){
  63.                         $this->matriz[$clave]["posVertical"] = $this->nuevaPosicionGeneral;
  64.                     }
  65.                 }
  66.                 $argumento = (int)$elemento[$this->idItem];
  67.                 $this->JLQ_ponerPosiciones($argumento);
  68.             }
  69.             unset($matrizNueva);
  70.         }
  71.  
  72. /* Una vez colocados los valores númericos en los campos que añadimos, se ordenan los
  73. elementos de la matriz en base, precisamente, a dichos campos.*/
  74.         function JLQ_reOrdenar(){
  75.             if (!function_exists("JLQ_ordenar")){
  76.                 function JLQ_ordenar($a, $b){
  77.                     return ($a["posVertical"] < $b["posVertical"]) ? -1 : 1;
  78.                 }
  79.             }
  80.             usort($this->matriz, "JLQ_ordenar");
  81.         }
  82.  
  83. /* Los nombres de las categorias se modifican de modo que cada uno incluya la secuencia
  84. de todas las categorías de las que desciende, con un separador específico. */
  85.         function JLQ_reconstruirNombres(){
  86.             $matrizTemporal = array();
  87.             foreach ($this->matriz as $elemento) $matrizTemporal[$elemento[$this->idItem]] = $elemento;
  88.             foreach ($this->matriz as $clave=>$elemento){
  89.                 if ($elemento[$this->idPadre] != "0"){
  90.                     $categoriaBuscada = $elemento[$this->idPadre];
  91.                     $cadenaPrecedente = "";
  92.                     while($categoriaBuscada != "0"){
  93.                         $cadenaPrecedente = $matrizTemporal[$categoriaBuscada][$this->nombreItem].$this->cadenaDeSeparacion.$cadenaPrecedente;
  94.                         $categoriaBuscada = $matrizTemporal[$categoriaBuscada][$this->idPadre];
  95.                     }
  96.                     $this->matriz[$clave][$this->nombreItem] = $cadenaPrecedente.$elemento[$this->nombreItem];
  97.                 }
  98.             }
  99.             unset ($matrizTemporal);
  100.         }
  101.  
  102. /* Por último, se eliminan los campos que se añadieron, y que ya no son necesarios. */
  103.         function JLQ_eliminarPosVertical(){
  104.             foreach ($this->matriz as $clave=>$valor){
  105.                 unset($this->matriz[$clave]["posVertical"]);
  106.             }
  107.         }
  108.  
  109. /* El método JLQ_crearMapa() encadena la llamada a los distintos métodos de la clase,
  110. en la secuencia adecuada, y devuelve la matriz ordenada según nuestros deseos. */
  111.         function JLQ_crearMapa(){
  112.             $this->JLQ_idPadreCero();
  113.             $this->JLQ_agregarPosVertical();
  114.             $this->JLQ_ponerPosiciones();
  115.             $this->JLQ_reconstruirNombres();
  116.             $this->JLQ_reOrdenar();
  117.             $this->JLQ_eliminarPosVertical();
  118.             if($this->salidaTabulada){ //Si se quiere la salida con tabulaciones, esta se establece aquí.
  119.                 foreach($this->matriz as $indice=>$elemento){
  120.                     $tabulacion = "";
  121.                     while(true){
  122.                         $recorte = strstr($elemento[$this->nombreItem], $this->cadenaDeSeparacion);
  123.                         if (!$recorte) break;
  124.                         $elemento[$this->nombreItem] = substr($recorte, strlen($this->cadenaDeSeparacion));
  125.                         $tabulacion .= $this->tabulacion;
  126.                     }
  127.                     $this->matriz[$indice][$this->nombreItem] = $tabulacion.$elemento[$this->nombreItem];
  128.                 }
  129.             }
  130.             $this->JLQ_restaurarPadreBase();
  131.             return $this->matriz;
  132.         }
  133.     }
  134. ?>

Ejemplo de uso

Código PHP:
Ver original
  1. <?php
  2.     $dbhost = "localhost";
  3.     $dbuser = "root";
  4.     $dbpass = "";
  5.     $dbname = "almacen";
  6.     $conexion = @mysql_connect ($dbhost, $dbuser, $dbpass);
  7.     mysql_select_db ($dbname,$conexion);
  8.  
  9.     $consulta = "SELECT id_de_categoria, descripcion, id_de_padre FROM categorias;";
  10.     $hacerConsulta = mysql_query($consulta, $conexion);
  11.     $natrizDeCategorias = array();
  12.     while($categoria = mysql_fetch_assoc($hacerConsulta)) $matrizDeCategorias[] = $categoria;
  13.     @mysql_free_result($hacerConsulta);
  14.  
  15.  
  16.     include("class.ordenarCategorias.php");
  17.  
  18.     $miMatriz = new ordenarCategorias();
  19.     $miMatriz->matriz = $matrizDeCategorias;
  20.     $miMatriz->idItem = "id_de_categoria";
  21.     $miMatriz->nombreItem = "descripcion";
  22.     $miMatriz->idPadre = "id_de_padre";
  23.     $miMatriz->idPadreBase = "0";
  24.     $miMatriz->salidaTabulada = true;
  25.     $miMatriz->cadenaDeSeparacion = "==>>";
  26.     $miMatriz->tabulacion = "&nbsp;&nbsp;&nbsp;&nbsp;";
  27.     $matrizOrdenada = $miMatriz->JLQ_crearMapa();
  28.  
  29.     foreach ($matrizOrdenada as $elemento) echo $elemento["descripcion"]."<br />";
  30. ?>