Soporte para relaciones muchos a muchos

Hola!

He implementado algo para controlar las relaciones muchos a muchos, lo pongo a su consideracion.

En el forms/db/archivo active_record.php
private $_registered_mn = array();
public function register_mn($relation,$isFirst){
        if(!array_key_exists($relation, $this->_registered_mn)){
		$this->_registered_mn["$relation"] = $isFirst;
	}
}
public function __call($method, $args=array()){
...
if(array_key_exists($mmodel,$this->_registered_mn)){
		    $has_relation = $true;
		    if(kumbia::$models[$model]){
		      $isFirst =  $this->_registered_mn["$mmodel"];
		      $tablemn = (!$isFirst) ? $this->source . '_' . $mmodel : $mmodel . '_' . $this->source;
		      $query = "SELECT * FROM $mmodel WHERE id IN (SELECT {$mmodel}_id FROM $tablemn WHERE {$this->source}_id = $this->id)";
		      $result = kumbia::$models[$model]->find_all_by_sql($query);
		      return $result;
		    } else {
		        return array();
		   	}
		}
...
}

La convencion de las tablas correlativas es t1_t2, el valor bool que acepta el metodo register_mn es para saber que entidad esta primera en el nombre de la tabla. Al crear los modelos quedaria asi
class Controlador extends ActiveRecord {
		
		public function Controlador(){
			$this->register_mn('rol',true);
			$this->register_mn('accion',false);
		}
		
	}

class Accion extends ActiveRecord {
	    
		public function Accion(){
		    $this->register_mn('controlador',true);
		}
		
	}


Espero que les sea util,

Comentarios

  • Podrias documentarlo un poco mas, para hacer una comparacion de esa funcionalidad que se encuentra disponible en la version 0.5...
  • edited 4:12
    He comentado el codigo, y dejo un ejemplo mas elaborado. Saludos

    Un ejemplo de relaciones muchos a muchos (m:n):

    * Un Usuario puede tener varios Roles.
    * Un Rol puede tener varios Controladores.

    En la documentación que viene con la versión 0.4 dice que estas asociaciones no están soportadas. He aquí un código con el que pude ahorrarme unas lineas de SQL:

    En el archivo /forms/db/active_record.php adicionamos la variable _registered_mn, y creamos la funcion register_mn:
    private $_registered_mn = array();
    
        /**
         * Crea una relación m-n entre dos modelos
         *
         * @param  String $relation Nombre de la entidad a la que esta relacionada.
         * @param  bool $isFirst Determina si en la tabla en la que se implementa esta relacion la entidad especificada se lista primero.
         */
        public function register_mn($relation,$isFirst){
            if(!array_key_exists($relation, $this->_registered_mn)){
                $this->_registered_mn["$relation"] = $isFirst;
            }
         }
    
    Posteriormente modificamos el método mágico __call (las dos primeras lineas se han incluido para una mejor compresion pues forman parte del archivo).
    Notese que se asume la notacion de T1_T2 en las tabla, y sus campos son de la forma T1_id, T2_id.
        /**
         * Devuelve un valor o un listado dependiendo del tipo de Relación
         *
         */
    public function __call($method, $args=array()){
        //...
        $model = ereg_replace("^get", "", $method);
        $mmodel = strtolower($model);
        //...
        if(array_key_exists($mmodel,$this->_registered_mn)){
                $has_relation = $true;
                //Si el modelo existe
                if(kumbia::$models[$model]){
                  $isFirst =  $this->_registered_mn["$mmodel"];
                  //Determinamos el nombre de la tabla que implementa la relacion.
                  $tablemn = (!$isFirst) ? $this->source . '_' . $mmodel : $mmodel . '_' . $this->source;
                  //Construimos la consulta.
                  $query = "SELECT * FROM $mmodel WHERE id IN (SELECT {$mmodel}_id FROM $tablemn WHERE {$this->source}_id = $this->id)";
                  //Ejecutamos la consulta y devolvemos el resultado.
                  $result = kumbia::$models[$model]->find_all_by_sql($query);
                  return $result;
                }
                else
                    return array();
        }
        //...
    }
    
    Procedemos a registrar los controladores:
        class Usuario extends ActiveRecord {
    
           
    
            public function Usuario(){
    
                $this->register_mn('rol',false);
    
            }
        }
    
    
        class Rol extends ActiveRecord {
    
            public function Controlador(){
    
                $this->register_mn('usuario',true);
    
                $this->register_mn('controlador,false);
    
            }
    
        }
    
        class Controlador extends ActiveRecord {
           
            public function Controlador(){
                $this->register_mn('rol',true);
            }
           
        }
    

    Para probar:
    $user = $this->Usuario->find(10);
    foreach($user->getRol()->getControlador as $controlador)
        echo $controlador->Nombre;
    
  • edited 4:12
    No he probado el código, pero considero que esta muy bien, enhorabuena hnh12358.

    Saludos y sigue así.
  • edited 4:12
    gracias <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->
Sign In or Register to comment.