Herencia y relaciones de clases

He desarrollado una aplicación bien básica con Yii pero necesito saber si estoy haciendo las cosas bien.

Se me ocurre este ejemplo para ilustrar un poco mi duda: Supongamos que estamos desarrollando un sistema donde registro las evaluaciones que realizan los alumnos dentro de una universidad.

  • Si en un diagrama de clases tenemos las clases ALUMNO y DOCENTE que heredan de la clase PERSONA y poseen atributos particulares, cómo podría codificar esto en Yii? ¿Qué modelos debería crear?

  • Siguiendo con el mismo diagrama, notamos que la clase DOCENTE posee una relación con la clase MATERIA (no importan las cardinalidades). Nuevamente, cómo relaciono estas clases/modelos en Yii si por ejemplo quiero saber que materias dicta un determinado profesor?

Gracias.

Hola, tengo la misma duda,

Tengo una clase Usuario con la información común a todos los usuarios (dni, nombre, apellido…) y tengo 3 clases más que herendan de Usuario, que son Administrador, profesor y Alumno, con sus relaciones a otras clases y con sus información especifica.

¿cómo debería modelar esto en yii?

migueArgentina, aun que no te contestó nadie, ¿lo solucionaste? ¿como lo hiciste?

Hasta ahora he creado los modelos con gii de la siguiende manera: el de Usuario lo he creado con clase base CActiveRecord y en los otros 3 lo he creado con la clase base Usuario. ¿esto es correcto?

Un saludo!

Muchas gracias

Esta es la parte avanzada que Yii nos permite hacer de manera muy sencilla.

Hay dos formas:

  1. La forma clásica: que es teniendo tres tablas físicas en la base de datos, y en Yii generamos los modelos para cada uno (con las relaciones y herencia respectiva)

  2. Por "Factory", y para no entrar en tanto detalle técnico, hago referencia a un wiki que publiqué hace un tiempo en Español: http://www.yiiframework.com/wiki/414/instanciar-clase-hija-basada-en-campo-de-modelo-padre-cactiverecord/

Saludos.

Habría una tercera forma para los fanáticos de UML :P usando “interfaces”, pero creo que el caso es demasiado sencillo y no amerita complicarlo demasiado Principio KISS y DRY).

Saludos.

En cuanto a la 1º forma:

[indent]Creo que eso es lo que he hecho pero no se si lo he hecho correctamente, lo que he hecho es lo siguiente:

  • En la base de datos:

Tengo 4 tablas Usuarios(dni, nombre, apellidos, direccion…), Alumnos(dni_usuario, y mas columnas especificas), Profesores (dni_usuario, y mas columnas) y administradores (dni_usuario).

  • En el codigo:

Como he dicho antes he creado las clases con gii que me ha creado la clase Usuario (heredando a CActiveRecord) y las demás clases heredan de Usuario. Automaticamente se han generado las relaciones en Administrador, profesor y alumno BELONGS_TO hacia la clase Usuario y en Usuario 3 relaciones HAS_ONE hacia las clases hijas.

Ahora mi pregunta: ¿esto es correcto? ¿tengo que sobreeescribir todos los metodos en las clases hijas?

[/indent]

En cuanto a la 2º forma:

[indent]

No he entendido al 100% que hace exactamente instantiate(), ¿se llama en la clase hija y lo que hace es crear un nuevo objeto de la clase hija? ¿sin atributos?

[/indent]

Muchas gracias por la ayuda!

Un saludo!

La opción dos se usa cuando la tabla basees la misma, pero tiene comportamiento diferente (o usa la información de manera diferente), algo como lo que hace postgresql con la herencia de tablas.

Pero viendo que aplicó la solución1, entonces en ese caso la forma sencilla es definir las relaciones desde el motor de la base de datos y luego permitir que Gii genere los modelos (con las relaciones en él autodetectadas en ambas direcciones, BELONGS_TO y HAS_MANY, o ONE_ONE según el caso).

Ahora mi pregunta es si están almacenando/consultando bien y sin problemas.

Sea dicho de paso que si desean tener un generador de código más completo que el Gii "genérico", les recomiendo AweCrud.

Y contestando la pregunta de @migueArgentina, sería algo así:





$docente = Docente::model()->findByPk(1); // Cargamos el docente de id=1

$materias = $docente->materias; // Le puedo poner paréntesis a materias() y dentro del paréntesis puedo poner la condición.

//A recorrer las materias

foreach($materias as $mat){

    echo $mat->nombre; // Imprimimos el nombre de la materia

}



Si, por ahora está almacenando y consultando bien. Muchas gracias por tu ayuda.

Tengo una última pregunta:

[indent]

si quiero hacer una consulta entre 2 tablas que no se relacionan entre sí, ¿tengo que usar obligatoriamente:


findAllBySql($sql,$params);

?

El caso es con la tabla alumnos y profesores, que como he dicho en post anteriores se relacionan con Usuario pero no entre si. lo que quiero hacer es buscar todos los alumnos que no sean profesores y lo he hecho con la siguiente consulta:




$sql='SELECT * FROM Alumnos WHERE Alumnos.dni NOT IN (SELECT Profesores.dni FROM Profesores)';

$alumnos=Usuarios::model()->findAllBySql($sql);



¿Se puede hacer con las consultas propias de CActiveRecord?

[/indent]

Un saludo

Muchas gracias!! ;)

Sí se puede hacer por CActiveRecord, pero exige más trabajo :P




Alumnos::model()->findAll(

	array(

		// El with y el together se pueden omitir si no se van a usar las relaciones

		'with'=>array('Usuario','Usuario.Profesor'), // Asumo que así se llaman las relaciones (y que en Usuario la relación se llama Profesor)

		'together'=>true, // Se hace una sola consulta (eager-loading)

		'condition'=>'Acá va la condición con el NOT IN")

	)

);



Oook muchas gracias!! ;)