Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Creando Módulos en Yii 2

¿Cómo están?

En esta oportunidad quiero compartir con ustedes algo que estoy seguro les será de mucha utilidad, y es la creación de módulos en Yii 2.

Pero, ¿qué es un módulo?

De acuerdo a la documentación oficial de Yii 2:

“Los módulos son unidades de software auto-contenidas que consisten en modelos, vistas, controladores y otros componentes de soporte. Los usuarios finales pueden acceder a los controladores de un módulo si este está instalado en la aplicación. Por estas razones, los módulos son vistos usualmente como mini-aplicaciones. La diferencia de los módulos con respecto a las aplicaciones es que éstos no pueden ser desplegados por sí solos y deben residir dentro de aplicaciones.”

Es decir, un módulo es un conjunto de componentes, dispuestos de tal manera que pueden ser instalados en una aplicación aumentando así la reutilización de código.

Los módulos son especialmente útiles cuando estamos trabajando con aplicaciones de mediana a gran complejidad, donde la funcionalidad de la misma está dividida en grupos.

Por ejemplo, podemos tener un módulo que implemente un foro, un gestor de encuestas, un blog, etc.

En lugar de tener que reescribir dicha funcionalidad cada vez, podemos diseñarla y desarrollarla una vez, y reusarla en cada aplicación donde sea necesario.

Otra ventaja de los módulos, es que aceleran el tiempo de desarrollo cuando se está trabajando en un equipo.

Al dividir la funcionalidad de una aplicación en módulos, distintos miembros pueden trabajar en módulos diferentes, con lo que se logra una clara separación de responsabilidades.

Muy bien, suficiente teoría. ¡Pongamos manos a la obra!

La idea

El módulo que vamos a desarrollar consiste en un sistema de mensajería privada.

Tendrá una funcionalidad muy limitada, ya que el propósito es mostrar el proceso de creación de un módulo. Sin Embargo, nueva funcionalidad puede agregarse fácilmente. ¡Los invito a mejorarlo!

Como punto de partida para nuestro módulo, usaremos la herramienta de generación de código de yii. Gii.

En entradas anteriores la hemos empleado ya y hemos comprobado el significativo ahorro de tiempo y esfuerzo que proporciona.

Para este ejemplo, consideraremos como siempre que estamos trabajando con la plantilla avanzada, la cuál hemos instalado y a la que le hemos creado un alias en nuestro servidor. Si tienen dudas con alguno de estos pasos, pueden consultar la entrada Instalación de la plantilla avanzada.

En primer lugar, accedamos a gii:

yii2advanced.com/index.php?r=gii

Al ingresar esa dirección en el navegador, veremos la Siguiente pantalla:

Seleccionemos la opción Module Generator:

Son sólo dos campos de texto los que debemos completar. En Module Class, debemos ingresar el espacio de nombres COMPLETO dónde residirá nuestro módulo.

En este caso en particular, se ha decidido que el módulo resida en un directorio llamado modules dentro del frontend, por lo que el nombre de nuestra clase debe ser ingresado como:

frontend\modules\message\Message

La primera parte del espacio de nombres se corresponde con la estructura de directorios, y la última es el nombre seleccionado para nuestra clase propiamente dicha: Message.

Todo módulo tiene una clase principal dónde pueden efectuarse tareas de inicialización del módulo, tales como la inicialización de variables a través de parámetros, entre otras.

Otro punto a tener en cuenta, es que deberemos crear el directorio modules dentro del directorio frontend, de lo contrario obtendremos un error. Creemos pues este directorio antes de seleccionar Preview.

El segundo cuadro de texto, Module ID, será completado automáticamente, pero podemos sobreescribir su valor. La ID de un módulo, es el identificador por el que el módulo será referenciado en la aplicación. Dejemos el nombre por defecto.

A continuación podremos seleccionar Preview y a continuación Generate, luego de lo cual obtendremos el siguiente mensaje:

Podemos ver que se nos informa de 3 archivos a ser creados. El archivo de la clase del módulo propiamente dicho, y un controlador y una vista por defecto.

Continuemos y seleccionemos la opción Generate:

Además de avisarnos que la creación del módulo fue exitosa, se nos muestran las líneas de código que debemos agregar a nuestro archivo de configuración.

Abramos el archivo frontend/config/main.php, y agreguemos la entrada modules arriba indicada. Nuestro archivo deberá verse de la siguiente manera:

Lo que estamos haciendo aquí, es indicarle a nuestra aplicación que el módulo identificado como message, será accesible a partir de la clase frontend\modules\message\Message.

A partir de este momento, nuestro módulo está efectivamente instalado en el frontend.

¿Cómo accedemos a nuestro módulo?

Pues bien. Como hemos señalado anteriormente, un módulo contiene sus propios modelos, controladores, y vistas.

En yii, para convocar a una determinada acción, debemos escribir:

ruta_a_la_aplicacion/index.php?r=controlador/accion

Similarmente, cuando un módulo está instalado y queremos convocar a sus acciones, podemos hacerlo con:

ruta_a_la_aplicacion/index.php?r=modulo/controlador/accion

Si omitimos el nombre de la acción, se ejecutará la acción por defecto (index) del controlador indicado. Si se omite el controlador, se convocará al controlador por defecto (DefaultController).

De esta forma, si introducimos:

yii2advanced.com/index.php?r=message

Esto es equivalente a ingresar:

yii2advanced.com/index.php?r=message/default/index

De cualquiera de las dos maneras, veremos la siguiente pantalla:

Esta es la vista que, como se señaló anteriormente, fue creada como resultado del primer paso, la generación del módulo.

Muy bien, ahora dejemos de lado gii por un momento y concentrémonos en la estructura de los datos para soportar nuestro sistema de mensajería.

Por el momento, emplearemos una sola tabla denominada messages. Aquí tenemos la estructura de la misma:

--
-- Estructura de tabla para la tabla `messages`
--

CREATE TABLE IF NOT EXISTS `messages` (
`id` int(11) NOT NULL,
`sender_id` int(11) NOT NULL,
`receiver_id` int(11) NOT NULL,
`subject` varchar(256) NOT NULL DEFAULT '',
`body` text,
`is_read` enum('0','1') NOT NULL DEFAULT '0',
`deleted_by` enum('sender','receiver') DEFAULT NULL,
`created_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Índices para tablas volcadas
--

--
-- Indices de la tabla `messages`
--
ALTER TABLE `messages`
ADD PRIMARY KEY (`id`), ADD KEY `sender` (`sender_id`), ADD KEY `reciever` (`receiver_id`);

--
-- AUTO_INCREMENT de las tablas volcadas
--

--
-- AUTO_INCREMENT de la tabla `messages`
--
ALTER TABLE `messages`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

Es una estructura muy sencilla:

  • sender_id guarda la id del usuario que envía el mensaje
  • receiver_id guarda la id del usuario que recibe el mensaje
  • subject es el asunto del mensaje
  • body es el cuerpo del mensaje

Ya tenemos nuestra tabla, ahora podemos continuar desarrollando nuestro módulo.

Regresemos nuevamente a Gii.

El siguiente paso, es generar el modelo que se comunicará con la tabla. Para ello, emplearemos la opción Model Generator, como lo haríamos con cualquier modelo ordinario, con algunas salvedades:

 

Como podemos ver en la imagen anterior, los dos primeros cuadros de texto son los habituales. Sin embargo, debemos prestar atención a la opción Namespace.

Esta opción, por defecto, tiene el valor app\models.

Ahora bien, app\models, en realidad representa un alias, que apunta al directorio models del frontend o backend, dependiendo de a partir de dónde sea convocado gii. Es decir, si accedemos desde el frontend como en este caso, app\models representará frontend\models, y si lo hacemos desde el frontend (introduciendo backend.yii2advanced.com/index.php?r=gii por ejemplo), app\models representará backend\models.

Sin embargo, nosotros deseamos crear un modelo dentro del directorio models correspondiente a nuestro módulo.

Por ello, debemos reemplazar el valor de app\models de la siguiente manera:

De esta forma, el modelo será creado en la ubicación correcta.

El siguiente paso es utilizar el generador de CRUD:

En este punto, al seleccionar la opción Preview se presentó un problema por un olvido, que aprovecho a señalar.

Como pueden observar, en el campo Search Model Class se introdujo el siguiente valor:

frontend\modules\message\models\search\MessagesSearch

Debemos tener en cuenta, sin embargo, que el directorio search debe ser creado de antemano o de lo contrario obtendremos un error como el siguiente:

Este error desaparecerá una vez creado dicho directorio.

Aquí hay otro punto importante a tener en cuenta.

Observen el valor ingresado en View Path:

frontend\modules\message\views

Dicho valor, debería permitirnos generar las vistas en el lugar correcto. Sin embargo, al seleccionar Preview y luego Generate, las vistas no fueron generadas a pesar de que no se informó de algún error.

Si esto les sucede, simplemente dejen vacío el valor de View Path. Como resultado se creará un directorio messages dentro de frontend/views.

Luego pueden cortar el directorio y pegarlo dentro de frontend/modules/message/views, como se pretendía originalmente.

¡Muy bien!

Con esto ya tenemos la funcionalidad básica de nuestro módulo. Si ahora nos dirigimos a yii2advanced.com/index.php?r=message/messages veremos la siguiente pantalla:

Pongamos atención a la url que introducimos en el navegador, especialmente al valor ubicado luego de r=.

message/messages

message hace referencia al módulo propiamente dicho, y messages hace referencia al controlador MessagesController que fue creado con el generador de CRUD. Al omitir la acción, se convocará la acción por defecto (index).

Si seleccionamos Create Messages, veremos la siguiente pantalla:

Obviamente, es un formulario burdo, pero es un punto de partida a partir del cual podemos trabajar.

Pero antes, debemos realizar unas cuantas modificaciones.

Por un lado, sender_id no debe ser un campo de texto que pueda completar el usuario. El valor de sender_id, debe tomarse de la id que corresponde al usuario logueado.

Sin embargo, actualmente podemos acceder al módulo de mensajería sin haber iniciado sesión.

Debemos modificar esta situación.

Dirijámonos a MessagesController y reemplacemos el actual método behaviors por el siguiente:

<code>

public function behaviors()
{
    return [
        'verbs' => [
            'class' => VerbFilter::className(),
            'actions' => [
                'delete' => ['post'],
            ],
        ],
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
            ],
        ],
    ];
}

</code>

Lo diferente aquí es el agregado de la clave ‘access’ al arreglo retornado por el método.

Aquí, estamos determinando que sólo puedan acceder a las acciones del controlador los usuarios que han iniciado sesión (identificados por el rol @).

Para que lo anterior funcione, debemos agregar la siguiente sentencia:

use yii\filters\AccessControl

Podemos ubicarla debajo de las existentes.

De esta forma, al refrescar la página se nos mostrará la pantalla de inicio de sesión:

Una vez que hemos iniciado sesión, podremos acceder al formulario anterior de creación de mensajes.

Ahora podemos prescindir del campo sender_id del formulario, y tampoco son necesarios aquellos que están luego de body. Para ello debemos modificar el archivo frontend/modules/views/_form.php

El formulario debe quedar de la siguiente manera:

Para que el formulario funcione correctamente, debemos modificar ahora el método actionCreate de MessagesController:

<code>

public function actionCreate()
{
    $model = new Messages();

    $model->sender_id = yii::$app->user->identity->id;

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['view', 'id' => $model->id]);
    } else {
        return $this->render('create', [
            'model' => $model,
        ]);
    }
}

</code>

La nueva línea es:

$model->sender_id = yii::$app->user->identity->id;

Aquí, estamos asignando el valor sender_id a partir de la id del usuario logueado, que es lo que necesitamos.

Sin embargo, todavía no estamos en condiciones de probar el formulario.

Tenemos otro campo, created_at, cuyo valor debería tomar el de la fecha y hora en que se envía el mensaje.

Aquí tenemos una buena oportunidad de presentar otras facilidades que nos proporciona el framework.

Dirijámonos al archivo frontend/modules/message/models/Messages

Agreguemos el siguiente método:

<code>

public function behaviors()
{
    return [
        'timestamp' => [
            'class' => 'yii\behaviors\TimestampBehavior',
            'attributes' => [
                ActiveRecord::EVENT_BEFORE_INSERT => ['created_at']
            ],
            'value' => new Expression('NOW()'),
        ],
    ];
}

</code>

Aquí nos estamos valiendo de la clase TimestampBehavior. Esta nos permite definir atributos cuyos valores serán modificados a partir de ciertos eventos, como por ejemplo la inserción o actualización.

Estos es muy útil para establecer una auditoría básica en nuestras tablas. Por ejemplo, podemos incluir en las tablas claves dos campos: created_at y updated_at.

Y luego usar el método behaviors de la siguiente manera:

<code>

public function behaviors()
{
    return [
        'timestamp' => [
            'class' => 'yii\behaviors\TimestampBehavior',
            'attributes' => [
                ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at',
                ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at']
],
 'value' => new Expression('NOW()'),
 ],
 ];
}

</code>

De esta forma podremos conocer el momento exacto de la inserción, y el de la última modificación de cualquier registro.

En el módulo que estamos desarrollando, sólo necesitamos el campo created_at.

Para que lo anterior funcione, debemos incluir la siguiente sentencia use:

use yii\db\ActiveRecord

Ahora si, estamos en condiciones de probar el formulario:

Por supuesto, esta aún no es una solución. Como habrán notada, en el campo receiver_id, tuvimos que insertar manualmente un valor numérico que representa la id del usuario al que está destinado el mensaje.

Esto en absoluto es lo que buscamos. Una alternativa sería usar una lista desplegable que mostrara todos los usuarios, pero esta solución es poco práctica.

Creo que esta entrada se ha prolongado demasiado, en la próxima resolveremos este problema y concluiremos nuestro módulo dejándolo en un estado funcional.

Espero sus observaciones y comentarios. ¡Hasta pronto!

 




This post first appeared on Yii 2 En Español | Todo Lo Que Necesita Saber Par, please read the originial post: here

Share the post

Creando Módulos en Yii 2

×

Subscribe to Yii 2 En Español | Todo Lo Que Necesita Saber Par

Get updates delivered right to your inbox!

Thank you for your subscription

×