Modelo de ejemplo en Yii2

Escribir código es en parte un arte… y éso nos lleva muchas veces a navegar perdidos dentro de nuestra propia creación.

Por ello, aquí se encuentra un código de ejemplo para un modelo en Yii2 (en el listado 1).

Simplemente se sugieren algunas secciones para estructurar un poco la creación, que puede que pronto crezca y se salga de nuestras manos.

Se sugieren los siguientes bloques:

  1. Constantes (líneas 9 a 10) .
  2. Propiedades adicionales (líneas 12 a 13) .
  3. Otras funciones necesarias del modelo (líneas 15 a 52) .
  4. Funciones públicas (líneas 54 a 84) .
  5. Funciones protegidas (líneas 86 a 108) .
  6. Propiedades adicionales (líneas 110 a 129) .
  7. Eventos (líneas 131 a 168) .
  8. Funciones estáticas (líneas 170 a 186) .
  9. Relaciones (líneas 188 a 210) .

Si se utiliza Sublime Text y se tiene instalado el paquete Additional PHP Snippets, se pueden crear los comentarios que separan las secciones mediante la snippet php-section-comment (siempre puedes configurar Sublime a la Ktaris).

Generalmente, y debido a la pereza, simplemente escribo phpsec y presiono Enter. Estoy casi seguro que con sólo escribir psec y Enter sería suficiente.

<?php

namespace frontend\models;

use Yii;

class Modelo extends BaseModelo
{
    const PRIMERA_CONSTANTE = 10;
    const SEGUNDA_CONSTANTE = 20;

    public $una_propiedad_publica;
    public $otra_propiedad_publica;

    public function rules()
    {
        $arr = parent::rules();

        return array_merge($arr, [
            [['atributo'], 'default', 'value' => self::PRIMERA_CONSTANTE],
        ]);
    }

    public function attributeLabels()
    {
        $arr = parent::attributeLabels();

        return array_merge($arr, [
            'descripcion' => 'Descripción',
            // Virtuales
            'propiedad_virtual' => 'Propiedad virtual',
        ]);
    }

    public function behaviors()
    {
        return [
            'blameable' => [
                'class' => \yii\behaviors\BlameableBehavior::className(),
                'createdByAttribute' => 'creacion_usuario',
                'updatedByAttribute' => 'actualizacion_usuario',
            ],
            'timestamp' => [
                'class' => 'yii\behaviors\TimestampBehavior',
                'attributes' => [
                    \yii\db\ActiveRecord::EVENT_BEFORE_INSERT => ['creacion_fecha', 'actualizacion_fecha'],
                    \yii\db\ActiveRecord::EVENT_BEFORE_UPDATE => ['actualizacion_fecha'],
                ],
                'value' => new \yii\db\Expression('NOW()'),
            ],
        ];
    }

    // ==================================================================
    //
    // Funciones públicas.
    //
    // ------------------------------------------------------------------

    /**
     * Las funciones públicas se encargan de realizar algún proceso en
     * particular con el modelo. Las más comunes, que ya provee el
     * framework, son "validate" y "save".
     *
     * Si necesitamos que el controlador haga cierto procesamiento, el
     * modelo debe encargarse del trabajo a través de un método público,
     * como "autorizar" para que el modelo se encargue de cambiar los
     * valores.
     *
     * Los nombres de las funciones públicas tienen a ser cortos. Volviendo
     * a los del framework, son sólo un verbo. Recuerden que al ser públicos,
     * se pueden usar muchas veces en muchos lugares. Hay que mantener los
     * nombres cortos pero significativos.
     *
     * Generalmente, las funciones públicas solamente modifican atributos
     * o llaman funciones privadas para el procesamiento, a menos que la
     * lógica sea muy simple.
     *
     * @return boolean determina si la acción terminó como se esperaba
     */
    public function nombreDebeContenerVerbo()
    {
        return $salioTodoBien;
    }

    // ==================================================================
    //
    // Funciones protegidas.
    //
    // ------------------------------------------------------------------

    /**
     * Las funciones protegidas realizan la lógica interna del proceso,
     * las cosas que el modelo tiene que hacer y que a nadie más le
     * deben importar, siguiendo el modelo de "caja negra":
     *     Quién sabe cómo funciona, pero funciona.
     *
     * Los nombres de las funciones protegidas a nadie le importan, porque
     * son propias de la clase,y nada más los van a usar en este archivo o
     * en sus hijitos. Los nombres de funciones protegidas pueden ser muy
     * largos y descriptivos sobre lo que hacen.
     *
     * @return string campo calculado
     */
    protected function algunCalculoInterno()
    {
        return $this->propiedad1.' '.$this->propiedad2;
    }

    // ==================================================================
    //
    // Propiedades adicionales.
    //
    // ------------------------------------------------------------------

    /**
     * Las propiedades virtuales son campos creados a nuestra conveniencia,
     * y sirven para fingir como si estuvieran en la base de datos.
     * Generalmente son un cálculo, una concatenación, entre los datos que
     * sí existen en la base de datos y otras constantes.
     * Un ejemplo es unir "nombre" y "apellido" en otra propiedad que se
     * llame "nombre_completo".
     * Las propiedades virtuales son de sólo lectura.
     * @return mixed describe el tipo de dato
     */
    public function getPropiedad_virtual()
    {
        return 'Ejemplo';
    }

    // ==================================================================
    //
    // Eventos.
    //
    // ------------------------------------------------------------------

    /**
     * Se ejecuta antes de insertar un registro en la base de datos.
     */
    public function beforeSave($insert)
    {
        // Lógica a ser implementada aquí.

        // Al final, regresar lo siguiente:
        return parent::beforeSave($insert);
    }

    /**
     * Se ejecuta después de guardar un registro en la base de datos.
     */
    public function afterSave($insert, $changedAttributes)
    {
        // Esta línea sí debe ir al principio.
        parent::afterSave($insert,$changedAttributes);

        // Lógica a ser implementada aquí.
    }

    /**
     * Este evento se ejecuta tras jalar un registro de la base de datos.
     */
    public function afterFind()
    {
        // Lógica a ser implementada aquí.

        // Al final, regresar lo siguiente:
        return parent::afterFind();
    }

    // ==================================================================
    //
    // Funciones estáticas.
    //
    // ------------------------------------------------------------------

    /**
     * Las funciones estáticas son útiles cuando queremos tener una función
     * que pertenece al modelo pero que no necesita del modelo. Son un
     * concepto más complejo.
     *
     * Pero, si se llega a dar, están hasta el final, o casi.
     */
    public static function accionQueNoNecesitaModelo()
    {
        return $algo;
    }

    // ==================================================================
    //
    // Relaciones
    //
    // ------------------------------------------------------------------

    /**
     * En teoría, las relaciones deberían ir en su mayoría en la clase base,
     * pues las genera Gii. En caso de hacer una migración con una nueva relación,
     * regenerar el modelo base.
     *
     * Aún así, puede que quieran tener una relación en código que no existe en la
     * base de dato, y hay razones legítimas para ello.
     *
     * En caso de necesitar poner una relación que no debe ir en modelo base,
     * colocarla aquí, hasta el final del archivo.
     *
     * @return \yii\db\ActiveQuery
     */
    public function getRelacion()
    {
        return $this->hasOne(\frontend\models\ClaseConNombreDeTabla::className(), ['id' => 'tabla_subordinada_id']);
    }
}

De momento, es la estructura y secciones que se utilizan en Ktaris.

¿Hay alguna sección que debería ser incluída o alguna otra distribución que valga la pena intentar?



Deja un comentario