Relaciones entre entidades: Parte II

Hola a todos! Como os prometí aquí os traigo la segunda y última parte acerca de las relaciones entre las entidades del modelo de nuestras aplicaciones basadas en Yii Framework.

En este post os contaré cómo tratar dos escenarios con los que es común encontrarse cuando trabajamos con dos entidades relacionadas dentro de nuestro modelo. Si recordáis el ejercicio de la entrada anterior, disponíamos de las clases del modelo País y Ciudad y establecimos que, esta última, tuviese una relación de dependencia con la primero. Los escenarios a los que nos enfrentamos son:

  1. ¿Cómo mostrar el listado de nombres de ciudad para poder elegir una desde la vista de países en lugar del identificador?
  2. ¿Cómo mostrar el listado de ciudades en base a un país seleccionado desde un segundo selector?

Entorno de desarrollo

  • OS X Yosemite (10.10.3) – SSOO
  • MAMP (3.2.1) (PHP 5,6,7, MySQL 5.0.11-dev y Apache 2.2.29) – Lenguaje, Servidor y gestor de bases de datos).
  • Sublime Text (3) – Editor de texto
  • Yii Framework (2.0.4) – Framework de desarrollo PHP
  • Composer (1.0-dev) – Gestor de dependencias para PHP

Dónde nos quedamos?

Como os comentaba, en el ejercicio anterior dejamos el proyecto listo para poder empezar a administrar dos nuevas entidades del modelo: País (Country) y Ciudad (City). Apoyándonos en Gii creamos las clases del modelo, la vista y el controlador y a continuación indicamos como, desde nuestro phpmyadmin podíamos establecer la relación entre las dos tablas para que desde Gii se auto-generase el código sin necesidad de “picarlo” nosotros.

1er escenario: relaciones entre tablas

El primer punto lo solventaremos modificando levemente el código de algunos de nuestros ficheros .php de las vistas (view). Actualmente, cuando accedemos al listado de ciudades (cities) desde la url http://localhost:8888/basic/web/index.php?r=city nos encontramos esto:

yiirelationships17

Como ya dijimos, esta forma de visualizar la información no es intuitiva para el usuario, puesto que cuando quiere consultar una ciudad tiene que recordar el país al que hace referencia el identificador que se muestra en la columna Country ID. Así que, para “facilitarle la vida” al usuario, vamos a mostrar el nombre del país en lugar del identificador.

Para ello abrimos el fichero views/city/index.php que es el encargado de mostrar el GridView donde se muestra la información de la anterior imagen, y aquí vamos a modificar el código para que nuestro GridView sea de la siguiente forma:

relationsshipsII1

No os olvidéis de indicar que utilizamos 2 nuevas clases dentro de este fichero por lo que añadid lo siguiente al inicio:

use yii\helpers\ArrayHelper;
use app\models\Country;

Este es el resultado una vez que recargamos la página:

relationsshipsII2

El siguiente paso es aplicar la misma filosofía en el resto de vistas en las que se muestre el identificador del país (Country ID) en lugar del nombre. Empezamos por views/city/view.php donde el código del DetailView quedará de la siguiente forma:

relationsshipsII3

De manera que cuando accedamos al detalle de una de las ciudades del listado veremos algo como esto:

relationsshipsII4

Sigamos aplicando esta misma filosofía, pero esta vez en el formulario de creación/edición de ciudades. Si desde el listado de ciudades pulsamos sobre Create new (http://localhost:8888/basic/web/index.php?r=city%2Fcreate) vemos que el formulario contiene un campo de texto para introducir el identificador del país:

relationsshipsII5

Bien! Pues vamos a hacer que esto sea un campo de selección de los países que ya están dados de alta en la BBDD. Para ello modificamos el código del fichero views/city/_form.php substituyendo la línea:

<?= $form->field($model, 'country_id')->textInput() ?>

Por la siguiente:

use yii\helpers\ArrayHelper;
use app\models\Country;

<?= $form->field($model, 'country_id')
->dropDownList(
ArrayHelper::map(Country::find()->all(), 'id', 'name'))
?>

Si volvemos a recargar la página debemos ver algo parecido a esto:

relationsshipsII6

Os animo a que apliquéis esta técnica a cualquier otra relación que hayáis creado en vuestro proyecto y la compartáis para que podamos conocer cuál ha sido vuestra solución o si habéis encontrado alguna dificultad con la que podamos ayudaros.

2º escenario: selectores dependientes

Con lo anterior explicado, hemos solventado el primer punto de nuestros dos escenarios mencionados al inicio de esta entrada y a continuación abordaremos el segundo punto. Para ello, vamos a poner en práctica el primer punto añadiendo las propiedades País y Ciudad a la entidad del modelo Usuario (user) que creamos en nuestra primera entrada.

Lo primero, como siempre que queremos añadir nueva información al modelo, es definir la columna en la tabla correspondiente de nuestra BBDD, de manera que con la inclusión de los campos Country y City nuestra estructura de la tabla user debe quedar de la siguiente forma:

relationsshipsII7

Os recuerdo los pasos para crear esta estructura:

  1. Crear las columnas city_id y country_id.
  2. Crear un índice por cada una de estas columnas.
  3. Crear la relación de la tabla user con la tabla city y country a partir de los índices.

Aquí debéis tener en cuenta que, cuando vayamos a crear las relaciones, como ya tenemos datos creados en la tabla de nuestros usuarios, phpmyadmin os puede dar el error:

#1452 – Cannot add or update a child row: a foreign key constraint fails ( …

Por lo tanto, entre el paso 2 y 3 debemos exportarnos los datos de los usuarios, eliminar todos los usuarios de la tabla, ejecutar el paso 3 y por último volver a crear los usuarios, o al menos uno con el que podamos acceder a la administración de la aplicación. Os muestro como deberían quedar las relaciones entre tablas:

relationsshipsII8

Para hacerlo más sencillo y que dispongáis de un usuario rápidamente, os paso la cláusula INSERT que lancé al final de estos pasos en lugar de insertar de nuevo todos los usuarios:

INSERT INTO `user` (`id`, `username`, `auth_key`, `password_hash`, `password_reset_token`, `email`, `status`, `created_at`, `updated_at`, `country_id`, `city_id`) VALUES (1, 'vicmonmena', 'xhukgP1kqKtrTqq8qGda62UXZ-a3KNtZ','$2y$13$epIWyKeMjD0nX20ATjjtZeN7xMWs6Mv4uniWPzWa15D0urTTd0zqa', NULL, 'vicmonmena@gmail.com', 10, 1434215225, 1434215225, 2, 2)

Vamos a comprobar que nuestra web continúa funcionando correctamente a pesar de haber incluido estos cambios en la BBDD. Para ello vamos a crear un usuario (http://localhost:8888/basic/web/index.php?r=user%2Fcreate) y vamos a ver si se ha generado el registro en la BBDD:

relationsshipsII9

Todo parece funcionar correctamente! Ahora vamos a adaptar el formulario de creación/edición de usuarios para que podamos escoger la ciudad y el país. Para ello, como hicimos en el escenario 1 añadimos el siguiente código en el fichero views/user/_form.php:

use yii\helpers\ArrayHelper;
use app\models\City;
use app\models\Country;

<?= $form->field($model, 'country_id')
->dropDownList(
ArrayHelper::map(Country::find()->all(), 'id', 'name'))
?>

<?= $form->field($model, 'city_id')
->dropDownList(
ArrayHelper::map(City::find()->all(), 'id', 'city'))
?>

Y vamos a ver cómo queda la página en nuestro navegador:

relationsshipsII10

Todo parece pintar bien; sin embargo, faltan algunos detalles bastante importantes y en los cuales podéis haber caído ya si habéis seguido las anteriores entradas acerca del desarrollo con Yii.

Empecemos por adaptar el código de nuestras entidades del modelo para trabajar con las relaciones. Para ello, nos apoyaremos en Gii (si no habéis leído aún la entrada Yii: Framework Gii, este es un buen momento). Con esto solo tenemos que copiar y pegar el código que Gii nos propone en nuestras clases: User, City y Contry, y en este mismo orden os indico qué código he añadido yo:

User.php

use app\models\City;
use app\models\Country;

/**
* @inheritdoc
*/
public function rules()
{
return [
...
[['country_id', 'city_id'], 'integer'],
];
}

/**
* @return \yii\db\ActiveQuery
*/
public function getCity()
{
return $this->hasOne(City::className(), ['id' => 'city_id']);
}

/**
* @return \yii\db\ActiveQuery
*/
public function getCountry()
{
return $this->hasOne(Country::className(), ['id' => 'country_id']);
}

City.php

use app\models\User;

/**
* @return \yii\db\ActiveQuery
*/
public function getUsers()
{
return $this->hasMany(User::className(), ['city_id' => 'id']);
}

Country.php

use app\models\User;

/**
* @return \yii\db\ActiveQuery
*/
public function getUsers()
{
return $this->hasMany(User::className(), ['country_id' => 'id']);
}

Y ahora vamos a comprobar que efectivamente si elegimos una ciudad y un país estos quedan registrados para nuestro nuevo usuario, creemos un usuario nuevo!

relationsshipsII11

Y veamos que en la BBDD aparece:

relationsshipsII12

Perfecto! Pero…¿No notáis algo que no cuadra? ¿Un usuario que es de Huelva, ciudad de Canadá? Este es el segundo punto importante, filtrar el listado de ciudades en función del país seleccionado para que la información que se introduzca tenga sentido.

Para que sea más sencillo voy a enumerar los pasos que tenemos que dar para adaptar nuestro formulario para que el comportamiento de los selectores funcione de esta forma:

1. Crear una función en el controlador de ciudades que nos devuelva el listado de ciudades filtrado por identificador de país (country_id). Para esto, he creado una nueva action en la clase controllers/CityController.php con el siguiente código:

/**
* Obtiene un listado de ciudades cuyo contry_id coincida con el argumento.
* El formato del listado será HTML de tipo <option value=ID>NAME</option>
*/
public function actionList($id) {
    $cities = City::find()->where(['country_id' => $id])->all();
    $citiesSize = City::find()->where(['country_id' => $id])->count();
    if ($citiesSize > 0) {
        foreach ($cities as $city) {
            echo "<option value='" . $city->id . "'>" . $city->city . "</option>";
        }
     } else {
        echo "<option>-</option>";
     }
}

2. Modificar el código del primer dropDownList (el de países) del formulario views/user/_form.php para que cargue el listado de ciudades en base al país seleccionado. El código quedaría así:

use yii\helpers\Url;

<?= $form->field($model, 'country_id')
->dropDownList(
ArrayHelper::map(Country::find()->all(), 'id', 'name'),
[
'prompt' => 'Selecciona país',
'onchange' => '$.get("' .
Yii::$app->urlManager->createUrl('city/list') . '", { id:                         $(this).val() }).done(
function(data) {
$("select#user-city_id").html(data);
});'
]
);
?>

Varias observaciones sobre el código anterior:

  • Hemos añadido comportamiento al evento onchange para que cuando se seleccione un país, se invoque la action definida en el controlador: list pasándole como argumento el valor seleccionado: $(this).val(), que en este caso es el id del país.
  • Una vez se ejecuta el método definido en CityController (actionList), el código html generado se asigna al dropDownList que hemos incluído en nuestra vista para cargar el listado de ciudades: select#user-city_id.
  • Al final, la URL que se genera mediante la llamada a:

Yii::$app->urlManager->createUrl(‘city/list’) . ‘”, { id: $(this).val() }

debe ser similar a:

http://localhost:8888/basic/web/index.php?r=city%2Flist&id=2

  • Por último, para poder saber cuál es el id que yii auto-genera para el dropDownList de ciudades, debemos localizarlo en el DOM del formulario (_form). Para ello los navegadores traen herramientas de desarrollo ya integradas que permiten explorar los elementos del HTML de las páginas rápidamente, como se aprecia a continuación:

relationsshipsII13

Y el resultado final es…

Aquí os dejo cómo debería quedar el listado de ciudades cuando seleccionamos un España:

relationsshipsII14

Y cuando escogemos Canadá:

relationsshipsII15

Por último os animo a que pongáis en práctica los conocimientos adquiridos hasta el momento y añadáis a las vistas del listado de usuarios (views/user/index.php) y de detalle de usuario (views/user/view.php) estos campos Ciudad y País para que podamos prescindir de phpmyadmin para comprobar a qué ciudad y país pertenece cada usuario. Os dejo cómo debería quedaros al final:

relationsshipsII16

Y eso es todo por ahora, en cuanto a las relaciones entre entidades del modelo. Como siempre, os dejo el código para que lo descarguéis de este repositorio.

Hasta la próxima!

Publicado en Desarrollo web, yii | Etiquetado , , , , , , | 2 comentarios

Relaciones entre entidades: Parte I

Hola a todos! Hoy os traigo la primera de dos partes en las que he dividido esta nueva entrada acerca del desarrollo de aplicaciones con Yii Framework. En ellas veremos cómo se establecen relaciones entre dos entidades del modelo, es decir, dos clases ubicadas en la carpeta models y que representan una entidad de nuestro modelo.

Vamos a continuar ampliando las funcionalidades del proyecto basic con el que venimos trabajando en entradas anteriores como Yii Framework: Gii, al cual vamos a añadir un par de clases nuevas (País y Ciudad) que nos permitan aportar más información sobre los usuarios que se registran en nuestro sistema.

Entorno de desarrollo

  • OS X Yosemite (10.10.3) – SSOO
  • MAMP (3.2.1) (PHP 5,6,7, MySQL 5.0.11-dev y Apache 2.2.29) – Lenguaje, Servidor y gestor de bases de datos).
  • Sublime Text (3) – Editor de texto
  • Yii Framework (2.0.4) – Framework de desarrollo PHP
  • Composer (1.0-dev) – Gestor de dependencias para PHP

Un rápido repaso

En el último post conocimos una herramienta fantástica que Yii Framework provee para la generación automática del código de nuestras clases del modelo, la vista y el controlador a través de un sencillo e intuitivo asistente: Gii.

Con esta herramienta generamos una sencilla administración que nos permite realizar las operaciones CRUD de los usuarios registrados en el sistema y además trabajamos sobre el comportamiento de algunos campos para darle un poco de coherencia a la creación de usuario en el sistema.

Por dónde empezamos?

Vamos a construir las clases País (Country.php) y Ciudad (City.php) y a dotarles de sus secciones de administración correspondientes igual que hicimos con la clase User. Para ello pondremos en práctica los conocimientos aprendidos en la entrada anterior sobre Gii, pero antes que nada necesitamos construir las tablas de la BBDD que representarán esas dos entidades. Os dejo el código SQL para que lo lancéis contra vuestro esquema del proyecto basic (en mi caso lo llamé yii2basic) y así agilizamos el trabajo:

--
-- Estructura de tabla para la tabla `country`
--
CREATE TABLE `country` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`create_at` timestamp NOT NULL,
`update_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Estructura de tabla para la tabla `city`
--
CREATE TABLE `city` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`country_id` int(11) NOT NULL,
`create_at` timestamp NOT NULL,
`update_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Sobre el código SQL anterior, comentar dos cosas:

  1. Desde hace tiempo sigo la buena práctica de aportar un sistema para auditar la información de las tablas de la BBDD de manera que añadiendo los campos de tipo fecha (create_at y update_at) puedo conocer cuándo se dan de alta y se modifican los registro.
  2. En la tabla city he añadido un campo country_id que nos permitirá definir la relación entre ciudad y país estableciendo que: una ciudad pertenece a un país y un país puede contener varias ciudades.

Hecho esto vamos a nuestro navegador para construir las clases del modelo la vista y el controlador a través de Gii. Os pongo el ejemplo de country y os dejo a vosotros el ejercicio de crear el código para la clase city:

Primero el modelo:

yiirelationships1

A continuación el controlador y las vistas:

yiirelationships2

Ahora veamos cómo queda la estructura del proyecto:

yiirelationships3

Ahora vamos a establecer la relación entre País y Ciudad, de manera que cuando consultemos una país obtengamos el nombre de la ciudad en lugar del identificador. Para ello podemos optar por dos vías: implementar nosotros el código o hacer uso de Gii.

En ambos casos el resultado será el mismo y al final lo que veremos en nuestro proyecto será código php añadido en ambas clases, por lo que para conocer la diferencia entre elegir una u otra vía voy a optar por apoyarme en Gii para generar la relación. Para ello seguimos estos pasos:

1. Desde nuestro phpmyadmin, examinamos la tabla city y creamos un índice de la columna country_id para que nos permite a continuación crear la relación:

yiirelationships4

2. A continuación, clicamos sobre la opción Relation View:

yiirelationships5

3. Creamos la relación con la tabla country:

yiirelationships6

4. Desde nuestro navegador volvemos a generar la clase del modelo city, donde, esta vez, Gii nos propone añadir ciertos cambios al código del que ya disponemos:

yiirelationships7

5. Aceptamos y realizamos la misma operación con la clase Country:

yiirelationships8

¡OJO! Recordad que hay que marcar el check junto a la acción overwrite para que sobre escriba o los cambios no serán efectivos.

Pero todo esto funciona?

Bien! Si ya tenemos todo, vamos a ver cómo queda nuestra interfaz de usuario desde la que podemos administrar las entidades del modelo:

País (http://localhost:8888/basic/web/index.php?r=country)

yiirelationships9

Ciudad (http://localhost:8888/basic/web/index.php?r=city)

yiirelationships10

A continuación vamos a crear un par de países y luego un par de ciudades por cada uno para ver si realmente todo queda registrado en nuestra BBDD y disponible para su administración. Vamos con los países:

yiirelationships11

Parece que hemos encontrado un obstáculo en el camino puesto que el formulario de creación de países nos está solicitando introducir un valor para dos campos de tipo fecha en formato texto. La opción ideal en este caso es omitirlos en el formulario ya que es algo que debería almacenarse de forma automática y no manual para que así podamos conocer cuándo han sido creados y cuándo fue la última vez que se modificaron.

Vamos a poner en práctica algo que ya aprendimos en la entrada anterior y vamos a modificar el fichero views/country/_form.php eliminando estos dos campos ara realizar altas de forma sencilla introduciendo únicamente el nombre. Además vamos a aprovechar y hacemos lo mismo con el fichero views/city/_form.php. Quedarían así:

yiirelationships12

De manera que cuando ahora demos de alta un país y nos pida solo el nombre el resultado que esperaremos será similar a este:

yiirelationships13

Vamos a crear un par de ciudades por cada país:

yiirelationships14

Ahora mismo, tal y como el código se ha generado por Gii, tenemos recordar los identificadores de los países con los que queremos asociar las ciudades que vamos creando pero en la siguiente entrada os explicaré de qué forma podemos resolver esto mostrándole al usuario un campo desplegable desde el que elegir el país al que quieren asociar la ciudad. El resultado debe quedar parecido a este:

yiirelationships15

Estos son los países que yo he creado y de forma similar deben verse los vuestros:

yiirelationships16

Y estas son las ciudades:

yiirelationships17

Como veis en el listado de ciudades aparece el identificador del país al que pertenecen y esto no es intuitivo para el usuario, así que como indicaba anteriormente, será el primer tema que abordaremos en la segunda parte de nuestra entrada acerca de Yii y las relaciones entre entidades.

En cuanto al código del proyecto, como siempre os dejo en este repositorio un tag desde donde descargarlo para que podáis utilizarlo como referencia o como plantilla para vuestros proyectos. Fijáis que en la carpeta data he colocado el export del esquema de BBDD.

Hasta la próxima!

Publicado en Desarrollo web, yii | Etiquetado , , , , , | 1 Comentario

Yii Framework: Gii

Buenas de nuevo!

Continuando con la entrada anterior hoy voy a explicaros un poco más sobre Yii, concretamente sobre una herramienta muy potente que el framework nos proporciona para agilizar el desarrollo de nuestras aplicaciones. Se trata de Gii, un potente generador de código que, mediante un asistente nos guiará para que podamos crear nuestras clases del modelo, la vista y el controlador sin picar ninguna línea de código.

Para ello vamos a continuar complementando nuestro proyecto basic por lo que os recomiendo que antes de continuar leyendo este post echéis un ojo al anterior: Yii Framework: mi primer proyecto).

Entorno de desarrollo

  • OS X Yosemite (10.10.3) – SSOO
  • MAMP (3.2.1) (PHP 5,6,7, MySQL 5.0.11-dev y Apache 2.2.29) – Lenguaje, Servidor y gestor de bases de datos).
  • Sublime Text (3) – Editor de texto
  • Yii Framework (2.0.4) – Framework de desarrollo PHP
  • Composer (1.0-dev) – Gestor de dependencias para PHP

Dónde nos quedamos?

En la anterior entrada creamos un proyecto basado en la plantilla básica y lo bautizamos como “basic“. Este proyecto traía implementado un sistema de login “ficticio” para los usuarios y por lo tanto decidí tratar los pasos para añadirle un mecanismo de autenticación que atacase a una BBDD, así como un formulario de alta de usuarios que permitiese acercarnos más a una aplicación web real. Para ello reutilicé el código generado por otro proyecto, limpio y desde cero, creado a partir de la plantilla avanzada.

La estructura de carpetas que obtuvimos al final quedó de la siguiente forma:

gii1

Como vemos disponemos de una carpeta que identifica las 3 partes del patrón MVC en el que se basan las aplicaciones desarrolladas con Yii: models, views, controllers.

Dentro de models se encuentra la clase User (dada por el fichero User.php), sobre la que trabajaremos en este post.

Primeros pasos con Gii

Si desde nuestro navegador introducimos la siguiente URL (atentos al puerto que hayáis definido vosotros, el mío es el que trae establece por defecto mamp – 8888): http://localhost:8888/basic/web/index.php?r=gii debe aparecernos la siguiente web:

gii2

Si os fijáis en la URL, hemos introducido el parámetro “r” para indicar dónde queremos dirigirnos, esto también podemos hacerlo para el resto de páginas que vayamos creando en nuestra aplicación, por ejemplo:

Vamos con Gii! Primero vamos a ver la opción Model Generator desde la cual se realiza el mapeo de las tablas que están en nuestra base de datos a las clases (.php) que representan nuestro modelo, como es el caso de User. En este caso ya disponemos de un archivo que representa nuestra clase, pero si no existiese, Gii lo generaría y en su contenido escribiría todo el código necesario para establecer el mapeo.

Y os preguntaréis… ¿Qué ocurre si el fichero ya está generado? pues aquí viene un poco de la magia de esta herramienta. Fijaos en la siguiente imagen, cuando introducimos los valores de los campos que solicita:

gii3

Gii nos indica que puede sobre escribir (overwrite) el archivo que ya existe en nuestro proyecto (models/User.php) introduciendo una serie de cambios (diff). Si clicamos sobre diff vemos que gii dispone de un comparador de código similar al que traen las herramientas de versionado de código, donde podemos ver (marcado en verde) qué nos propone Gii añadir y qué quitar (en rojo):

gii4

Yo también quiero generar código con Gii!

Para que podamos experimentar  con Gii y veamos que realmente funciona vamos a generar una parte muy interesante de nuestro proyecto como es la administración de los usuarios registrados que hasta ahora solo podíamos consultar mediante phpmyadmin  o el gestor de BBDD que utilicéis.

Para ello vamos a la segunda opción que marqué: CRUD Generator. Como ya habréis deducido, esta opción nos permite generar las opciones de Lectura (Create), Consulta (Read), Actualización (Update) y Borrado (Delete):

gii5

Como se observa en la imagen, además del controlador donde se definen los métodos CRUD de los usuarios, también se generan las vistas desde las que se invocan estos métodos. Si abrimos el fichero del controlador encontramos métodos como:

public function actionIndex() {...}

public function actionView($id) {...}

public function actionCreate() {...}

public function actionUpdate($id) {...}

public function actionDelete($id) {...}

Estos métodos son invocados desde las vistas para realizar las operaciones CRUD contra la tabla User y por supuesto son libres de modificar en base a nuestras necesidades. Pulsemos “Generate” para que Gii autogenere nuestro código:

gii6

A partir de ahora podemos visualizar los usuarios dados de alta en la base de datos y administrarlos de forma visual e intuitiva desde nuestra aplicación web, con solo acceder a la URL: http://localhost:8888/basic/web/index.php?r=user

gii7

En cuanto a los ficheros de las views, destacar que, el fichero con nombre _form es el que representa el formulario base con el que se construyen los formularios de creación (create.php) y actualización (update.php) de manera que si queremos, por ejemplo, mostrar la información de forma distinta a la hora de crear un usuario que al darlo de alta pero utilizando los mismos campos, deberíamos modificar los ficheros create y update y si lo que queremos que que cuando demos de alta o editemos la información de un usuario nos solicite un campo concreto, debemos incluirlo dentro el fichero _form. Veamos su contenido para realizar un ejemplo:

gii8

Si desde nuestro navegador accedemos a la URL: http://localhost:8888/basic/web/index.php?r=user%2Fcreate o bien pulsamos sobre el botón “Create user” vemos que lo que genera el código anterior es un único campo con el que dar de alta al usuario y esto no es muy práctico porque como mínimo un nombre de usuario y un password deberíamos poder crear ya que son los datos básicos para la autenticación, así que vamos a añadir estos y un campo email en el archivo _form.php antes del campo status. Si volvemos al navegador y refrescamos (Ctrl+R) vemos nuestros 3 nuevos campos listos para recoger los datos del usuario que vamos a crear:

gii9

Es más, si editamos el usuario que ya teníamos creado inicialmente vemos que también aparecen estos campos:

gii10

Y como decíamos, si queremos podemos aportar comportamientos distintos entre los formularios de creación y actualización, por ejemplo, como hemos hecho aquí, donde hemos incluido el campo “created_at” para indicar la fecha de creación del usuario. Para ello he modificado el código del fichero update.php eliminando la renderización del fichero _form .php y añadiendo directamente el contenido de este último fichero mas el campo “created_at”. Lo vemos a continuación:

gii11

Probando el código

Vamos a dar de alta un usuario en el sistema a través de la administración:

gii12

El resultado que debe mostraros es el siguiente:

gii13

El sistema indica que se ha creado un nuevo usuario sin embargo…algo falla, ¡No aparecen todos los datos que habíamos introducido! Aunque el status si lo ha registrado ¿Dónde está la información correspondiente a”username”, “password_hash” y “email”? Si consultamos esto directamente en BBDD lo verificamos, se ha generado un nuevo registro pero sin estos datos:

gii14

Entonces… ¿No funciona?

Tal vez alguno de vosotros ya se ha dado cuenta de lo que ocurre o bien, sin darse cuenta, fue precavido y en el paso en el que hablábamos de la generación de las clases del modelo con Gii copió algunos de los cambios que proponía la herramienta, concretamente los que afectaban al método rules de la clase User:

gii15

Al aplicarnos, el código de la función sería algo así:

public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE,                     self::STATUS_DELETED]],
[['username', 'password_hash', 'email'], 'required'],
];
}

Si queréis investigar podéis incluir todo lo que propone Gii pero en mi caso solo he incluido la línea que afecta a los campos en cuestión:

[['username', 'password_hash', 'email'], ‘required’],

Con esto estamos definiendo una regla de validación, concretamente required, para los campos username, password_hash email de manera que, se obliga al usuario que rellena el formulario a introducir estos valores. Veamos que ocurre cuando volvemos a crear un nuevo usuario tras añadir nuestras líneas de código:

gii16

Como vemos esta vez si hemos podido crear nuestro usuario con los datos completos. Y ahora os preguntaréis… Y ¿Qué ocurre cuando tenemos campos opcionales y por tanto que puedan dejarse en blanco? Vamos con un ejemplo, seguid estos dos pasos:

  1. Desde phpmyadmin, localizad vuestra tabla usuario de la BBDD y modificad el campo email para que permita valores nulos.
  2. Modificad la última línea que añadimos para que el campo email no sea required:

[['username', 'password_hash'], ‘required’],

Si damos de alta un tercer usuario vemos que el campo email, de nuevo no aparece registrado ¿Cierto? Pues bien, vamos a utilizar la herramienta de Yii para depurar el código php que vamos ejecutando. Para ello pulsamos sobre la opción LOG de la barra inferior desde el navegador:

gii17

Y a continuación vemos los mensajes generados entre los cuales debéis encontrar uno similar al que aparece en la siguiente imagen:

gii18

Dabo el mensaje Falied to set unsafe attribute ’email’ in ‘app\models\User vemos que se indica la línea 65 del fichero UserController.php donde se produce el error. Si lo abrimos vemos que en esa línea el código es el siguiente:

if ($model->load(Yii::$app->request->post()) && $model->save()) {...}

En resumen todo esto se explica porque Yii, por defecto tiene predefinido un mecanismo de seguridad que prevee que se introduzcan valores vacíos en nuestra BBDD que puedan generar inconsistencias o problemas en otras zonas de la web donde se haga uso de ellos. De manera que mientras no indiquemos en algún sitio de nuestro que en nuestro modelo existen campos que deben ser almacenados INCLUSO CUANDO EL VALOR INTRODUCIDO ES VACÍO, Yii no nos permitirá guardar la información relativa a estos campos.

Para eso Yii nos provee de un tipo de validación llamada safe, con lo que nuestro problema queda resuelto tras añadirla a la función rules. Veamos cómo queda el código:

gii19

Bien! Pues para finalizar, vamos a ver qué ocurre ahora si introducimos el email a la hora de crear un usuario:

gii20

Vemos que estoy introduciendo el email, aunque podría dejarlo vacío si quisiese ya que ya no es un campo required en mi modelo. Y el resultado es el siguiente:

gii21

Y hasta aquí el post de hoy. Como siempre, os dejo el código del proyecto en este repositorio y os invito a que experimentéis con los campos de vuestro modelo y a que creéis campos nuevos que permitan crear una entidad Usuario en base a las necesidades de vuestro proyecto. Eso sí! Acordáis de incluir los nuevos campos en la BBDD también.

Un saludo!

Publicado en Desarrollo web, yii | Etiquetado , , , , , | 3 comentarios

Yii Framework: mi primer proyecto

Sobre Yii

Tras un periodo de inactividad he decido retomar el blog para hablaros de mi experiencia con una herramienta de trabajo que a los desarrolladores y sobre todo a los phperos les puede resultar muy interesante. Hablo de Yii Framework , un framework orientado a objetos para el desarrollo de aplicaciones web con php.

logo_yii

Algunas de las características que argumentan su uso y que por el momento me han aportado hasta el momento me parecen interesantes destacar se encuentran:

Mi experiencia con este framework se basa en la versión 2, que fue publicada oficialmente en Octubre del año pasado (Ver Historia de versiones) y para iniciarme comencé de la forma que considero más indicada para cualquier tipo de herramienta de este tipo: leyendo la documentación oficial (Guía Yii 2.0).

Qué os cuento hoy?

En el post de hoy hablaré de cómo crear nuestro primer proyecto con Yii y explicaré un poco sobre la estructura de carpetas para que podamos a continuación tratar un escenario muy común en las aplicaciones web: la autenticación de usuarios.

Antes de comenzar quiero mencionar que para desarrollar este proyecto me basé en la gúia 2.0 de la documentación oficial de Yii (http://www.yiiframework.com/doc-2.0/index.html) y en el post Autenticación y autorización básica en Yii 2 (http://yii2enespanol.com/2015/04/09/autenticacion-y-autorizacion-basica-en-yii-2/) escrito por vihugarcia, donde se trabaja con un proyecto creado con la plantilla avanzada de Yii que más adelante explicaremos.

Entorno de desarrollo

  • OS X Yosemite (10.10.3) – SSOO
  • MAMP (3.2.1) (PHP 5,6,7, MySQL 5.0.11-dev y Apache 2.2.29) – Lenguaje, Servidor y gestor de bases de datos).
  • Sublime Text (3) – Editor de texto
  • Yii Framework (2.0.4) – Framework de desarrollo PHP
  • Composer (1.0-dev) – Gestor de dependencias para PHP

Creando el proyecto

Teniendo en cuenta que tenemos instalados los requisitos comentados en el punto anterior, desde el terminal o la línea de comandos si estáis en Windows nos colocamos en la ruta:

iMac-de-Vicente:/ vicmonmena$ cd Applications/MAMP/htdocs/

Y desde aquí introducimos lo siguiente:

composer create-project --prefer-dist yiisoft/yii2-app-basic basic

yii_helloworld_1

Con estos estaremos creando un proyecto llamado “basic” con la estructura de carpetas generada con la plantilla básica de Yii (yii-app-basic). La estructura de carpetas generada es la siguiente:

yii_helloworld_2

En ella he señalado varios elementos que interesa conocer para qué sirven:

  • basic, es la carpeta contenedora de todo el proyecto, y por la que nuestra URL, a priori, estará formada.
  • config, contiene ficheros de configuración donde se definen los parámetros de conexión con la base de datos (db.php) o de la propia aplicación web (we.php)
  • models y controllers, contienen las clases que representan el modelo y los controladores respectivamente.
  • views, contiene los ficheros que general la interfaz de usuario de la aplicación
  • composer.json, es el fichero que utiliza el gestor de dependencias (composer).

La plantilla avanzada

Como comentamos al inicio del post, la alternativa a la plantilla básica que hemos usado aquí es la que utiliza vihugarcia en su post: la plantilla avanzada con la que se generaría un proyecto con la siguiente estructura de carpetas:

yii_helloworld_3

La principal diferencia es que con la plantilla avanzada el backend se independiza del frontend, permitiendo que el primero pueda ser reutilizado por varias aplicaciones (Podéis leer más aquí).

Pero quiero ver algo en mi navegador!

A partir de este momento ya podemos acceder a nuestra aplicación web desde el navegador para ver el resultado generado cuando creamos el proyecto Yii basado en la plantilla básica. Para ello introducimos en nuestro navegador la URL: http://localhost:8888/basic/web/ que nos muestra la Home de nuestra web:

yii_helloworld_4

Una vez hayáis navegado un poco por el sitio web habréis podido observar que, por un lado en la zona inferior disponemos de la barra de depuración de Yii o Yii Debbuger desde la que podemos acceder a múltiples herramientas que nos ayudarán durante el desarrollo; y por otro lado, disponemos de un sistema de autenticación de usuarios con un formulario de Login ya implementado y disponible para su uso desde la ULR http://localhost:8888/basic/web/index.php?r=site%2Flogin:

yii_helloworld_5

Aunque parezca que ya está todo hecho para que podamos trabajar con nuestros usuarios y nuestra base de datos, esto no es más que un “cartón-piedra”, es decir, la autenticación no se realiza contra la BBDD y tampoco existen más usuarios que los que están hardcodeados en el fichero basic/models/User.php:

yii_helloworld_6

Don’t worry! Para eso escribo este post. Aquí vamos a desarrollar la parte de autenticación de usuarios contra la BBDD además de la inclusión de roles que nos permitan definir a qué zona de la web tiene acceso cada usuario.

Modelo-Vista-Controlador

Para continuar implementando código entendiendo lo que hacemos, debemos conocer cómo se aplicar este patrón en Yii.

Por defecto el fichero SiteController.php que se ha auto-generado es el controlador de todas las vista creadas dentro del paquete basic/views/site, por ejemplo:

Cuando hacemos clic sobre el link “about” estamos llamando a la URL http://localhost:8888/basic/web/index.php?r=site%2Fabout lo que se traduce en invocar a la acción actionAbout dentro de la clase SiteController.php quien en este caso renderiza el fichero basic/views/site/about.php para que sea dispuesto por el navegador:

public function actionAbout() {
    return $this->render('about'); 
}

Otro caso, donde las clases del modelo entran en juego, sería pulsar en “Login” desde el formulario de login para identificarnos en el sistema, con lo que estaríamos invocando la siguiente función del controlador SiteController:

yii_helloworld_7

Como vemos primero se valida si el usuario ya estaba previamente logado:

Yii::$app->user->isGuest

Y si no es el caso se recogen los datos del formulario de login (LoginForm) y se validan las credenciales mediante la llamada a la función login:

yii_helloworld_8

Como vemos se produce la interacción Controlador – Modelo y Controlador – Vista.
Reutilizando

Uno de los principales conceptos que aprendemos los programadores es el de la reutilización del código. Cuántas veces hemos escuchado eso de:

utiliza lo que ya este hecho y que sepas que funcione para ahorrar tiempo en tus desarrollos…

Es por ello que siendo fieles a este concepto vamos a utilizar trozos de un proyecto de la plantilla avanzada para adaptarlo a nuestro código y no tener que programar de nuevo todo el código referente a la autenticación de usuarios.

Resulta que, si habéis sido curiosos y habéis creado un proyecto con la plantilla avanzada como se comentaba más arriba, os habréis fijado que, según la guía oficial, hay un paso en el que se genera la base de datos del proyecto con la que se va a trabajar (leed el apartado Getting started de la guía).
Pues con nuestro proyecto vamos a hacer lo mismo, es decir, vamos a aprovechar la parte del proyecto con la plantilla avanzada y la vamos a incluir dentro de nuestro proyecto para disponer de un sistema de autenticación y una BBDD lista para funcionar:
El primer paso es disponer de un proyecto con la plantilla avanzada, para lo cual ejecutamos lo siguiente en consola:

composer create-project --prefer-dist yiisoft/yii2-app-advanced yii-application

Para crear la BBDD, desde la línea de comandos nos situamos en la carpeta raíz de nuestro proyecto y ejecutamos el comando:

yii migrate/create init_user

yii_helloworld_9
Como vemos, se ha generado un archivo nuevo (m150613_150726_init_user.php) y una carpeta nueva (migrations) dentro del proyecto. Este fichero sirve para generar todo el esquema de BBDD, incluso si lo deseamos, con registros ya creados en nuestras tablas (para más detalles podemos consultar la guía oficial).

Comencemos a reutilizar! Para ello primero localizamos dentro del proyecto de la plantilla avanzada (yii-application) el archivo de migración con nombre similar al que acabamos de crear, concretamente en la ruta yii-application/console/migrations/ y copiamos las funciones “up” y “down” en nuestro fichero de migración:

yii_helloworld_10

A continuación vamos a configurar nuestro proyecto para que se conecte con la base de datos. Para ello abrimos el fichero basic/config/db.php donde definimos los parámetros de usuario, password y nombre del esquema que vayamos a utilizar. Si aún no habéis creado el esquema ¡Esto es lo primero! Acceded a vuestro phpmyadmin y creadlo.
Seguidamente nos dirigimos a la consola e introducimos el comando:

yii migrate

Ojo! Si os da un error de conexión con la BBDD similar a este:

yii_helloworld_11

Debéis cambiar la cadena de conexión del fichero db.php para poner la siguiente:

'dsn' => 'mysql:host=localhost;port=8889;dbname=yii2basic;unix_socket=/Applications/MAMP/tmp/mysql/mysql.sock'

Si todo ha ido bien entonces debe quedaros un resultado similar a este:

yii_helloworld_12

De manera que cuando vayamos a nuestro phpmyadmin veremos que el esquema que creamos (en mi caso he dejado el de por defecto “yii2basic”) ya no está vacío y que contiene una tabla llamada “migrations” que crea Yii automáticamente y la tabla que nos interesa y que definimos en el script “user”:

yii_helloworld_13

El segundo paso en este proceso de reutilización está relacionado con el código PHP del proyecto. Vamos a copiar las clases y las vistas del proyecto yii-application (el de la plantilla avanzada) en nuestro proyecto para que la autenticación se realice contra la tabla “user” de la base de datos.
En la siguiente imagen marco los ficheros que he copiado a mi proyecto, donde como vemos en algunos casos que se trata de ficheros que no existían previamente, como puede ser SignupForm.php y otros que si como SiteController.php:

yii_helloworld_14
Una vez copiado todo el código debemos corregir las rutas a las que se hacen referencia para que vayan acorde con la estructura de carpetas de un proyecto basado en la plantilla básica.
Por ejemplo, en la clase SiteController, donde ponga “frontend” y common” debemos colocar la palabra “app”, es decir:

namespace frontend\controllers; ===> namespace app\controllers;

use common\models\LoginForm; ===> use app\models\LoginForm;

Una vez terminamos ya podríamos realizar el login en la aplicación que autenticaría nuestro usuario contra la base de datos, accediendo a la URL: http://localhost:8888/basic/web/index.php?r=site%2Flogin

Sin embargo, en ningún momento hemos creado un usuario y por tanto nuestra tabla “user” está vacía. Así que vamos a facilitar a los usuarios una vía para poder registrarse en nuestra aplicación y para ello vamos a modificar el código de una de nuestras vistas, concretamente basic/views/login.php, de la siguiente forma:
Cambiamos la línea:

If you forgot your password you can .

Por lo siguiente:

Sign up or if you forgot your password you can .

Ahora cuando accedamos al formulario de login encontraremos un link al formulario de alta de usuarios:

yii_helloworld_15

Desde este momento podemos darnos de alta:

yii_helloworld_16

Y a continuación identificarnos en el sistema:

yii_helloworld_17

Si visualizamos el contenido de la tabla “user” vemos que se ha generado un nuevo registro:

yii_helloworld_18

Y hasta aquí por hoy que no es poco!
Os dejo el código de este proyecto publicado en github por si queréis descargarlo. En el próximo post abordaremos el tema de la autorización, es decir, definiremos una serie de roles y reglas que determinarán el acceso a las distintas zonas de la web.
Un saludo y espero que os sea de utilidad!!

Publicado en Desarrollo web, yii | Etiquetado , , , , , | 2 comentarios

Apache Barcamp Spain 2012

Este año se celebra por segunda vez en Sevilla uno de esos eventos “frikis” como calificarían la mayoría de personas. La Apache Barcamp Spain.

El objetivo del evento es uno de los muchos factores que hace que sea tan “atracativo” y de gran interés para la comunidad: aprender, divertirse, compartir, conocer gente y supongo que alguna que otra cerveza caerá :)

Como podéis leer en el enlace anterior el año pasado fue un exitazo por lo que éste las entradas han volado, si aún te animas creo que @recena comentaba algo por Twitter sobre una persona que vendía su entrada por que no podía ir, así que date prisa.

Por mi parte, este año junto con mi compañero Álvaro Aroca decidimos no solo asistir sino que ya que vamos, podíamos contribuir con algo y de paso aprender, así que nos decantamos por hacer una aplicación para dispositivos móviles (el iOS y yo Android) para poder consultar en directo las noticias del evento, información relacionada y el horario, las ponencias y los ponentes que ese día intervendrán. Y así pues, de eso y unos cuantos guantazos con mi Eclipse y mi Java del alma nació la aplicación barcamp app que espero que os guste y que os podéis descargar en Google Play.

Y… ¿Por qué una aplicación solo para un evento? pues porque esta es mi manera de decir que esto es lo que puedo aportar por ahora según mis conocimientos y porque me motivaba el hecho de poder aprender y profundizar en el desarrollo con Android y hacer algo por mi cuenta según mis criterios, gustos y métodos, aunque haya ido de forma paralela a la aplicación que ha hecho Álvaro para iOS.

En cuanto a los detalles técnicos de la aplicación comentar que es una aplicación desarrollada en Android nativo y a parte del código que he picado he incluido algunos componentes y me he apoyado en fuentes que me gustaría mencionar ya que sin ellos hubiese sido un coste bastante mayor:

  • La pantalla de Noticias donde aparece el listado de noticias leído desde la web de la Apache Barcamp Spain contiene un componente que me mola un montón y que os será familiar a todos lo que uséis Twitter. Este es el PullToRefresh 4 Android que permite actualizar el listado arrastrándolo hacia abajo.
  • En cuanto al listado de tracks decidimos incluir una vista por cada track y para ello añadí el componente HorizontalPagerWithPageControl que permite desplazar la pantalla horizontalmente con el dedo para ver diferentes vistas.
  • He incluido además esta librería para la lectura de los RSS de la web de la Apache Barcamp Spain.

En cuanto al resto destacar componentes de que ofrece el SDK de Android y que he aprendido a manejar un poco mejor tras hacer esta aplicación:

Las AsyncTask para la carga asíncrona de información, los WebView utilizados en las pestañas de Headquarters y Detalles de Noticias para la carga de contenido HTML con el que el usuario pueda interactuar o la clase ArrayAdapter de la que he extendido en 2 ocasiones para poder personalizar los registros que aparecen en el Listado de Noticias y en el de Tracks.

En cuanto a los recursos, los iconos los he sacado de la web de iconmonster y por supuesto! como no! he tenido que recurrir alguna que otra vez al más que conocido Stackoverflow.

Ah! Si queréis el código fuente de la aplicación aquí os dejo el repositorio de subversion donde está localizado. Y para cualquier duda, sugerencia o si queréis discutir sobre cómo hacer algo de lo que hay en la aplicación de forma más eficiente, no dudéis en poneros en contacto conmigo a través del blog, twitter o correo electrónico y por supuesto ¡¡EN EL EVENTO!!

Publicado en Android, General, iOS | Etiquetado | 1 Comentario

Introduction to BlackBerry development

Hi again!

Recently I’ve finished a Blackberry Development course and I’ve decided to share all the things that I’ve learned. This is the first of three post about Blackberry that I’m going to publish and during this post I’ll talk about:

  • How to work with Blackberry UI components.
  • How to work with data persistem system in Blackberry applications.
  • How to work with Networking in Blackberry application.

But first of all we have to configure and prepare our Integrated Development Environment (IDE). In that case we have chosen and, in fact! I recommend installing BlackBerry Plugin for Eclipse which allows you to work with Eclipse IDE within a BlackBerry Plugin.

First step is do click on Plugin for Eclipse link:

And the next one download the IDE:

When downloading would have finished unzip the folder in your local hard drive and you will see your folder like this:

Now is the moment to configure your IDE. Please do clic on eclipse.exe file and when it ask you about your workspace set the default work space or select any other. In my case, as you can see in that picture I’ve added one folder called workspace but this is not mandatory, I leave it in your hands (literal translation – I love it ;) it’s funny).

Well, we just need to configure two important things in our Eclipse:

  • BlackBerry SDK version that we are going to work: 7.0.0
  • Java Compiler Compliance Level: 1.3

So, go to Windows > Preferences > Java > Installed JREs and confirm if SDK 7.0.0 is checked:

Now go to Windows > Preferences > Java > Compiler and select 1.3 for Compiler Compliance level:

Ok! Now we are going to check if all is right to start our developments. We are going to make our first Blackberry project:

It works like other kind of plugins, first step is define our project name and our JRE:

Next one we have to set our project folder structure. In that case I just defined it by default:

And finally, and the most interesting is defininf our project type:

We are going to select the first option: BlackBerry Application. Don’t worry, I’ll explain the other options and which is better depending on projects in later post. Now we just just go to make a test appplication to check if our IDE has been configured correctly. So, click next button and fill the form shows in that picture:

Here you could used your own best practices to define your application name and screen name, but in my case I’ve learned that is a really good practice to set names linked with the matter of the file. It is:

  • Application Class Name – It should finish with the word Application
  • Screen Class Name – It should finish with the word Screen and the first one could be called MainScreen because it represents first screen in our application which will be showed.

Ready? well! We just have to do click on Finish button and see that in our project explorer tab has appeared a new Blackberry project called HelloWorld:

And now we have to create a run configuration to launch our project. In that case you  just select you run configuration name, your project and your device:

As you can see in the picture, I’ve selected BlackBerry-SDK-9930 but it’s probably that you haven’t this device. Don’t mind my friend! You can download your favourite device or another device that you need here.

Did you select your project in project tab and your devide already? Ok! Do click in Apply and after in Run. Can you see the simulator like this picture?

Great! When this loading process is over the simulator shows you the main screen like a BlackBerry device. And here you can look for your application icon:

Come on! Don’t be afraid and push it and let’s see what it shows. Somehting like that?

Well done! This is your first BlackBerry application. Althought this is a little bit simple, in next post I’m going to show you some components and how to work with them and how to do our application more interesting.

Thanks to @larasith for him patience ;)

Publicado en BlackBerry | Etiquetado , , , , , , , | Deja un comentario

ADAFramework: How to work with relationships

In this post I’m going to talk about ADA Framework again, specifically about how to work with relationships. I’ve tried to publish it as soon as it was possible but It tooks me more than I thought because, as you can see, I decided to write it in English ;).

Well! Let’s begin at the biginning! ;)

Sources:

Development envirnomment information:

  • Windows 7 Home Premium 64bits.
  • Eclipse Indigo and ADT Plugin for Eclipse.
  • Android SDk 2.2 (min. sdk 8).
  • ADA Framework 1.4.5.
  • Tested on Samsung Galaxy ACE GT-S5830 con Android 2.3.5
  • SVN repository download: svn://svn.code.sf.net/p/rateyourmusic/code-0/trunk

Project package explorer:

In this case I’ve created an Android project related to music and to song rates. I’ve defined two concepts:

1.- We are going to work with two entities call Song and Album.

2.- One Song is linked to on Album neither one Album is linked to many Songs.

ADA Framework make our work with our relationships easier because we now we only have to give an Album entity to our Song entity. Look at this code:

The first one ir Song class and the second one is Album class and both extend from com.desandroid.framework.ada.Entity like always. As you can see we have defined our relationship using the “album” attribute of Album type and we have defined it as Entity.DATATYPE_ENTITY_REFERENCE. Now we can to start to work with our entities.

Like in previous post, we are going to create an entity manager that allows to work get information from database and to save, to update and to delete (CRUD operationes) data in database. This is ApplicationDataContext and it extends to com.desandroid.framework.ada.ObjectContext. Let’s see a bit of code:

It’s simple, isn’t it?. Look at the first piece of code. it contains two com.desandroid.framework.ada.ObjectSet attributes to manage our two entity types. They allows us to execute all CRUD operation wich ObjectSet class contains. Now, when we create a ApplicationDataContext instance ir our Activities we will have two structures to do INSERT, UPDATE, DELETE and SELECT (basic and complex) operations with Songs and Albums, and when we won’t do anything special if we will go to save a song with a album or a position or a name, that’s the same.

Now we are going to talk about Activity classes in the project. I’ve created two activities.

1.- HomeActivity: Allows to list all songs with this format: POSITION .- SONG NAME (RATING) .

2.- SongDetails: Allows to create a new activity or to vote for songs.

I’m going to talk only about the most important in this classes, but if you have doubts, suggestions or corrections you just write your comment ;).

As we haven’t songs and albums initially, when we run the frrist time it found that database is empty and makes several songs and albums and their relationships. For next times load ones and it doesn’t create again.

* Take a loot at initializedDatabase() method in project source code if you don’t understand what it does.

As you can see, HomeActivity is our ListView component to show songs and it contains an ArrayAdapter to magane songs and to put into the ListView. Too, it have an ApplicationDataContext attribute to get songs from database executing dataContext.getSongSet().fill() line code.

At the end of onCreate method we define the same adapter for song records in database and in ListView. Yes! This seems weird but is the way to define the relationship between database and Activity classes.

What happen when I do click in a lisview item?… Well it shows you detailed information about that item (Song) that allows you to vote for songs.

We have two options, as I said, vote for a song (onListItemClick overrided method) or, if you want to create a new song, press your menu device menu button (onOptionItemSelected overrided method). In the second one you can see that we passing parameters bettween Activities with intent.putExtra(ARGUMENT_NAME,ARGUMENT_VALUE), with SONG_ID. It allows to find this song in database to load it in SongDetails Activity.

One more thing about HomeActivity class! To refresh that ListView when we update it I’ve overrided onResume method, and I’d like to know your opinion about that. Do you know another ways to do that? How do you usually do that?

Now we are going to look at SongDetails Activity.

SongDetails activity detects if we want to create or not to create a song checking if we have passed SONG_ID parameter from HomeActivity.

If we want to create a song, we load albums from database into Spinner component (loadAlbumsSpinner method) and set form field as Editable state:

Press on album spinner:

Else, we search in database the song clicked in HomeActivity ListView and load her detailed information (loadInformation method) :

Finally when we do click in vote button vote method is executed:

And it execute one of two queries using the same method dataContext.getSongsSet().save(SONG_OBJECT):

1.- INSERT INTO ‘tSong’: Put  attention on  song.setAlbum((Album) spinner.getSelecteditem())!! We are creating our relashionship between Song and Album as if only was a simple data type like String, int, boolean, etc. 

2.- UPDATE TABLE ‘tSong’: Put attention on song.setStatus.(Entity.STATUS_UPDATED), because if you don’t change that property ADA Framework won’t do anything and your changes won’t be saved.

Fill the form and press on vote spinner:



Now it’s your turn! Press device menu button whe you are showing any song details ;)

My most sincere thanks for @DesAndrOId

Publicado en Android | Etiquetado , , , , | 4 comentarios