1

DataMapper: Object Relational Mapper en CodeIgniter

 

¿Qué vamos a necesitar?

1.- CodeIgniter (Este tutorial trata sobre la versión 1.7.3)
2.- DataMapper (1.8.0 es la más actual, en el momento de escribir este tutorial)

La instalación de CodeIgniter es muy sencilla, como ya vimos en el anterior tutorial. Para añadir DataMapper al proyecto, simplemente tenemos que copiar el contenido del directorio “application” dentro del directorio “system/application” de nuestro CodeIgniter.

Configuración

Si todo ha ido bien, deberíamos poder configurar DataMapper editando el fichero “system/application/config/datamapper.php”. En general, aunque dependiendo de la estructura de tu base de datos, para lo único que necesitas editar este fichero es para añadir las extensiones que queramos utilizar, ya hablaremos más adelante de esto. En cualquier caso, si tienes dudas, la documentación ofrece una tabla con la descripción de todos los parámetros de configuración.

ESTRUCTURA DE LA BASE DE DATOS

En este ejemplo vamos a dar los primeros pasos para crear un juego de rol, así que los modelos que vamos a necesitar en la base de datos serían:

· Usuarios ( users: id, username, password, created, updated )
· Personajes ( players: id, name, life, created, updated )
· Clases de personajes ( characters: id, name, created, updated )
· Objetos que llevan los personajes ( items: id, name, quantity, created, updated )

Aunque se puede configurar de otra manera a la hora de preparar el modelo de CodeIgniter, por defecto debemos escribir el nombre de las tablas de la base de datos en el plural del inglés. Básicamente hay que añadirle una s al final de la palabra, salvo las excepciones en las que terminan en y. Por ejemplo para el modelo pony, el nombre de la tabla sería ponies.

TABLAS INTERMEDIAS PARA LAS RELACIONES

DataMapper permite relaciones del tipo One to OneOne to Many y Many to Many.

En nuestro juego, cada usuario puede tener un personaje (One to One), a su vez, un personaje sólo puede ser de un tipo (One to One). Sin embargo, un personaje puede llevar muchos objetos (One to Many).

Todas estas relaciones necesitan sus tablas en la base de datos, con esta estructura:

· players_users: id, player_id, user_id, created, updated
· characters_players: id, character_id, player_id, created, updated
· items_players: id, item_id, player_id, created, updated

El nombre de la tabla sería, en orden alfabético y plural, los dos nombres de las tablas que queremos relacionar.

PREPARANDO LOS MODELOS EN CODEIGNITER

Ahora es cuando viene lo bueno de verdad, vamos a preparar los siguientes modelos en system/application/models:

User.php

  1. <?php
  2. class User extends DataMapper {
  3.     var $has_one = array(‘Player’);
  4. }

Un usuario nada más que puede tener un personaje.

Player.php

  1. <?php
  2. class Player extends DataMapper {
  3.     var $has_one = array(‘User’, ‘Character’);
  4.     var $has_many = array(‘Item’);
  5. }

Un personaje puede tener un único usuario y una única clase, pero puede tener muchos objetos.

Character.php

  1. <?php
  2. class Character extends DataMapper {
  3.     var $has_many = array(‘Player’);
  4. }

Una clase de personaje puede pertenecer a su vez a muchos personajes, esto nos sirve para listar todos los personajes de una clase concreta.

Item.php

  1. <?php
  2. class Item extends DataMapper {
  3.     var $has_one = array(‘Player’);
  4. }

En nuestro juego, los objetos son físicos y no pueden pertenecer a varios personajes al mismo tiempo, si quisiéramos extender el juego, lo suyo sería hacer también clases de objetos.

Te lo creas o no, esa es la configuración más básica de nuestros modelos de objeto, del resto se encarga DataMapper… ¿cuánto tiempo has ahorrado preparando los modelos? =)

Cosas a destacar:
– Los modelos extienden a DataMapper, en lugar de a Model.
– Si queremos especificarle el nombre de la tabla -> var $table = ‘tabla‘;
– Puedes consultar la documentación sobre la creación de modelos para ampliar información.

CONTROLADORES

Vamos a poner en acción esos modelos que hemos preparado para que veas el potencial. ¿Qué tal si creamos a nuestro primer usuario?:

  1. // Lo primero es cargar nuestro modelo y
  2. // crear una instancia del mismo
  3. $this->load->model(‘User’);
  4. $user = new $this->User();
  5. // Directamente le asignamos las variables
  6. $user->username = ‘piradoiv’;
  7. $user->password = md5(‘1234’);
  8. // Y lo guardamos en la base de datos
  9. $user->save();

DataMapper se encargará de establecer automáticamente los campos created y updated.

Vamos a practicar un poco más creando un par de tipos de personajes:

  1. $this->load->model(‘Character’);
  2. $barbarian = new $this->Character();
  3. $assassin = new $this->Character();
  4. $barbarian->name = ‘Bárbaro’;
  5. $assassin->name = ‘Asesina’;
  6. $barbarian->save();
  7. $assassin->save();

Ahora vamos a preparar las relaciones, con un jugador:

  1. // Voy a suponer que estamos en otro
  2. // controlador diferente, así que necesitamos
  3. // volver a cargar los modelos
  4. $this->load->model(‘User’);
  5. $this->load->model(‘Player’);
  6. $this->load->model(‘Character’);
  7. // Instanciamos los modelos
  8. $user = new User();
  9. $player = new Player();
  10. $character = new Character();
  11. // Usamos un poco de magia para
  12. // recuperar el usuario que habíamos
  13. // creado y a mi personaje favorito
  14. // del Diablo II, la asesina 😛
  15. $user->get_by_username(‘piradoiv’);
  16. $character->get_by_name(‘assassin’);
  17. // Ahora se lo vamos a asignar
  18. // a un personaje nuevo
  19. $player->name = ‘Pirado IV’;
  20. $player->save();
  21. // Para guardar relaciones, basta con
  22. // invocar el método save, pasándole
  23. // como parámetros los objetos
  24. // relacionados.
  25. $player->save(array($user, $character));

Como puedes ver, podemos hacer búsquedas con get_by_[u]field[/u]. Otra manera de hacer exactamente lo mismo sería:

  1. $user->get(‘username’, ‘piradoiv’);
  2. // Aprovechamos para actualizarle la
  3. // contraseña al usuario
  4. $user->password = md5(‘hoygan’);
  5. $user->save();

Como ves, save() también actualiza la base de datos.

GENERANDO LISTADOS

Otra de las típicas cosas que vamos a querer hacer, es generar listados de objetos, vamos a aprovechar la base de datos tal y como la tenemos para practicar:

  1. $characters = new Character();
  2. $characters->get();
  3. foreach($characters->all as $character) {
  4.     echo “$character->name<br />”;
  5. }

Si estás familiarizado con ActiveRecord, te sentirás a gusto filtrando y ordenando los listados:

  1. // Ordenar por ID descendiente
  2. $characters->order_by(‘id’, ‘desc’)->get();
  3. // O buscar con LIKE y limitar a un resultado
  4. $characters->like(‘character’, ‘assa’)->limit(1)->get();

Tienes todos los ejemplos en la documentación sobre el método Get

ACCEDIENDO A LAS RELACIONES

¡Casi se me olvida ponerlo!, para acceder a las relaciones basta con ejecutar un get(); en la propiedad a la que quieras acceder. Vamos a verlo con un ejemplo:

  1. // Cargamos el modelo del usuario,
  2. // los demás no nos van a hacer falta
  3. // porque vienen incluídos al acceder
  4. // a la relaciones.
  5. $this->load->model(‘User’);
  6. $user = new $this->User();
  7. $user->get_by_username(‘piradoiv’);
  8. // Cargamos nuestro personaje…
  9. $user->player->get();
  10. // Eso nos descargará únicamente los
  11. // jugadores que tengan relación con
  12. // ese usuario, vamos a descargarnos
  13. // todos los items que tiene este
  14. // usuario
  15. $items = $user->player->item;
  16. $items->get();
  17. foreach($items->all as $item) {
  18.     echo “$item->name<br />”;
  19. }

DOS COSITAS MÁS

DataMapper ha sido programado de manera que se le pueden crear extensiones de una manera sencilla.Entre otras, la versión actual incluye:

· Una extensión para generar arrays de tus objetos:

  1. $character->get_by_name(‘barbarian’);
  2. print_r($character->to_array());

· Importar y exportar objetos desde ficheros CSV

  1. $characters->get();
  2. $characters->csv_export(‘/fichero.csv’);

Tiene unas cuantas más, lo mejor es que le eches un ojo a la documentación. Lo que tienes que tener en cuenta es que para utilizar estas extensiones, debes añadirlas al fichero de configuración (system/application/config/datamapper.php):

  1. $config[‘extensions’] = array(‘array’, ‘json’, ‘csv’);

La otra cosa interesante de DataMapper es que funciona nativamente con las funciones de acceso a la base de datos de CodeIgniter, por lo que podremos utilizar el Profiler para encontrar cuellos de botella en nuestra aplicación. Si encontramos algo que necesitemos pulir, podemos optimizarlo al detalle con consultas directas ActiveRecord, SQL, …

¡CAMBIO Y CORTO!

Espero que este tutorial te haya servido de ayuda, ahora eres tú el que debes echarle un ojo en profundidad a la documentación.

http://datamapper.wanwizard.eu/

Y si aun así necesitas una mano, siempre estamos por #mv.nerd en Quakenet y #mvnerds en Twitter.

Fuente: mediavida.com

 

Leave a reply