[EN] [ES]
A veces nos encontramos en circunstancias como ésta:
class TipoAnimal extends CActiveRecord {} // Tabla con los "tipos" de Animales class Animal extends CActiveRecord { // Clase del modelo padre // Modelo basado en una tabla con un campo: tipo_id // que guarda el "tipo" de Animal } class Gato extends Animal {} // Clase hija class Perro extends Animal {}
Y nos gustaría hacer algo como:
// Esta instrucción devuelve una clase "Gato" $algunAnimal = Animal::model()->findByPk(1);
Ya que Yii implementa un modelo de desarrollo llamado "Factory", es muy fácil implementar una solución rápida a este escenario.
Paso 1 (y único) Sobrecargar la función instantiate(). Incluí los comentarios originales de la función CActiveRecord
/** * Creates an active record instance. * This method is called by {@link populateRecord} and {@link populateRecords}. * You may override this method if the instance being created * depends the attributes that are to be populated to the record. * For example, by creating a record based on the value of a column, * you may implement the so-called single-table inheritance mapping. * @param array $attributes list of attribute values for the active records. * @return MiClase the active record */ protected function instantiate($attributes) { if (!isset($attributes['tipo_id'])) { // Cuando se crea and $tipo_id no se ha definido return parent::instantiate($attributes); } $classRecord = AnimalType::model()->findByPk($attributes['tipo_id']); // Cargar el "Tipo" if($classRecord === null) throw new CException('Tipo de Animal no encontrado'); $className = $classRecord->nombre; // Asumiendo que el campo "nombre" almacena el nombre de la clase hija $model = new $className(null); // El parámetro NULL es obligatorio return $model; }
Bastante sencillo, ¿verdad? A disfrutar y compartir :)