Vous êtes sur la page 1sur 78

Diseo de Aplicaciones Web

PHP
Gestin de Datos

Almacenamiento de Datos en PHP


Alternativas de almacenamiento en PHP:

Almacenamiento contra el API de MySQL.


API extendida de MySQL.
Objetos de datos: PDO (PHP Data Objects))
Serializacin y almacenamiento de objetos.
Proyeccin de datos relacionales en objetos: ORM (Object-Relational
Mapping)
Doctrine
Propel
Xyster

DAW 2

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

MySQL en PHP
API de MySQL y MySQLi

DAW 3

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Establecimiento de conexin:
resource mysql_connect (
[ string $server
= ini_get("mysql.default_host")
[, string $username = ini_get("mysql.default_user")
[, string $password = ini_get("mysql.default_password")
[, bool $new_link
= false
[, int
$client_flags = 0 ]]]]] )

El resultado de la llamada es un recurso (manejador al enlace


establecido) de la conexin con la BD.
Dicho valor se usa como parmetro en las posteriores llamadas.
$handler= mysql_connect('localhost', chema', patata');
if (!$ handler) {
die(Error de conexin: ' . mysql_error());
}
echo Conexin establecida';
DAW 4

La referencia al servidor se
realiza con el formato:
servidor:puerto
Por ejemplo:
laurel.datsi.fi.upm.es:4577

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Seleccin de la base de datos:
bool mysql_select_db (string $database_name [, resource $link_identifier = NULL ] )

Utilizando el manejador al enlace se selecciona la BD a utilizar.


Esta operacin es anloga al mandado de MySQL:
USE base_de_datos;
$handler= mysql_connect('localhost', chema', patata');
if (!$ handler) {
die(Error de conexin: ' . mysql_error());
}
echo Conexin establecida';
$bd_ok = mysql_select_db('foo', $handler);
if (!$bd_ok) {
die ('No se puede accede a foo : ' . mysql_error());
}

DAW 5

El utilizar o no una base de datos no es


excluyente, en MySQL es posible
acceder tablas de otras bases de datos
utilizando la sintaxis:
bd.tabla
Ejemplo:
SELECT * FROM stock.productos;

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Consultas SQL:
mixed mysql_query ( string $query [, resource $link_identifier = NULL ] )

Operaciones CRUD (Create, Read, Update and Delete):


Operaciones que devuelve listas de registos (tpicamente SELECT,
SHOW, DESCRIBE, EXPLAIN): El valor devuelto es otro recurso
(manejador del cursor de la consulta) al que se le puede consultar
por el nmero de registros devueltos:
int mysql_num_rows ( resource $result )

Operaciones que modifican registros (tpicamente INSERT, UPDATE,


DELETE, DROP): No se devuelve un recurso, pero se puede obtener
el nmero de registros afectados:
int mysql_affected_rows ([ resource $link_identifier = NULL ] )
DAW 6

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Recuperacin de registros de un SELECT (modo cursor):
array mysql_fetch_array ( resource $result [, int $result_type = MYSQL_BOTH ] )

Esta llamada devuelve un array con el siguiente registro del


manejador de cursos proporcionado o falso si no hay ms registros.
El tipo de resultado indica si el array producido est indexado por
nmeros o por nombres de columnas (o por ambos).
mysql_connect('localhost', 'chema', 'patata');
mysql_select_db('foo');
$resultado = mysql_query('SELECT id, nombre FROM tabla');
while ($fila = mysql_fetch_array($resultado, MYSQL_BOTH)) {
printf('ID: %s Nombre: %s', $fila['id'], $fila['nombre']);
}

DAW 7

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Recuperacin de registros de un SELECT (modo cursor con
objetos):
object mysql_fetch_object ( resource $result [, string $class_name [, array $params ]] )

La operativa es idntica al caso anterior pero el elemento devuelto no


es un array sino que es un objeto con los atributos de los campos del
registro.
mysql_connect('localhost', 'chema', 'patata');
mysql_select_db('foo');
$resultado = mysql_query('SELECT id, nombre FROM tabla');
while ($fila = mysql_fetch_object($resultado)) {
printf('ID: %s Nombre: %s', $fila->id, $fila->nombre);
}

DAW 8

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Lectura de un resultado de un SELECT (modo indexado):
string mysql_result ( resource $result , int $row [, mixed $field = 0 ] )

Esta alternativa permite acceder a los resultados indexando nmero


de fila y el campo.
El indicador del campo puede ser tanto el ndice, como el nombre del
mismo (incluyendo el formato tabla.campo).
mysql_connect('localhost', 'chema', 'patata');
mysql_select_db('foo');
$resultado = mysql_query('SELECT id, nombre FROM tabla');
for ($f = 0; $f < mysql_num_rows($resultado); $f++) {
printf('ID: %s Nombre: %s',
mysql_result($resultado, $f, 'id'),
mysql_result($resultado, $f, 'nombre'));
}
DAW 9

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Sentencias de modificacin de registros:
Vale con verificar si el resultado de ejecutar la consulta ha sido
verdadero o no.
mysql_connect('localhost', 'chema', 'patata');
mysql_select_db('foo');
$sql = "INSERT INTO agenda (nombre, direccion, telefono, email) ".
"VALUES ('$nombre', '$direccion', '$telefono', '$email')";
$resultado = mysql_query($sql);
if (!$resultado) {
print('Error en INSERT: '. mysql_error());
die();
}
$sql = "UPDATE agenda SET nombre='$nombre', direccion='$direccion',".
"telefono='$telefono', email='$email'";
$resultado = mysql_query($sql);
if(!$resultado) {
print('Error en UPDATE: '. mysql_error());
die();
}
DAW 10

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Otras funciones de utilidad:
Modificacin de cadenas con secuencias de escape:
string mysql_real_escape_string ( string $unescaped_string
[, resource $link_identifier = NULL ] )

Gestin de errores:
int mysql_errno ([ resource $link_identifier = NULL ] )
string mysql_error ([ resource $link_identifier = NULL ] )

Obtencin de identificador generado automticamente:


int mysql_insert_id ([ resource $link_identifier = NULL ] )

Obtener el nmero de campos de una consulta SELECT:


int mysql_num_fields ( resource $result )

Borrado de una base de datos


bool mysql_drop_db ( string $database_name [, resource $link_identifier = NULL ] )

Equivale al mandato SQL: DROP DATABASE base_de_datos;


DAW 11

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Gestin de transacciones:
No existen llamadas al API especficas para ello.
Se realizan consultas SQL estndar usando la funcin
mysql_query().
mysql_query("START TRANSACTION");
mysql_query("BEGIN");
$resultado = mysql_query("DELETE FROM facturas WHERE cliente_id='$id'");
if (!$resultado) {
mysql_query(ROLLBACK");
die('Error al borrar FACTURAS: '. mysql_error());
}

$resultado = mysql_query("DELETE FROM clientes WHERE id='$id'");


if (!$resultado) {
mysql_query(ROLLBACK");
die('Error al borrar CLIENTES: '. mysql_error());
}
mysql_query("COMMIT");
DAW 12

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

API de MySQL en PHP


Liberacin de recursos:
Cerrado de la conexin (opuesto a mysql_connect()):
bool mysql_close ([ resource $link_identifier = NULL ] )

Liberar la memoria de un cursos de consulta (el resultado de un


mysql_query() de tipo SELECT):
bool mysql_free_result ( resource $result )

Conexiones persistentes:
resource mysql_pconnect (
[ string $server
= ini_get("mysql.default_host")
[, string $username = ini_get("mysql.default_user")
[, string $password = ini_get("mysql.default_password")
[, int
$client_flags = 0 ]]]]] )

No se cierran cuando el script termina y se intentan reutilizar en otras


llamadas del mismo tipo.
DAW 13

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Limitaciones API Nativa de MySQL


Resulta necesario realizar las consultas picando SQL.
Adems:
Es necesario establecer la proteccin ante valores de campos que
puedan ser peligrosos:
Usando mysql_real_escape_string().

A la hora de insertar registros con campos de autoincremento se


necesita consultar y gestionar los identificadores:
Usando mysql_insert_id().

Y, sobre todo, es procedimental no Orientado a Objetos.

DAW 14

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Evolucin de las APIs de MySQL


PHP 4

PHP 5

API (procedimental) de MySQL:


Funciones mysql_()

PHP 5.5.0
API (orientada a objetos) de MySQL:
Objeto mysqli

mysqli {

__construct ([ string $host = ini_get("mysqli.default_host")


[, string $username = ini_get("mysqli.default_user")
[,string $passwd = ini_get("mysqli.default_pw")
[, string $dbname = ""
[, int $port = ini_get("mysqli.default_port")
[, string $socket = ini_get("mysqli.default_socket") ]]]]]] )
DAW 15

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

MySQLi
$db = new mysqli('localhost', 'chema', 'patata', 'foo');
if ($db->connect_errno > 0){
die('Error de conexin: ' . $db->connect_error );
}
if (!$resultado = $db->query('SELECT id, nombre FROM tabla')){
die('Error en la consulta: ' . $db->error);
}
while ($fila = $resultado->fetch_array(MYSQLI_NUM)) {
printf('ID: %s Nombre: %s', $fila['id'], $fila['nombre']);
}
printf('Se han obtenido %s filas', $resultado->num_rows);
if (!$db->query('DELETE FROM tabla WHERE edad<18')){
die('Error en la consulta: ' . $db->error);
}
printf('Se han borrado %s filas', $db->affected_rows);

DAW 16

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Sentencias Preparadas en MySQLi


Permite tener mandatos y consultas SQL preprocesadas:
$db = new mysqli('localhost', 'chema', 'patata', 'foo');

$sentencia = $db->prepare('SELECT id, nombre FROM tabla');


$sentencia->execute();

Estas sentencias pueden estar parametrizadas:


$sentencia = $db->prepare('SELECT id, nombre FROM tabla WHERE nombre=? ');
$nombre='Efigenia';
$sentencia->bind_param('s', $nombre);

Para recoger los resultados tambin se enlazan variables:


$sentencia->bind_result($res_id, $res_nombre);
while($sentencia->fetch()) {
printf('ID: %s Nombre: %s', $resid, $resnombre);
}

DAW 17

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Limitaciones API de MySQLi


En esencia es un recubrimiento orientado a objetos del API nativa.
Se sigue teniendo que escribir SQL.
Al igual que el API nativa de MySQL es completamente dependiente de
la tecnologa de BD (MySQL).

DAW 18

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Objetos de Datos PHP


Generalizacin de Acceso a Bases de Datos y
PDO de PHP

DAW 19

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Interfaz PDO
Objetivo: Independencia de la tecnologa de base de datos.
PDO (PHP Data Objects) es una extensin al estilo de otras
capas intermedias de estndares de acceso a bases de datos
(e.g., ODBC o JDBC).
El soporte de tecnologas de
PDO {

__construct ( string $dsn


[, string $username
[, string $password
[, array $options ]]] )

bases de datos concretas se


realizan por medio de drivers.
El driver y los parmetros de
configuracin se proporcionan en
la creacin del objeto PDO.

PostgreSQL:

$db = new PDO("pgsql:host=localhost;dbname=foo", chema", patata" );

MySQL:

$db = new PDO("mysql:host=localhost;dbname=foo", chema", patata" );

SQLite:

$db = new PDO("sqlite:/ruta/a/la/base_de_datos.sdb");

DAW 20

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Interfaz PDO
Ejecucin de consultas que devuelven registros:
public PDOStatement PDO::query ( string $statement )

Ejecucin de consultas que modifican registros:


public int PDO::exec ( string $statement )
try {

$db = new PDO("mysql:host=localhost;dbname=foo", chema", patata" );


foreach ($db->query('SELECT id, nombre FROM tabla') as $fila) {
printf('ID: %s Nombre: %s', $fila['id'], $fila['nombre']);
}
$cuantas = $db->exec('DELETE FROM tabla WHERE edad<18');
printf('Se han borrado %s filas', $cuantas);

}
catch (PDOException $e) {
echo $e->getMessage();
}
DAW 21

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Interfaz PDO
Recuperacin de datos con fetch():
public mixed PDOStatement::fetch (
[ int $fetch_style
[, int $cursor_orientation = PDO::FETCH_ORI_NEXT
[, int$cursor_offset = 0 ]]] )
$sentencia = $db->query('SELECT id, nombre FROM tabla');

Como un array: nombre o ndice


$array = $sentencia->fetch(PDO::FETCH_ASSOC);
printf('ID: %s Nombre: %s', $array['id'], $array['nombre']);

Como un objeto (annimo):


$objeto = $sentencia->fetch(PDO::FETCH_OBJ);
printf('ID: %s Nombre: %s', $objeto->id, $objeto->nombre);

DAW 22

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Interfaz PDO
class Persona {
public $id;
public $nombre;
public function nombre_mayusculas() {
return ucwords($this->nombre);
}
}

Como un objeto
de una clase
definida:
Con un cursor:

try {
$db = new PDO("mysql:host=localhost;dbname=foo", chema", "patata" );

$sql = "SELECT id, nombre FROM tabla";


$sentencia = $db->query($sql);
$pepe = $sentencia->fetch(PDO::FETCH_CLASS, 'Persona');
echo $pepe->nombre_mayusculas();
$cursor = $sentencia->fetchALL(PDO::FETCH_CLASS, 'Persona');
foreach($cursor as $persona)
echo $persona->nombre_mayusculas();

}
catch(PDOException $e) {
echo $e->getMessage();
}
DAW 23

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Tecnologas Soportadas por PDO


Las tecnologas de bases de datos soportadas por PDO:

CUBRID: Cubrid databases.


DBLIB: FreeTDS / Microsoft SQL Server / Sybase
Firebird (http://firebird.sourceforge.net/): Firebird/Interbase 6
IBM (IBM DB2)
INFORMIX - IBM Informix Dynamic Server
MYSQL (http://www.mysql.com/): MySQL 3.x/4.x/5.x
OCI (http://www.oracle.com): Oracle Call Interface
ODBC: ODBC v3 (IBM DB2, unixODBC y win32 ODBC)
PGSQL (http://www.postgresql.org/): PostgreSQL
SQLITE (http://sqlite.org/): SQLite 2.x/3.x
SQLSRV (http://msdn.microsoft.com/): Microsoft SQL Server / SQL
Azure
4D (http://www.4d.com/): 4th Dimension.
DAW 24

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Limitaciones PDO
No quiero escribir ms SQL!!!!!

DAW 25

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Necesidades de Almacenamiento de
Objetos
Limitaciones de Soluciones Relacionales y
Serializacin de Objetos en PHP

DAW 26

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Gestin de Datos en Aplicaciones Web


Necesidades de almacenamientos de datos:
Informacin estructurada
Documentos (ficheros)
Documentos (objetos)

Desde el punto de vista de funcionalidad lo que necesita el


nivel de aplicacin es que
Todo objeto de datos tenga su respaldo y
Que el acceso al respaldo (grabar y recuperar) sea eficiente.

DAW 27

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Limitaciones del Modelo Relacional


Las BD almacenan la informacin en filas y columnas.
El desarrollo de las aplicaciones e hace sobre estructuras de
datos y objetos.
Se puede simular las referencias entre objetos y las colecciones de
datos por medio de relaciones entre filas de las tablas.
Las restricciones que aseguran unicidad de identificadores o campos
son difciles de asegurar e implementar en los objetos.
Conceptos de campos dinmicos, algunas funcionalidades de las
herencias y ciertas colecciones de objetos se transcriben mal en el
modelo relacional.

DAW 28

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Almacenamiento de Objetos
La orientacin a objetos en su aplicacin al almacenamientos
de datos puede ser:
Que las estructuras de datos a nivel aplicacin sean objetos y se
almacenen como tales.
Que las estructuras de datos a nivel aplicacin sean objetos y se
almacenen como tablas (relacionales) de datos.
Aplicacin

OBJ

OBJ

Objeto
Documento

Fichero
Sistema de
Ficheros
DAW 29

Objeto
Registro de una tabla

NoSQL

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Almacenamiento de Objetos
Que las estructuras de datos a nivel aplicacin sean objetos y
se almacenen como tales:
Serializacin de objetos.
E.g., JSON o XML:

JavaScript
...
var txt = JSON.stringify(employeeList, replacer);
...
var obj = JSON.parse(txt, reviver);
...

XML
<employees>
<employee>
<firstName>John</firstName> <lastName>Doe</lastName>
</employee>
<employee>
<firstName>Anna</firstName> <lastName>Smith</lastName>
</employee>
<employee>
<firstName>Peter</firstName> <lastName>Jones</lastName>
</employee>
</employees>

DAW 30

JSON
{"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]}

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Serializacin en PHP
Se apoya en dos mtodos:
string serialize ( mixed $value )
mixed unserialize ( string $str )

El mtodos serialize() convierte un objeto en una cadena de caracteres y unserialize()


convierte una cadena de caracteres en un objeto.
Adicionalmente hay dos funciones a implementar en una clase serializable:
public array __sleep ( void )

Que devuelve un array de los strings de los campos a serializar. Dicha funcin se invoca
inmediatamente antes de serializar.
void __wakeup ( void )

Que se ejecuta inmediatamente despus de deserializar el objeto.


La serializacin es con un formato propio de PHP.
DAW 31

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Serializacin en PHP

class Empleado {
public $nombre;
public $apellido;
public $edad;
private $sueldo;
function __construct ($n, $a, $e, $s) {
$this->nombre = $n;
$this->apellido = $a;
$this->edad = $e;
$this->sueldo = $s;
}
}

object(Empleado)[1]
public 'nombre' => string 'Pepe' (length=4)
public 'apellido' => string 'Potamo' (length=6)
public 'edad' => int 32
private 'sueldo' => int 1900
O:8:"Empleado":4:{s:6:"nombre";s:4:"Pepe";s:8:"
apellido";s:6:"Potamo";s:4:"edad";i:32;s:16:"Em
pleadosueldo";i:1900;}
object(Empleado)[2]
public 'nombre' => string 'Pepe' (length=4)
public 'apellido' => string 'Potamo' (length=6)
public 'edad' => int 32
private 'sueldo' => int 1900

$pepe = new Empleado("Pepe", "Potamo", 32, 1900);


var_dump($pepe);
$str=serialize($pepe);
print $str;
$copia = unserialize($str);
var_dump($copia);
DAW 32

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Serializacin en PHP
object(Empleado)[1]
public 'nombre' => string 'Pepe' (length=4)
public 'apellido' => string 'Potamo' (length=6)
public 'edad' => int 32
private ' clave' => string patata' (length=6)
class Empleado {
O:8:"Empleado":4:{s:6:"nombre";s:4:"Pepe";s:8:"
public $nombre;
apellido";s:6:"Potamo";s:4:"edad";i:32;s:16:"Em
public $apellido;
pleadoclave";s:6:"cngngn";}
public $edad;
private $clave;
function __construct ($n, $a, $e, $c) {
$this->nombre = $n;
$this->apellido = $a;
$this->edad = $e;
$this->clave = $c;
}
function __sleep() {
$this->clave=str_rot13($this->clave);
return array('nombre', 'apellido', 'edad', 'clave');
}
function __wakeup() {
$this->clave=str_rot13($this->clave);
}
}
DAW 33

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Proyeccin Objeto-Relacional
ORM General y Versiones de Doctrine

DAW 34

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Proyeccin Objeto-Relacional
En ingls Object-Relational Mapping (ORM)
Propsito:
Guardar un objeto como una fila en una tabla de una BD.
Recuperar datos de las tablas y convertirlos en objetos.
Guardar y recrear asociaciones entre objetos.

Objetivos del diseo:


Separar los servicios de mapping entre objetos y relaciones del resto
del programa.
Minimizar el impacto de cambiar la tecnologa (y modelo) de la BD.

DAW 35

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Ejemplo
Aula
nmero: int
bloque: int
plazas: int

Curso
aula
1

nombre: String
horario: Date
crditos: int

Profesor
curso
1

profesores
* nombre: String

despacho: String

* cursos
* alumnos

Alumno
nombre: String
matrcula: int

DAW 36

Adicionalmente, se puede
asumir que todas las clases
disponen de un atributo id()
que es nico para todos los
objetos de esa clase (una
clave).

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Object-Relational Mapping
Clase:

Aula

Debe tener un atributo que acte


como identificador (id).

nmero: int
bloque: int
plazas: int

Data mapper:
Convierte:
Clase Tabla
Objeto Fila

ORM

Adapta los tipos de datos.


Instancia los objetos.

AULAS
PK id
nmero
bloque
plazas
DAW 37

VARCHAR(12)
INTEGER
INTEGER
INTEGER

Tabla:
El atributo identificador es
tpicamente la clave primaria.

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Object-Relational Mapping
(Aula) aqui
nmero=5101
bloque=5
plazas=125

Almacenado

Recuperacin
AULAS
id
C01
E02
E03

DAW 38

nmero bloque
3201
3
5101
5
5102
5

plazas
145
125
117

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Object-Relational Mapping
Funcionalidades de almacenamiento:
Almacenamiento explcito:
Se indica explcitamente cundo y qu almacenar.
Llamada de tipo save().

Almacenamiento de modificaciones realizadas:


Todo un conjunto de modificaciones se mandan a almacenar.
Se realizan mediante llamada flush().

Persistencia transparente:
Un objeto se declara como persistente.
Cada cambio de uno de sus atributos se sincroniza con el soporte de
almacenamiento.
Comienza en el momento en el que el elemento se registra en el gestor
correspondiente (register()).
Es necesario capturar los mtodos que modifican atributos.
DAW 39

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Active Record vs. Data Mapper


Dos patrones de implementacin de un ORM:
ACTIVE RECORD
Los objetos derivan de una clase de la
biblioteca de ORM de donde hereda
mtodos explcitos de
almacenado/recuperacin.
El diseo de los objetos establece qu
atributos son almacenables y aspectos
tales como el tipo de datos y nombre de
la columna de la tabla.
Se pueden construir los objetos del
cdigo a la BD o viceversa.
Ejemplos: Doctrine 1.2 (PHP), Ruby on
Rails o Laravel
DAW 40

DATA MAPPER
Los objetos no heredan de nada, son
objetos simples del lenguaje.
Los objetos estn desacoplado de cmo
almacenarlos (los mtodos que
implementan eso los mantiene un Entity
Manager).
La interaccin entre este elemento y la
BD es ms estricta.
Se puede ver como un DAL (Data
Access Layer) sofisticado que se las
entiende con objetos
Ejemplos: Doctrine 2+ (PHP), Boockself.js
o ROM

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Active Record vs. Data Mapper


Ventajas de Active Record:
El cdigo puede invocar expresamente al almacenamiento,
actualizacin y recuperacin de datos donde resulte ms adecuado
(es ms flexible).
Ms habituales y generalizadas y de utilidad en prototipado rpido.

Ventajas de Data Mapper:


Los objetos son ms ligeros (no mantienen la implementacin de los
mtodos de almacenamiento).
Al estar desacoplados los objetos de negocio del almacenamiento es
ms fcil ser estricto con MVC.
Se puede ver como un DAL (Data Access Layer) sofisticado que se
las entiende con objetos.
Facilita la persistencia transparente.
DAW 41

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Active Record vs. Data Mapper


$alumna = new Alumno("j070212", "Elena", "Nito del Bosque");
$alumna->creditos_aprobados = 207;
$alumna->save();

Active Record

Data Mapper

$alumna->save();

EntityManager::persist($alumna);

Doctrine 1.2

Doctrine 2

Implementaciones de ORM en PHP


DAW 42

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Identificadores en un ORM
La identificacin (identidad) de un objeto se implementa por
medio de dos mecanismos:
Est alojado en la misma ubicacin (o son la misma referencia),
operador A==B (igual).
Existe un mtodo de comparacin equals() o compareWith().

En una BD la comparacin est asociada a tener la misma


clave primaria.
La comparacin y la identidad de elementos est en la base
de la gestin de caches, de modificaciones y de transacciones.

DAW 43

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Relaciones entre Objetos


Curso
nombre: String
horario: Date
crditos: int

Profesor
curso
1

profesores
* nombre: String

despacho: String

ORM

CURSOS
PK id
nombre
horario
crditos
DAW 44

VARCHAR(8)
VARCHAR(64)
DATETIME
INTEGER

PROFESORES
PK id
nombre
despacho
FK id_curso

VARCHAR(12)
VARCHAR(64)
VARCHAR(16)
VARCHAR(8)

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Relaciones entre Objetos


En el momento que los objetos estn relacionados el
almacenamiento tiene que ser consistente con ello:
Si se almacena un objeto y hay modificaciones en objetos
relacionados con l se deben de guardar todas las modificaciones del
grafo.
Si se da las persistencia transparente esto debe de hacerse de forma
automtica.
new

creado

Registrar
Liberar
gestionado
eliminado
Buscar
Registrar
Desregistrar
Combinar
desacoplado
DAW 45

basura

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Flujos de Desarrollo con ORMs

Code First: Se
comienza por el
desarrollo de las clase
y luego se proyectan
en BD

Database First: Se
comienza por el modelo
de datos implementado
en la BD y de l se
extraen las clases.

Variante Model First: Cuando se comienzo con una herramienta


de modelado (tipo UML) de la estructura de clases.
DAW 46

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Problemas con Database First


Este flujo se apoya en una herramienta que analiza la estructura
de la base de datos y general el cdigo de las clases que la
implementan en el modelo de objetos.
Personas

Problemas:
Qu ocurre si sobre el cdigo generado yo lo
modifico y luego vuelvo a solicitar que se re-genere
desde la base de datos?
Se puede solucionar etiquetando las partes de
cdigo generadas manual o automticamente.
Derivar una subclase de la clase generada
automticamente.
DAW 47

Persona

DatoPersona
mi_mtodo()

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine
Implementacin de un ORM para PHP.
Versin Doctrine 1.2 basada en el patrn de implementacin de
Active Record.

Wikipedia

DAW 48

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 1.2
Las clases de objetos almacenables en BD deben extender la
clase Doctrine_Record:
Si se implementa como flujo Code First, se debe implementar el
mtodo setTableDefinition():
class Alumno extends Doctrine_Record {
public function setTableDefinition() {
$this->setTableName('Alumnos');
$this->hasColumn('nombre', 'string', 255, array('type' => 'string', 'length' => '255'));
$this->hasColumn('matricula', 'integer', 8, array('unsigned' => true));
}
}
CREATE TABLE Alumnos ( nombre VARCHAR(255), matricula INT(8) UNSIGNED);

Utilizacin:
DAW 49

$elena = new Alumno();


$elena->nombre ="Elena Nito del Bosque";
$elena->matricula = 70212;
$elena->save();
Santiago Rodrguez Santiago Gonzlez Fernando Prez
Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 1.2
Las relaciones entre tablas se disean como relaciones entro
clases:

class Alumno extends Doctrine_Record {


public function setTableDefinition() {
<>
}
public function setUp() {
$this->hasMany('Notas as Notas', array('refClass' => 'Nota', 'local' => 'id', 'foreign' => 'alumno_id'));
}
}

class Nota extends Doctrine_Record {


public function setTableDefinition() {
$this->setTableName('Notas');
$this->hasColumn('asignatura', 'string', 255, array('type' => 'string', 'length' => '255'));
$this->hasColumn('alumno_id', 'integer', 8, array('unsigned' => true));
$this->hasColumn(calificacion', 'integer', 2, array('unsigned' => true));
}
public function setUp() {
$this->hasOne('Alumno', array('refClass' => 'Alumno', 'local' => 'alumno_id', 'foreign' => 'matricula'));
}
}
DAW 50

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 1.2
$elena = new Alumno();
$elena->nombre ="Elena Nito del Bosque";
$elena->matricula = 70212;

Alumnos

$nota = new Nota();


$nota->asignatura = "Diseo de Aplicaciones Web";
$nota->calificacion = 9;

tienen

$elena->Notas[] = $nota;

Notas

$nota->Alumno = $elena;
$elana->save();

ALUMNOS
Matrcula

Nombre

70212

Elena Nito del Bosque

DAW 51

NOTAS
Matrcula

Asignatura

Calificacin

70212

Diseo de Aplicaciones Web

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Alternativas de Flujos de Generacin


Alternativa:
Declaracin de estructura va YAML:
Fichero: alumno.yml

Alumno:
columns:
nombre: string (255)
matricula: integer (8)

Ficheros
YAML

Base de
Datos

DAW 52

Doctrine_Core::generateModelsFromDb
Doctrine_Core::generateTablesFromModels
Doctrine_Core::generateSqlFromModels

Cdigo

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Alternativas de Flujos de Generacin


Model first:
echo 'Generando cdigo... ';
Doctrine_Core::generateModelsFromYaml(estructura.yml', '/Modelos');
echo hecho!\n";
echo 'Reconstruyendo tablas de la base de datos... ';
Doctrine_Core::dropDatabases();
Doctrine_Core::createDatabases();
Doctrine_Core::createTablesFromModels('/Modelos');
echo hecho!\n";

Database first:
echo 'Generando descripcin... ';
Doctrine_Core::generateYamlFromDb( estructura.yml', $conexion, $opciones );
echo hecho!\n";
echo 'Generando cdigo... ';
Doctrine_Core::generateModelsFromDb( '/Modelos', $conexion, $opciones );
echo hecho!\n";
DAW 53

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Limitaciones de Doctrine 1.2


La definicin de las tablas se hace desde la definicin de las
clase de forma programtica.
Si se hace desde la base de datos, la semntica de las
relaciones hay que hacerla a mano.
Hay mucho cdigo oscuro de PHP por debajo.
Todos los objetos de datos deben derivar de la clase
Doctrine_Record.

DAW 54

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Versin 2 basada en el patrn de implementacin Data
Mapper.
Inspirado en el diseo de la Java Persistence API (JPA).
El diseo separa el soporte de persistencia de la lgica de dominio:
Eso permite almacenar los objetos de datos no slo en SQL sino
tambin en NoSQL, XML,

Mejora en rendimiento sobre Doctrine 1.2 (x3).


Los objetos de datos no tiene que derivar de ninguna clase del
soporte de almacenamiento.
La seleccin de objetos y campos a almacenar se hace por medio de
anotaciones de mapeado.
Soportado desde PHP 5.3 e integrado en Symfony.
DAW 55

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Creacin de la clase:

namespace Entity;
class Alumno {
/** @var int */
private $matricula;

Mtodos (set/get):
/**
* @return int
*/
public function getMatricula() {
return $this->matricula;
}
/**
* @param int $matricula
*/
public function setMatricula($matricula) {
$this->matricula = (int) $matricula;
}
DAW 56

/** @var string */


private $nombre;

Constructor
/** Constructor
* @param int $matricula
*/
public function __construct($matricula) {
$this->setMatricula($matricula);
}

/**
* @return string
*/
public function getNombre() {
return $this->nombre;
}
/**
* @param string $nombre
*/
public function setNombre($nombre) {
$this->nombre = (string) $nombre;
}

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Anotaciones @ORM para
el mapeo de la clase:
Identificar lo que va a ser
una entidad (tabla).
Identificar los campos y sus
tipos.
Identificar la clave.

namespace Entity;

use Doctrine\ORM\Mapping as ORM;


/**
* @ORM\Entity
*/
class Alumno {
/**
* @ORM\Id()
* @ORM\Column(type="integer")
* @var int
*/
private $matricula;
/**
* @ORM\Column(type="string", length=255)
* @var string
*/
private $nombre;
}

DAW 57

// El resto

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Entity Manager (fichero config.php):
Es el componente encargado de almacenar/recuperar los datos entre
el objeto de datos (la clase) y el soporte de persistencia.
En PHP es necesario activar el soporte de autocargado que permite
que el intrprete de PHP, si encuentra una referencia a una clase y
no est declarada explcitamente el use correspondiente, la pueda
carga de forma dinmica:
use Doctrine\Common\ClassLoader;
//Autocargado
require_once __DIR__ . '/version/autoload.php';
$cargador1 = new ClassLoader('Entity', __DIR__ . '/Librerias');
$cargador1->register();
$cargador2 = new ClassLoader('EntityProxy', __DIR__ . '/Librerias');
$ cargador2 ->register();

DAW 58

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Entity Manager (fichero config.php, cont.):
Configuracin y metadatos:
use Doctrine\ORM\Configuration,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationRegistry,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\ORM\Mapping\Driver\AnnotationDriver;
//Configuracin
$config = new Configuration();
$cache = new ArrayCache();
$config->setQueryCacheImpl($cache);
$config->setProxyDir(__DIR__ . '/Librerias/EntityProxy');
$config->setProxyNamespace('EntityProxy');
$config->setAutoGenerateProxyClasses(true);
//mapping (example uses annotations, could be any of XML/YAML or plain PHP)
AnnotationRegistry::registerFile(__DIR__ . '/DoctrineDriver/DoctrineAnnotations.php');
$driver = new AnnotationDriver(new AnnotationReader(), array(__DIR__ . '/Librerias/Entity') );
$config->setMetadataDriverImpl($driver);
$config->setMetadataCacheImpl($cache);
DAW 59

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Entity Manager (fichero config.php, cont.):
Creacin del EntityManager:
Aqu se le pasan los parmetros (al estilo PDO) de cul es la BD que
actuar como repositorio.
use Doctrine\ORM\ EntityManager;
//Obtener el EntityManager
$em = EntityManager::create(
array(
'driver' => 'pdo_sqlite',
'path' => 'database.sqlite
),
$config);

DAW 60

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Creacin de la base de datos desde el modelo:
Para ello se crea un pequeo ejecutable (crear.php) que usar el
fichero anterior (config.php):
//crear.php
use Symfony\Component\Console\Helper\HelperSet,
Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper,
Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper,
Doctrine\ORM\Tools\Console\ConsoleRunner;
require_once __DIR__ . '/config.php';
$helperSet = new HelperSet(array(
'em' => new EntityManagerHelper($em),
'conn' => new ConnectionHelper($em->getConnection()) ));
ConsoleRunner::run($helperSet);

Que se lanzar como aplicacin de consola:


$ php crear.php orm:schema-tool:create
DAW 61

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo de uso (alta):
use Entity\Alumno;
require_once __DIR__ . '/config.php';
//Creamos un nuevo alumno
$elena = new Alumno(70212);
$elena->setNombre("Elena Nito del Bosque");

//Registramos a $elena en el EntityManager


$em->persist($elena);
//Cambiamos de nombre a $elena
$elena->setNombre("Elena Nito del Prado");
//Sincronizamos todos los cambios con la base de datos
$em->flush();
echo 'OK!';

DAW 62

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo de uso (bsqueda y modificacin):
require_once __DIR__ . '/config.php';
//Encontrar al alumno con matrcula = 70212
$alumno= $em->find('Entity\Alumno', 70212);
if($alumno) { //El EntityManager ha encontrado algn objeto de Entity\Alumno
echo 'He encontrado a un alumno (instancia de la clase ' . get_class($alumno)
. ') con nombre ' . $alumno->getNombre();
$alumno->setNombre("Cantalicio Floreal");
$em->flush();
}
else {
echo 'No he encontrado a nadie!!!';
}

DAW 63

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo de uso (bsqueda general):
require_once __DIR__ . '/config.php';
//Un repository es el concepto de tabla relacional
// que contiene entidades de un tipo (clase) determinado
$repo = $em->getRepository('Entity\Alumno');

//Buscar el alumno con nombre = "Elena Nito del Bosque"


$elenas = $repo->findBy(array('nombre' => 'Elena Nito del Bosque'));
//Mostrar resultados
echo 'Encontrados ' . count($elenas) . ' alumnos con ese nombre:' . PHP_EOL;
foreach($elenas as $el) {
echo ' - ' . $el->getMatricula() . PHP_EOL;
}

DAW 64

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo de uso (bsqueda DQL):
Extensin genrica similar a SQL.
require_once __DIR__ . '/config.php';
//Creamos una consulta DQL para buscar todos los alumnos del ao 07
$alumnos = $em
->createQuery('SELECT a FROM Entity\Alumno a '
. ' WHERE a.matricula >= 70000 AND a.matricula <= 79999')
->getResult();
//Mostrar resultados
echo 'Encontrados ' . count($alumnos) . ' alumnos de ese ao:' . PHP_EOL;
foreach($alumnos as $a) {
echo ' - ' . $a->getMatricula() . ": " . $a->getNombre() . PHP_EOL;
}

DAW 65

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo de uso (borrar):
require_once __DIR__ . '/config.php';
//Buscamos el ltimo matriculado
$alumnos = $em
->createQuery('SELECT a FROM Entity\Alumno a ORDER BY a.matricula DESC')
->setMaxResults(1) //slo vamos a querer un resultado
->getResult();
if(!empty($alumnos)) {
$al = reset($alumnos);
echo 'El ltimo nmero de matrcula es "' . $al->getMatricula()
. '" y corresponde al alumno "' . $al->getNombre() . '"' . PHP_EOL;
$em->remove($al);
$em->flush();
echo 'Alumno borrado!' . PHP_EOL;
}

DAW 66

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Definicin de relaciones:
En Doctrine las relaciones no se
establecen explicitando los identificadores
que se cruzan.
En cambio se dice las cardinalidades de
las relaciones de entidad contra entidad:
Un Alumno tiene N Notas
Una Nota pertenece a 1 Alumno.

Alumnos
tienen

Notas

Doctrine utiliza una nomenclatura propia:


Alumno::notas

OneToMany
inverted by

mapped by

ManyToOne

Nota::alumno

Alumno::notas es una relacin OneToMany con Notas mapeada por Nota::alumno


Nota::alumno es una relacin ManyToOne con Alumnos invertida por Alumno::notas
DAW 67

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Definicin de relaciones:
Cardinalidades disponibles:
OneToMany (mapped by ManyToOne)
ManyToOne (inversed by OneToMany)
OneToOne (inversed/mapped by OneToOne)
ManyToMany (inversed/mapped by ManyToMany)
Las relaciones OneToMany y ManyToMany se representan en

Doctrine como instancias del interfaz


Doctrine\Common\Collections\Collection.

DAW 68

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Definicin de relaciones:
Direccionalidad:
Las relaciones pueden ser uni- o bi-direccionales (inversibles).

Propietarios de las relaciones:


Toda relacin tiene uno de sus extremos que es propietario de la
misma.
Las relaciones bidireccionales tiene tanto lado propietario como lado
inverso.
Las relaciones unidireccionales slo tienen lado propietario.
El lado que es propietario es el que verifica Doctrine para propagar los
cambios.

Referencia:
http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html
DAW 69

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Modificamos la clase Alumno:
/**
* @ORM\OneToMany(targetEntity="Entity\Nota", mappedBy="alumno")
* @var Collection
*/
private $notas;
public function __construct($matricula) {
//Inicializamos la coleccin. Doctrine interpreta Collections, no arrays!
$this->notas = new ArrayCollection();
$this->setMatricula($matricula);
}
/** @return Collection */
public function getNotas() {
return $this->notas;
}
/** @param Nota $nota */
public function addNota(Nota $nota) {
$this->notas->add($nota);
$nota->setAlumno($this);
}
DAW 70

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Creamos la clase Nota:
/** @ORM\Entity */
class Nota {
/**@ORM\Id()
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
* @var int */
private $id;
/**@ORM\Column(type="string", length=255)
* @var string */
private $asignatura;
/**@ORM\Column(type="integer")
* @var int */
private $calificacion;
public function __construct($asignatura) {
$this->setAsignatura($asignatura);
}

continua

DAW 71

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Creamos la clase Nota:
/** @ORM\ManyToOne(targetEntity="Entity\Alumno", inversedBy="notas")
* @var Alumno|null
*/
private $alumno;
// Los getter y setter de $asignatura y de $calificacion
/** @return Alumno|null */
public function getAlumno() {
return $this->alumno;
}

/** @param Alumno $alumno */


public function setAlumno(Alumno $alumno) {
if($alumno === null || $alumno instanceof Alumno) {
$this->alumno = $alumno;
}
else {
throw new InvalidArgumentException('$alumno debe ser instancia de Entity\Alumno o null!');
}
}

DAW 72

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo (creacin):
use Entity\Alumno,
Entity\Nota;

require_once __DIR__ . '/config.php';


$chema = new Alumno(080332);
$chema->setNombe('Chema Pamundi');
$em->persist($chema);
$nota = new Nota('Danzas eslavas');
$nota->setCalificacion(10);
$em->persist($nota);
$alumno->addNota($nota);
$em->flush();

DAW 73

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo (consulta):
require_once __DIR__ . '/config.php';
$alumno = $em->find('Entity\Alumno', 080332);
if($alumno) {
echo 'Encontrado alumno: ' . PHP_EOL
. $alumno->getMatricula() . ' => ' . $alumno->getNombre() . '(' . get_class($alumno) . ')' . PHP_EOL
. 'y ' . $alumno->getNotas()->count() . ' Notas asociadas con l: ' . PHP_EOL;
foreach($alumno->getNotas() as $nota) {
echo ' ' . $nota->getAsignatura() . ': ' . $nota->getCalificacion()
. ' (' . get_class($nota) . ')' . PHP_EOL;
}

}
else {
echo 'No se ha encontrado alumno con matrcula=080332';
}

DAW 74

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo (borrado):
require_once __DIR__ . '/config.php';
$alumno = $em->find('Entity\Alumno', 080332);
if($alumno) {
echo 'Encontrado alumno: ' . PHP_EOL
. $alumno->getMatricula() . ' => ' . $alumno->getNombre() . '(' . get_class($alumno) . ')' . PHP_EOL
. 'y ' . $alumno->getNotas()->count() . ' Notas asociadas con l: ' . PHP_EOL;
foreach($alumno->getNotas() as $nota) {
$em->remove($nota);
}
$em->flush();

}
else {
echo 'No se ha encontrado alumno con matrcula=080332';
}

DAW 75

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Doctrine 2
Ejemplo (consultas con DQL):
require_once __DIR__ . '/config.php';
echo 'Obtener todas las matrculas de honor de el ao 08: ' . PHP_EOL;
$alumnos = $em
->createQuery('SELECT a FROM Entity\Alumno a JOIN a.notas n WHERE
. ' n.calificacion >= :calificacion AND
. ' a.matricula >= (:ano*10000) AND a.matricula < ((:ano+1)*1000)')
->setParameter('calificacion', 10)
->setParameter('ano', 8)
->getResult();
echo 'Se encontraron ' . count($alumnos) . ' casos:' . PHP_EOL;
foreach($alumnos as $al) {
echo ' ' . $alumno->getMatricula() . ' => ' . $alumno->getNombre() . PHP_EOL;
}

DAW 76

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Bases de Datos NoSQL Documentales


No todo es SQL:
Ms prximas a lo que sera el concepto
de un ORM.
Son objetos que directamente se pueden
guardar y recuperar.
Pero el sustrato de almacenamiento ya no
es una BD relacional.
Formatos de almacenamiento
documental: XML, YAML, JSON o BSON.
Bases de datos documentales puras:
MongoDB o CouchDB
Otras variantes: Cassandra o Redis
Extensiones de RDBMS: PostgresSQL o
Informix
DAW 77

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Bibliografa
Gilmore, W.J. (2010) Beginning PHP 5 and MySQL: From
Novice to Professional
Romer, M. (2013). Persistence in PHP with the Doctrine 2
ORM. Concepts, Techniques & Practical Solutions.
Tutoriales:
http://php.net/manual/es/set.mysqlinfo.php
http://php.net/manual/es/book.pdo.php
http://doctrine-orm.readthedocs.org/en/latest/tutorials/getting-started.html
https://github.com/Ocramius/Doctrine2ORMSlidesTutorial (M. Pivetta)

DAW 78

Santiago Rodrguez Santiago Gonzlez Fernando Prez


Juan Morales
Antonio LaTorre Francisco Rosales
Jos M. Pea

Vous aimerez peut-être aussi