Utilizando Doctrine Como ORM en PHP _ Web.ontuts

17
Tutoriales de Desarrollo y Diseño Web | Web.Ontuts Tutoriales Detallados & Fáciles Recursos Iconos, fuentes y más Inspiración Despierta tu creatividad Conócenos Contacto & Información Utilizando Doctrine como ORM en PHP julio 6, 2010 en Tutoriales por Iván Guardado doctrine, orm, php 7 Comentarios

Transcript of Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Page 1: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Tutoriales de Desarrollo y Diseño Web | Web.OntutsTutorialesDetallados & FácilesRecursosIconos, fuentes y másInspiraciónDespierta tu creatividadConócenosContacto & Información

Utilizando Doctrine como ORM en PHP

julio 6, 2010 en Tutoriales por Iván Guardadodoctrine, orm, php 7 Comentarios

Page 2: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Continuamos con otra publicación perteneciente a la serie de artículos dedicados a Object-Relational Mapping (ORM). Esta vez nos centraremos en algo máspráctico, creando un aplicación de ejemplo usando Doctrine como motor de ORM.

131 ► Retweet

Autor: Iván Guardado

Intentando mejorar cada día en este mundo tan cambiante de la programación. Sígueme en Twitter o en GitHub. Actualmente estoy disponible para contratar.

¿Que es Doctrine?

Doctrine es una librería 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.Si no sabes todavía que significa ORM y que ventajas / desventajas tiene, te recomiendo que leas el tutorial anterior: Introducción a Object-RelationalMapping (ORM).

Doctrine está inspirado en Hibernate, que es uno de los ORM más populares y grandes que existen y nos brinda una capa de abstracción de la base de datosmuy completa. La característica más importante es que te da la posibilidad de escribir consultas de base de datos en un lenguaje propio llamado DoctrineQuery Language (DQL).

Características principales

Doctrine es una librería muy completa y muy configurable, por lo que casi me resulta complicado seleccionar que detalles destacar. Os pongo lascaracterísticas más globales, ya que este tutorial pretende ser una introducción, por lo que dejamos de lado las cosas más “complejas”.

Generación automática del modelo

Cuando se trabaja con ORM, necesitas crear el conjunto de clases que representa el modelo de la aplicación, luego estas clases serán vinculadas al esquemade la base de datos de forma automática con un motor ORM.

Share 23

Page 3: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Aunque son cosas diferentes, cuando diseñas un modelo relacional y un modelo de clases, suelen ser muy parecidos. Doctrine se aprovecha de esta similitudy nos permite generar de forma automática el modelo de clases basándose 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 automática el modelo, pero también deja la posibilidad (como es lógico) quepuedas definir tu mismo el mapeo de tablas y sus relaciones.

Esto se puede hacer con código PHP o con YAML , que es un formato de serialización de datos legible por humanos muy usado para este fin. En el ejemplosiguiente se muestra como definir dos tablas relacionadas:

--- 01.User: 02. columns: 03. username: 04. type: string(255) 05. password: 06. type: string(255) 07. contact_id: 08. type: integer 09. relations: 10. Contact: 11. class: Contact 12. local: contact_id 13. foreign: id 14. foreignAlias: User 15. foreignType: one 16. type: one 17. 18.Contact: 19. columns: 20. first_name: 21. type: string(255) 22. last_name: 23. type: string(255) 24. phone: 25. type: string(255) 26. email: 27. type: string(255) 28. address: 29. type: string(255) 30.

Page 4: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

relations: 31. User: 32. class: User 33. local: id 34. foreign: contact_id 35. foreignAlias: Contact 36. foreignType: one 37. type: one 38.

En el ejemplo, se muestra una relación entre dos tablas a través 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 facilitamétodos para insertar, actualizar o eliminar registros entre otros. Por ejemplo:

view plain copy to clipboard print ?

<php 01.$user = new User(); 02.$user->name = “Iván”; 03.$user->save(); 04.

La clase Doctrine_Table representa el esquema de una tabla. A través de esta clase podemos, por ejemplo, obtener información sobre las columnas o buscarregistros específicos:

view plain copy to clipboard print ?

<?php 01.$userTable = Doctrine_Core::getTable('Users'); 02.$user = $userTable->find(1); 03.

Buscadores mágicos (Magic finders)

En Doctrine, puedes buscar registros basándote en cualquier campo de una tabla. En el partado anterior podíamos ver que existe el método find() para buscarun determinado id en una tabla…pues bien, se podría hacer findByX() en donde X es el nombre de la columna.

Si existen los campos llamados name y email, podemos hacer findByName() y findByEmail(). Tambien es importante decir que existe el método findAll(),que obtiene todos los registros de la tabla.

Page 5: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Relaciones entre entidades

En Doctrine, una vez que hemos definido nuestro modelo (o se ha creado de forma automática) con las tablas y sus relaciones, resulta fácil acceder ymoverse 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 dostablas, User y Comments, con relación 1-N:

view plain copy to clipboard print ?

<?php 01.$commentsTable = Doctrine_Core::getTable('Comments'); 02.$comments = $commentsTable->findAll(); 03.foreach($comments as $comment){ 04. echo $comment->User->name; 05.} 06.

A través de $comment->User estamos accediendo a un nuevo objeto del tipo User que se carga de forma dinámica, de esta forma podemos acceder a laspropiedades y métodos de dicha clase olvidándonos de tener que lanzar código 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á diseñado 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 información a cargar en lugar de usar la “forma automática” de Doctrine para mejorar elrendimiento. En el ejemplo anterior, cuando se accede a $comment->User, hemos dicho que se está cargando un nuevo objeto de forma dinámica, pues bien,esto no es óptimo porque realiza consultas SQL de más.

Si tenemos 100 comentarios, ejecutará 100 consultas SQL para cargar la información del objeto User, lo cual es una pérdida de rendimiento enorme. En lugarde eso, es necesario usar DQL para que traiga toda la información de un solo paso:

view plain copy to clipboard print ?

<?php 01.$q = Doctrine_Query::create() 02.

Page 6: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

->select('c.*,u.name') 03. ->from('Comments c') 04. ->innerJoin('c.User u'); 05.$comments = $q->execute(); 06.

El código anterior obtendrá la información de los comentarios cruzados con los datos de usuario, por lo que obtendrá toda la información en un solo paso.

El lenguaje DQL es algo tan extenso que necesitaría varios artículos para explicarlo en profundidad, por eso te recomiendo que mires la documentaciónoficial que está bien explicado y completo

Construyendo un ejemplo real

Para darle algo de vida al tutorial, vamos a crear una implementación muy sencilla de Doctrine en la que veremos todo lo comentado hasta ahora. Laaplicación 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 elusuario 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_comments.

view plain copy to clipboard print ?

CREATE SCHEMA ontuts_doctrine CHARSET UTF8 COLLATE utf8_general_ci; 01.use ontuts_doctrine; 02.CREATE TABLE users( 03. id INT(11) PRIMARY KEY auto_increment, 04. name VARCHAR(30), 05. email VARCHAR(60) 06.)ENGINE=INNODB; 07.CREATE TABLE users_comments( 08. id INT(11) PRIMARY KEY auto_increment, 09. id_user INT(11) NOT NULL, 10. text VARCHAR(255), 11.CONSTRAINT fk_users_comments_users FOREIGN KEY (id_user) REFERENCES users(id) 12.)ENGINE=INNODB; 13.

Paso 2: crear el modelo

Page 7: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Esto, como ya habrás aprendido, se puede hacer de forma manual (con PHP o YAML) y de forma automática. En este caso lo haremos de forma automáticapara explicar como funciona. Vamos a crear el script que se encargará de generar los ficheros, create_orm_model.php:

view plain copy to clipboard print ?

<?php 01.require_once(dirname(__FILE__) . '/lib/Doctrine.php'); 02.spl_autoload_register(array('Doctrine', 'autoload')); 03.$conn = Doctrine_Manager::connection('mysql://root:password@localhost/ontuts_doctrine', 'doctrine'); 04.Doctrine_Core::generateModelsFromDb('models', array('doctrine'), array('generateTableClasses' => true)); 05.

Nos aseguramos de que existe la carpeta models en la raíz de nuestro proyecto:

view plain copy to clipboard print ?

mkdir /path/myproject/models 01.

Ahora llamamos al script, bien vía Apache o vía CLI:

php5 -f create_orm_model.php 01.

Una vez se ha ejecutado con éxito, vamos a la carpeta models y vemos que se han generado varios ficheros:

Users.phpUsersTable.phpUserComments.phpUserCommentsTable.phpgenerated/BaseUsers.phpgenerated/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 deberías modificar. Cualquier método o propiedad que desees añadir, debeshacerlo sobre Users.php o UsersComments.php.

Paso 3: extender el modelo

Analizando la aplicación llegamos a la conclusión de que la clase Users necesita dos nuevos métodos:

Page 8: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

getName: que devuelva el nombre del usuario o “Desconocido” si no ha rellenado esa información.addComment: que inserte un nuevo comentario asignado a dicho usuario.

Editamos entonces el fichero Users.php y lo dejamos así:

view plain copy to clipboard print ?

<?php 01.class Users extends BaseUsers 02.{ 03. public function addComment($text){ 04. $comment = new UsersComments(); 05. $comment->id_user = $this->id; 06. $comment->text = $text; 07. $comment->save(); 08. } 09. public function getName(){ 10. if(emptyempty($this->name) || is_null($this->name)){ 11. return "Desconocido"; 12. }else{ 13. return $this->name; 14. } 15. } 16.} 17.

Tambien necesitamos extender la clase UsersCommentsTable para sobreescribir el método findAll(), de forma que obtenga la información cruzada con latabla users y así mejorar el rendimiento. Editamos el fichero UsersCommentsTable.php y lo dejamos así:

view plain copy to clipboard print ?

<?php 01.class UsersCommentsTable extends Doctrine_Table 02.{ 03. /** 04. * Returns an instance of this class. 05. * 06. * @return object UsersCommentsTable 07. */ 08. public static function getInstance() 09. { 10. return Doctrine_Core::getTable('UsersComments'); 11. } 12. public function findAll($hydrationMode = null){ 13. $q = Doctrine_Query::create() 14. ->select('c.*,u.name') 15.

Page 9: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

->from('UsersComments c') 16. ->innerJoin('c.Users u'); 17. return $q->execute(); 18. } 19.} 20.

Listo, ya tenemos nuestro modelo ampliado .

Paso 4: crear la lógica

A continuación creamos el fichero index.php que contendrá la lógica principal de la aplicación. Nos queda algo así: index.php

view plain copy to clipboard print ?

<?php 01.//Carga Doctrine 02.require_once(dirname(__FILE__) . '/lib/Doctrine.php'); 03.spl_autoload_register(array('Doctrine', 'autoload')); 04.$conn = Doctrine_Manager::connection('mysql://root@localhost/ontuts_doctrine', 'doctrine'); 05.$conn->setCharset('utf8'); 06.Doctrine_Core::loadModels('models'); 07. 08.//Variable en la plantilla html 09.$tpl = array("comments"=> array(), "error"=>false); 10. 11.//Comprueba si se ha enviado el formulario 12.if(!emptyempty($_POST) && isset($_POST['create_comment'])){ 13. $email = filter_input(INPUT_POST, "email", FILTER_SANITIZE_STRING); 14. $name = filter_input(INPUT_POST, "name", FILTER_SANITIZE_STRING); 15. $text = filter_input(INPUT_POST, "text", FILTER_SANITIZE_STRING); 16. //Comprueba que se hayan rellenado los campos obligatorios 17. if(!emptyempty($email) && !is_null($email) && 18. !emptyempty($text) && !is_null($text)){ 19. $userTable = Doctrine_Core::getTable('Users'); 20. $users = $userTable->findByEmail($email); 21. $user = null; 22. //Si el usuario no existe, lo crea 23. if($users->count()==0){ 24. $user = new Users(); 25. $user->name = $name; 26. $user->email = $email; 27. $user->save(); 28. }else{ 29. $user = $users[0]; 30. } 31.

Page 10: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

//Inserta el comentario 32. $user->addComment($text); 33. }else{ 34. //Si no se se han rellenado todos los valores obligatorios 35. //mostrará un error 36. $tpl['error'] = true; 37. } 38.} 39.//Carga los comentarios 40.$commentsTable = Doctrine_Core::getTable('UsersComments'); 41.$tpl['comments'] = $commentsTable->findAll(); 42.//Envia la información 43.require_once('template.phtml'); 44.

Paso 5: crear la plantilla

Por último ya solo nos queda dar formato visual al contenido de template.phtml:

view plain copy to clipboard print ?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 01.<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> 02.<head> 03.<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 04.</head> 05.<body> 06.<h2>Añadir comentario</h2> 07.<?if($tpl['error']):?><p>Por favor, rellena las cajas marcadas con asterisco (*)</p><?endif?> 08.<form action="index.php" method="post"> 09.<label>Dirección e-mail *</label><br/> 10.<input type="text" name="email"/><br/> 11.<label>Nombre</label><br/> 12.<input type="text" name="name"/><br/> 13.<label>Comentario *</label><br/> 14.<textarea name="text" cols="80" rows="5"></textarea><br/> 15.<input type="submit" name="create_comment" value="Enviar"/> 16.</form> 17.<h2>Comentarios de los usuarios</h2> 18.<ul> 19.<?foreach($tpl['comments'] as $comment):?> 20.<li><a href="mailto:<?=$comment->Users->email?>"><?=$comment->Users->getName()?></a> - <?=$comment->text?></li> 21.<?endforeach?> 22.</ul> 23.</body> 24.</html> 25.

Page 11: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Reflexión final

Como has visto, en cuestión de minutos tenemos una mini aplicación en PHP que nos permite añadir y listar registros de una base de datos de una forma muyordenada y sin tocar ni una letra de código SQL.

No llevaría mucho tiempo añadir un sistema de login de usuarios y que pudiesen editar y borrar los comentarios, gracias a los métodos save() y delete() de laclase Doctrine_Record.

¡Nos vemos en la próxima publicación!

Te sugerimos otras entradas relacionadas...

Cómo validar un formulario utilizando PHP y Javascript (jQuery)

Creando una capa de conexión abstracta a base de datos con PHP

Page 12: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Introducción a Object-Relational Mapping (ORM)

Acelerando los tiempos de carga uniendo archivos Javascript con PHP

Page 13: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

¿Necesitas desarrollar un proyecto web o para móviles? ¡Estamos disponibles!

Cokidoo, los creadores de Ontuts, desarrollamos proyectos tecnológicos centrados en redes sociales y aplicaciones web, aplicaciones móviles y consultoríaweb y bases de datos.

Somos jóvenes, inquietos, versátiles, apasionados por la innovación y enfocados en las nuevas tecnologías. Con Ontuts tratamos de compartir nuestroconocimiento adquirido en los distintos proyectos, ayudando a la comunidad y mostrando nuestra capacidad tecnológica.

Si necesitas un presupuesto sin compromiso, estamos disponibles, no dudes en contactar con nosotros.

Comentarios en esta publicación (7 comentarios)

¿Te ha gustado esta publicación? ¡Puedes compartir tu opinión con todos nosotros! Simplemente pincha aquí mismo.

marcos

Holamuy interesante tu Post!!me sirve mucho est ateoria y algo de practica pues estoy entrando al mundo de symfony y esto me valdra mucho!

gracias por postear este tutorial

atte marcos velasquez

Publicado el día 10 de noviembre del año 2010Alberto

Es para la versión 1 o 2 de Doctrine?

Publicado el día 01 de febrero del año 2011

Page 14: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Jorge Leguia

Muy bueno tu post.Está bien elaborado y es objetivo.

Gracias y Ojalá cuelgues una Aplicación practica igual utilizando Symfony o Zend.

Este ejemplo lo probe con Doctrine 1.2 y me funcionó.En cuanto al Doctrine 2.0, solo trabaja con PHP 5.3.+ y estos ejemplos no funcionan ya que la estructura de archivos es otra, etc.

Saludos

Publicado el día 07 de marzo del año 2011

Rafael

Excelente trabajo, estoy empezando con CodeIgniter y este material es muy valioso.

Gracias

Saludos

Publicado el día 05 de abril del año 2011madeley

hola quiero hacer una consulta donde trabajo hay un sistema que se va a eliminar para crear uno nuevo me estan pidiendo que use doctrine no conozco de esaherramienta asi que tengo que estudiar quiero saber si se puede trabajar con doctrine sin utilizar framework como symfony por ejemplo osea doctrine solo ycomo se trabajaria? con que herramienta puedo codificar que sea amigable y que acepte doctrine por ejemplo algo como eclipse me han hablado de netbeanpero no c mucho de el me puedes ayudar

Publicado el día 16 de junio del año 2011javier

es caca

Publicado el día 27 de julio del año 2011

Page 15: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Lucas

Te agradezco por la info, siempre viene muy bien algo de teoría bien explicada. Uso symfony desde hace 6 meses y cada día me convence más.

Gracias!

Publicado el día 25 de agosto del año 2011

Añade Tu Comentario

Avísame si hay nuevos comentarios via e-mail

Conoce a los creadores...

Desde la empresa Cokidoo tratamos de ayudar a desarrolladores y diseñadores web compartiendo nuestro conocimiento.

Suscritos al Feed RSSFollowers en Twitter442 Fans en Facebook¡Suscríbete via E-mail ahora!cracks.ontuts: sólo los mejores

Page 16: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Advertise Here

Anunciarse en OntutsAyudamos a promocionar productos y servicios a empresas y freelancers.

Únete a la Comunidad flickr

Page 17: Utilizando Doctrine Como ORM en PHP _ Web.ontuts

Se ha escrito sobre...

análisis apis arte base datos concursos consejos css diseño ecommerce entrevista fuentes google gratis herramientas html html5 iconos imágenes indie

Inspiración internet explorer javascript jquery juno logos maquetacion microsoft noticias novedades opinión optimización php

programación python Recursos web silverlight sorteos sprites themes tipografia tutorial videojuegos web wordpress xbox

Ontuts.com, tutoriales, diseño, inspiracion & recursos web - Entradas (RSS) and Comentarios (RSS). Algunos iconos de WeFunction.