Relaciones en Yii

| 2013-04-28 | No hay comentarios »

En este tema quiero mostrar el manejo de las claves foráneas en Yii framework mediante Active Record (AR).

Antes de usar AR para ejecutar consultas relacionales, necesitamos darle conocer a AR como una clase AR se relaciona con otra.

La relación entre dos clases AR está directamente asociada con la relación entre las tablas de la base de datos representadas por esas clases. Desde el punto de vista de la base de datos, una relación entre dos tablas A y B tiene tres tipos: uno-a-muchos (ej.: User y Post), uno-a-uno (ej.: User y Profile) y muchos-a-muchos (ej.: Category y Post). En AR, hay cuatro tipo de relaciones:

  • BELONGS_TO: si la relación entre la tabla A y B es uno-a-muchos, entonces B pertenece a A (ej.: Postpertenece a User);
  • HAS_MANY: si la relación entre la tabla A y B es uno-a-muchos, entonces A tiene muchos B (ej.: User tiene muchos Post);
  • HAS_ONE: este es un caso especial de HAS_MANY donde A tiene a lo sumo un B (ej.: User tiene a lo sumo un Profile);
  • MANY_MANY: corresponde a la relación muchos-a-muchos en la base de datos Una tabla asociativa es necesaria para romper una relación muchos-a-muchos en relaciones uno-a-muchos, ya que la mayoría de los DBMS no soportan directamente la relación muchos-a-muchos. En nuestro esquema de la base de datos de ejemplo, la tabla PostCategory sirve para este propósito. En terminología AR, podemos explicar MANY_MANY como la combinación de BELONGS_TO y HAS_MANY. Por ejemplo, Post pertenece a muchas Category y Category tiene muchos Post.

Declarar relaciones en AR involucra sobreescribir el método relations() de CActiveRecord. El método devuelve un arreglo de configuraciones de relaciones. Cada elemento del arreglo representa una sola relación con el siguiente formato:

'VarName'=>array('RelationType', 'ClassName', 'ForeignKey', ...additional options)

donde VarName es el nombre de la relación; RelationType especifica el tipo de relación, que puede ser una de las cuatro constantes: self::BELONGS_TOself::HAS_ONEself::HAS_MANY y self::MANY_MANY;ClassName es el nombre de la clase relacionada a ésta clase AR; y ForeignKey especifica la(s) clave(s) foránea(s) involucrada(s) en la relación. Pueden ser especificadas opciones adicionales al finad de cada relación (será descripto luego).

El siguiente código muestra como declarar las relaciones para las clases User y Post.

class Post extends CActiveRecord
{
    public function relations()
    {
        return array(
            'author'=>array(self::BELONGS_TO, 'User', 'authorID'),
            'categories'=>array(self::MANY_MANY, 'Category', 'PostCategory(postID, categoryID)'),
        );
    }
}

class User extends CActiveRecord
{
    public function relations()
    {
        return array(
            'posts'=>array(self::HAS_MANY, 'Post', 'authorID'),
            'profile'=>array(self::HAS_ONE, 'Profile', 'ownerID'),
        );
    }
}

Ejemplo concreto (Productos y Categorias con sus modelos y crus creados con gii):

Modelo Productos:

public function relations()
 {
 // NOTE: you may need to adjust the relation name and the related
 // class name for the relations automatically generated below.
 return array(
 'categoria' => array(self::BELONGS_TO, 'Categorias', 'id_categoria'),
 //Prestar atención a esta parte, ya que "categoria" será usado para acceder a dicho modelo y hacer consultas de una forma sencilla.
 //El modelo Categorias tiene los siguientes campos: id_categoria (pk) y desc_categoria
 );
 }

– Por defecto Yii nos crea todas las relaciones cuando creamos el modelo, pero por ejemplo si agregamos una una tabla en nuestra base de datos podemos agregar la nueva relación manualmente.
– Por defecto también Yii crea los cruds pero no muestra el valor real de la FK, para poder mostrar los valores reales en las vistas (views), hacer lo siguiente:
view.php de Productos.


id_categoria', //Modificar esa linea por:

array(
 'name'=>'id_categoria',
 'value'=>$model->categoria->desc_categoria, //Con esto se mostrará la descripción de la categoría en vez del id_categoria
 ),

_view.php de Productos.

Cambiar la linea donde se encuentra id_categoria por:


<b><?php echo CHtml::encode($data->getAttributeLabel('id_categoria')); ?>:</b>
 <?php echo CHtml::encode($data->categoria->desc_categoria); ?>  //Con esto se mostrará la descripción de la categoría en vez del id_categoria
 <br />

admin.php de Productos.

Cambiar la linea donde se encuentra ‘id_categoria’, por:


array(
 'name'=>'id_categoria',
 'value'=>'$data->categoria->desc_categoria',  //Con esto se mostrará la descripción de la categoría en vez del id_categoria
 'filter'=>Categorias::getListCategorias(),    //Esto ya es un agregado, muestra un combobox con todas las categorias para poder filtrarlas, si no lo ponemos usa el id_categoria por defecto
 //Debemos de crear una función estática en el modelo Categorias que se llame getListCategorias(), esto es totalmente opcional
 ),

Agregar la función al modelo Categorias (models/Categorias.php) para usar el filtro en la vista admin.php y también para crear o actualizar nuevos Productos:


public static function getListCategorias()
 {
 return CHtml::listData(Categorias::model()->findAll(),'id_categoria','desc_categoria');
 }

Para crear o actualizar productos y que aparezca un combobox para elegir las categorías hacer lo siguiente:
Modificar el _form.php, justamente reemplazar la parte donde encontremos el id_categoria por el siguiente código:


<?php echo $form->labelEx($model,'id_categoria'); ?>
<?php echo $form->dropDownList($model,'id_categoria',Categorias::getListCategorias(),array('empty'=>'seleccione categoria'));
//Esto es lo agregado para mostrar el combobox, como verán usa la misma función estática  que agregamos en el modelo Categorias
?>

Espero les haya servido de utilidad este tema, lo pueden adaptar todo según sus necesidades, es por eso que puse un ejemplo concreto.

Por más información sobre el tema, visitar este link

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • Phalcon – Framework PHP – Extensión de C
  • Reportes gráficos en Yii
  • Backup en Yii
  • Manual intermedio de Yii framework (PHP)



SEGUÍNOS EN FACEBOOK


GITHUB