Está en la página 1de 11

Universidad Nacional de San Agustn

Facultad de Ingeniera de Produccin y Servicios



Escuela Profesional de Ciencia de la Computacin




Tercer semestre

Curso
: Introduccin a Internet

Tema
: Doctrine (mapeador)


Presentado por las alumnas:

Escalante Calcina, Judith
Vargas Lazarte, Olenka
Cui: 20133438
Cui: 20111687


Arequipa Per

2014



















Introduccin
Doctrine es una mapeador de objetos-relacional (ORM) escrito en PHP que proporciona una capa de persistencia para
objetos de PHP. Es una capa de abstraccin que se sita justo encima de un SGBD.



Qu es Doctrine?

Doctrine es una librera para PHP que nos permite trabajar con un esquema de base de datos como si fuese un conjunto de
objetos, y no de tablas y registros. Introduccin a Object-Relational Mapping (ORM).
Doctrine est inspirado en Hibernate, que es uno de los ORM ms populares y grandes que existen y nos brinda una capa
de abstraccin de la base de datos muy completa. La caracterstica ms importante es que te da la posibilidad de escribir
consultas de base de datos en un lenguaje propio llamado Doctrine Query Language (DQL).






Antecedentes

El proyecto Doctrine empez con Konsta Vesterinen. Tambin conocido como zYne-. El 13 de Abril de 2006 se hizo el
primer envo al repositorio svn.
Doctrine tiene influencias de docenas de proyectos de personas muy diferentes. Las mayores influencias son de Hibernate
(el ORM de Java) y de ActiveRecord (de Ruby on Rails). Ambos tienen una implementacin completa tanto en Java como
en Ruby. El propsito de Doctrine es construir una solucin igual de potente para PHP.





Caractersticas principales

Doctrine es una librera muy completa y muy configurable, por lo que casi nos resulta complicado seleccionar que detalles
destacar. Os ponemos las caractersticas ms globales, ya que este tutorial pretende ser una introduccin, por lo que
dejamos de lado las cosas ms complejas.

Generacin automtica del modelo
Cuando se trabaja con ORM, necesitas crear el conjunto de clases que representa el modelo de la aplicacin,
luego estas clases sern vinculadas al esquema de la base de datos de forma automtica con un motor ORM.
Aunque son cosas diferentes, cuando diseas un modelo relacional y un modelo de clases, suelen ser muy
parecidos. Doctrine se aprovecha de esta similitud y nos permite generar de forma automtica el modelo de
clases basndose en el modelo relacional de tablas.
Es decir, si tenemos una tabla llamada usuarios, se autogenerar una clase llamada Usuarios cuyas propiedades
son las columnas de dicha tabla.

Posibilidad de trabajar con YAML
Como se comenta en el apartado anterior, Doctrine puede generar de forma automtica el modelo, pero tambin
deja la posibilidad (como es lgico) que puedas definir tu mismo el mapeo de tablas y sus relaciones.
Esto se puede hacer con cdigo PHP o con YAML, que es un formato de serializacin de datos legible por
humanos muy usado para este fin. En el ejemplo siguiente se muestra como definir dos tablas relacionadas:
1. ---
2. User:
3. columns:
4. username:
5. type: string(255)
6. password:
7. type: string(255)
8. contact_id:
9. type: integer
10. relations:
11. Contact:
12. class: Contact
13. local: contact_id
14. foreign: id
15. foreignAlias: User
16. foreignType: one
17. type: one
18.
19. Contact:
20. columns:
21. first_name:
22. type: string(255)
23. last_name:
24. type: string(255)
25. phone:
26. type: string(255)
27. email:
28. type: string(255)
29. address:
30. type: string(255)
31. relations:
32. User:
33. class: User
34. local: id
35. foreign: contact_id
36. foreignAlias: Contact
37. foreignType: one
38. type: one
En el ejemplo, se muestra una relacin entre dos tablas a travs de los campos User.contact_id y Contact.id.

Doctrine_Record y Doctrine_Table
Practicamente todo nuestro modelo heredar de estas dos clases. Doctrine_Record representa una entidad con
sus propiedades (columnas) y nos facilita mtodos para insertar, actualizar o eliminar registros entre otros. Por
ejemplo:

1. <php
2. $user = new User();
3. $user->name = Ivn;
4. $user->save();
La clase Doctrine_Table representa el esquema de una tabla. A travs de esta clase podemos, por ejemplo,
obtener informacin sobre las columnas o buscar registros especficos:

1. <?php
2. $userTable = Doctrine_Core::getTable('Users');
3. $user = $userTable->find(1);
Buscadores mgicos (Magic finders)
En Doctrine, puedes buscar registros basndote en cualquier campo de una tabla. En el prrafo anterior podamos
ver que existe el mtodo find() para buscar un determinado id en una tablapues bien, se podra hacer findByX()
en donde X es el nombre de la columna.
Si existen los campos llamados name y email, podemos hacer findByName() y findByEmail(). Tambin es
importante decir que existe el mtodo findAll(), que obtiene todos los registros de la tabla.

Relaciones entre entidades
En Doctrine, una vez que hemos definido nuestro modelo (o se ha creado de forma automtica) con las tablas y
sus relaciones, resulta fcil acceder y moverse por entidades relacionadas.
Vamos a ver un ejemplo de como acceder a valores que en nuestro sistema relacional se encuentran en tablas
separadas. Teniendo en cuenta que tenemos dos tablas, User y Comments, con relacin 1-N:

1. <?php
2. $commentsTable = Doctrine_Core::getTable('Comments');
3. $comments = $commentsTable->findAll();
4. foreach($comments as $comment){
5. echo $comment->User->name;
6. }
A travs de $comment->User estamos accediendo a un nuevo objeto del tipo User que se carga de forma
dinmica, de esta forma podemos acceder a las propiedades y mtodos de dicha clase olvidndonos de tener que
lanzar cdigo SQL.


Lenguaje DQL

DQL es un lenguaje creado para ayudar al programador a extraer objetos de la base de datos. Entre las ventajas de usar
este lenguaje se encuentran:
Est diseado para extraer objetos, no filas, que es lo que nos interesa.
Entiende las relaciones, por lo que no es necesario escribir los joins a mano.
Portable con diferentes bases de datos.
Es importante considerar el uso de DQL para obtener la informacin a cargar en lugar de usar la forma automtica de
Doctrine para mejorar el rendimiento. En el ejemplo anterior, cuando se accede a $comment->User, hemos dicho que se
est cargando un nuevo objeto de forma dinmica, pues bien, esto no es ptimo porque realiza consultas SQL de ms.
Si tenemos 100 comentarios, ejecutar 100 consultas SQL para cargar la informacin del objeto User, lo cual es una
prdida de rendimiento enorme. En lugar de eso, es necesario usar DQL para que traiga toda la informacin de un solo
paso:

1. <?php
2. $q = Doctrine_Query::create()
3. ->select('c.*,u.name')
4. ->from('Comments c')
5. ->innerJoin('c.User u');
6. $comments = $q->execute();
El cdigo anterior obtendr la informacin de los comentarios cruzados con los datos de usuario, por lo que obtendr toda la
informacin en un solo paso.
El lenguaje DQL es algo tan extenso que necesitaramos ms tiempo para explicarlo en profundidad, por eso
recomendamos mirar la documentacin oficial, donde est bien explicado y completo

Problema
Estamos frente a muchos problemas en la construccin de aplicaciones web. En lugar de tratar de explicar todo lo mejor es
leer lo que Wikipedia tiene que decir acerca de objetos mappers relacionales.
Tareas de gestin de datos en (OO) la programacin orientada a objetos se implementan normalmente mediante la
manipulacin de objetos, que son casi siempre los valores no escalares. Por ejemplo, considere una entrada de libreta de
direcciones que representa una sola persona, junto con cero o ms nmeros de telfono y cero o ms direcciones. Esto
podra ser modelado en una aplicacin orientada a objetos por un "objeto persona" con "slots" para contener los datos que
conforman la entrada: el nombre de la persona, una lista (o matriz) de nmeros de telfono, y una lista de direcciones. La
lista de nmeros de telfono podra contener en s "objetos Mviles" y as sucesivamente. La entrada de la libreta de
direcciones se trata como un nico valor por el lenguaje de programacin (se puede hacer referencia a una sola variable,
por ejemplo). Varios mtodos se pueden asociar con el objeto, tal como un mtodo para devolver el nmero preferido de
telfono, la direccin de su casa, y as sucesivamente.

Sin embargo, muchos productos de bases de datos populares, tales como SQL DBMS slo pueden almacenar y manipular
valores escalares como enteros y cadenas organizadas en tablas. El programador debe ya sea convertir los valores de los
objetos en grupos de valores ms simples para el almacenamiento en la base de datos (y convertirlos de nuevo en la
recuperacin), o slo utilizar valores escalares simples dentro del programa. Mapeo objeto-relacional se utiliza para
implementar el primer enfoque. La altura del problema es traducir esos objetos a las formas que se pueden almacenar en la
base de datos para su fcil recuperacin, preservando al mismo tiempo las propiedades de los objetos y sus relaciones;
estos objetos se dice que son persistentes.

Requerimientos mnimos

Como se ha expresado, el Doctrine, sera una librera en el servidor que se este usando, haciendo de su uso algo simple,
pues se descarga como cualquier librera y se crea una carpeta llamada mapeador, donde va a estar contenida la
informacin del Doctrine.

Construyendo un ejemplo real

Para darle algo de vida al tutorial, vamos a crear una implementacin muy sencilla de Doctrine en la que veremos todo lo
comentado hasta ahora. La aplicacin consiste en un listado de comentarios escritos por usuarios.
Cada vez que se desee insertar un nuevo comentario, se deber rellenar un formulario con: nombre, e-mail y texto, siendo
los dos ltimos obligatorios. Si el usuario no deja su nombre, se mostrar como Desconocido.

Paso 1: crear el esquema de base de datos
El ejemplo es tan sencillo que solamente tendr dos tablas relacionadas entre s: users y users_comment

1. CREATE SCHEMA ontuts_doctrine CHARSET UTF8 COLLATE utf8_general_ci;
2. use ontuts_doctrine;
3. CREATE TABLE users(
4. id INT(11) PRIMARY KEY auto_increment,
5. name VARCHAR(30),
6. email VARCHAR(60)
7. )ENGINE=INNODB;
8. CREATE TABLE users_comments(
9. id INT(11) PRIMARY KEY auto_increment,
10. id_user INT(11) NOT NULL,
11. text VARCHAR(255),
12. CONSTRAINT fk_users_comments_users FOREIGN KEY (id_user) REFERENCES users(id)
13. )ENGINE=INNODB;

Paso 2: crear el modelo
Esto, como ya habrs aprendido, se puede hacer de forma manual (con PHP o YAML) y de forma automtica. En este caso
lo haremos de forma automtica para explicar cmo funciona. Vamos a crear el script que se encargar de generar los
ficheros, create_orm_model.php:

1. <?php
2. require_once(dirname(__FILE__) . '/lib/Doctrine.php');
3. spl_autoload_register(array('Doctrine', 'autoload'));
4. $conn = Doctrine_Manager::connection('mysql://root:password@localhost/ontuts_doctrine', 'doctrine');
5. Doctrine_Core::generateModelsFromDb('models', array('doctrine'), array('generateTableClasses' => true));

Nos aseguramos de que existe la carpeta models en la raz de nuestro proyecto:
1. mkdir /path/myproject/models
Ahora llamamos al script, bien va Apache o va CLI:
1. php5 -f create_orm_model.php
Una vez se ha ejecutado con xito, vamos a la carpeta models y vemos que se han generado varios ficheros:
Users.php
UsersTable.php
UserComments.php
UserCommentsTable.php
generated/BaseUsers.php
generated/BaseUsersComments.php
Si te fijas, se han creado las clases que se extienden de Doctrine_Record y Doctrine_Table que ya hemos comentado
antes.
BaseUsers.php y BaseUsersComments.php representan clases base y que no deberas modificar. Cualquier mtodo o
propiedad que desees aadir, debes hacerlo sobre Users.php o UsersComments.php.

Paso 3: extender el modelo
Analizando la aplicacin llegamos a la conclusin de que la clase Users necesita dos nuevos mtodos:

getName: que devuelva el nombre del usuario o Desconocido si no ha rellenado esa informacin.
addComment: que inserte un nuevo comentario asignado a dicho usuario.
Editamos entonces el fichero Users.php y lo dejamos as:

1. <?php
2. class Users extends BaseUsers
3. {
4. public function addComment($text){
5. $comment = new UsersComments();
6. $comment->id_user = $this->id;
7. $comment->text = $text;
8. $comment->save();
9. }
10. public function getName(){
11. if(emptyempty($this->name) || is_null($this->name)){
12. return "Desconocido";
13. }else{
14. return $this->name;
15. }
16. }
17. }
Tambin necesitamos extender la clase UsersCommentsTable para sobreescribir el mtodo findAll(), de forma que obtenga
la informacin cruzada con la tabla users y as mejorar el rendimiento. Editamos el fichero UsersCommentsTable.php y lo
dejamos as:

1. <?php
2. class UsersCommentsTable extends Doctrine_Table
3. {
4. /**
5. * Returns an instance of this class.
6. *
7. * @return object UsersCommentsTable
8. */
9. public static function getInstance()
10. {
11. return Doctrine_Core::getTable('UsersComments');
12. }
13. public function findAll($hydrationMode = null){
14. $q = Doctrine_Query::create()
15. ->select('c.*,u.name')
16. ->from('UsersComments c')
17. ->innerJoin('c.Users u');
18. return $q->execute();
19. }
20. }
Listo, ya tenemos nuestro modelo ampliado

Paso 4: crear la lgica
A continuacin creamos el fichero index.php que contendr la lgica principal de la aplicacin. Nos queda algo
as: index.php

1. <?php
2. //Carga Doctrine
3. require_once(dirname(__FILE__) . '/lib/Doctrine.php');
4. spl_autoload_register(array('Doctrine', 'autoload'));
5. $conn = Doctrine_Manager::connection('mysql://root@localhost/ontuts_doctrine', 'doctrine');
6. $conn->setCharset('utf8');
7. Doctrine_Core::loadModels('models');
8.
9. //Variable en la plantilla html
10. $tpl = array("comments"=> array(), "error"=>false);
11.
12. //Comprueba si se ha enviado el formulario
13. if(!emptyempty($_POST) && isset($_POST['create_comment'])){
14. $email = filter_input(INPUT_POST, "email", FILTER_SANITIZE_STRING);
15. $name = filter_input(INPUT_POST, "name", FILTER_SANITIZE_STRING);
16. $text = filter_input(INPUT_POST, "text", FILTER_SANITIZE_STRING);
17. //Comprueba que se hayan rellenado los campos obligatorios
18. if(!emptyempty($email) && !is_null($email) &&
19. !emptyempty($text) && !is_null($text)){
20. $userTable = Doctrine_Core::getTable('Users');
21. $users = $userTable->findByEmail($email);
22. $user = null;
23. //Si el usuario no existe, lo crea
24. if($users->count()==0){
25. $user = new Users();
26. $user->name = $name;
27. $user->email = $email;
28. $user->save();
29. }else{
30. $user = $users[0];
31. }
32. //Inserta el comentario
33. $user->addComment($text);
34. }else{
35. //Si no se se han rellenado todos los valores obligatorios
36. //mostrar un error
37. $tpl['error'] = true;
38. }
39. }
40. //Carga los comentarios
41. $commentsTable = Doctrine_Core::getTable('UsersComments');
42. $tpl['comments'] = $commentsTable->findAll();
43. //Envia la informacin
44. require_once('template.phtml');
Paso 5: crear la plantilla
Por ltimo ya solo nos queda dar formato visual al contenido de template.phtml:

1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2. <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
3. <head>
4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5. </head>
6. <body>
7. <h2>Aadir comentario</h2>
8. <?if($tpl['error']):?><p>Por favor, rellena las cajas marcadas con asterisco (*)</p><?endif?>
9. <form action="index.php" method="post">
10. <label>Direccin e-mail *</label><br/>
11. <input type="text" name="email"/><br/>
12. <label>Nombre</label><br/>
13. <input type="text" name="name"/><br/>
14. <label>Comentario *</label><br/>
15. <textarea name="text" cols="80" rows="5"></textarea><br/>
16. <input type="submit" name="create_comment" value="Enviar"/>
17. </form>
18. <h2>Comentarios de los usuarios</h2>
19. <ul>
20. <?foreach($tpl['comments'] as $comment):?>
21. <li><a href="mailto:<?=$comment->Users->email?>"><?=$comment->Users->getName()?></a> - <?=$comment->text?></li>
22. <?endforeach?>
23. </ul>
24. </body>
25. </html>
Conclusin
Doctrine es una herramienta muy til, con la cual se simplifica la indexacin y se mejora el tiempo de bsqueda. Lo cual es
solamente gracias a los proyectos de un gran nmero de personas que hacen hoy posible, su uso. Su aplicacin es muy
fcil, pues slo requiere una pequea leda o explicacin; el detalle es que al ser programadores inicindose, no se
recomendara usarlo, pues se pierde ese aprendizaje que es bsico y necesario.

Bibliografa
http://www.doctrine-project.org/
http://es.wikipedia.org/wiki/Doctrine_(PHP)
http://web.ontuts.com/tutoriales/utilizando-doctrine-como-orm-en-php/
http://gnoma.es/blog/introduccion-a-doctrine-2/

También podría gustarte