Académique Documents
Professionnel Documents
Culture Documents
PHP
Gestin de Datos
DAW 2
MySQL en PHP
API de MySQL y MySQLi
DAW 3
La referencia al servidor se
realiza con el formato:
servidor:puerto
Por ejemplo:
laurel.datsi.fi.upm.es:4577
DAW 5
DAW 7
DAW 8
Gestin de errores:
int mysql_errno ([ resource $link_identifier = NULL ] )
string mysql_error ([ resource $link_identifier = NULL ] )
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 ]]]]] )
DAW 14
PHP 5
PHP 5.5.0
API (orientada a objetos) de MySQL:
Objeto mysqli
mysqli {
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
DAW 17
DAW 18
DAW 19
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 {
PostgreSQL:
MySQL:
SQLite:
DAW 20
Interfaz PDO
Ejecucin de consultas que devuelven registros:
public PDOStatement PDO::query ( string $statement )
}
catch (PDOException $e) {
echo $e->getMessage();
}
DAW 21
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');
DAW 22
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" );
}
catch(PDOException $e) {
echo $e->getMessage();
}
DAW 23
Limitaciones PDO
No quiero escribir ms SQL!!!!!
DAW 25
Necesidades de Almacenamiento de
Objetos
Limitaciones de Soluciones Relacionales y
Serializacin de Objetos en PHP
DAW 26
DAW 27
DAW 28
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
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"}
]}
Serializacin en PHP
Se apoya en dos mtodos:
string serialize ( mixed $value )
mixed unserialize ( string $str )
Que devuelve un array de los strings de los campos a serializar. Dicha funcin se invoca
inmediatamente antes de serializar.
void __wakeup ( void )
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
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
Proyeccin Objeto-Relacional
ORM General y Versiones de Doctrine
DAW 34
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.
DAW 35
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).
Object-Relational Mapping
Clase:
Aula
nmero: int
bloque: int
plazas: int
Data mapper:
Convierte:
Clase Tabla
Objeto Fila
ORM
AULAS
PK id
nmero
bloque
plazas
DAW 37
VARCHAR(12)
INTEGER
INTEGER
INTEGER
Tabla:
El atributo identificador es
tpicamente la clave primaria.
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
Object-Relational Mapping
Funcionalidades de almacenamiento:
Almacenamiento explcito:
Se indica explcitamente cundo y qu almacenar.
Llamada de tipo save().
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
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
Active Record
Data Mapper
$alumna->save();
EntityManager::persist($alumna);
Doctrine 1.2
Doctrine 2
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().
DAW 43
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)
creado
Registrar
Liberar
gestionado
eliminado
Buscar
Registrar
Desregistrar
Combinar
desacoplado
DAW 45
basura
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.
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()
Doctrine
Implementacin de un ORM para PHP.
Versin Doctrine 1.2 basada en el patrn de implementacin de
Active Record.
Wikipedia
DAW 48
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
Doctrine 1.2
Las relaciones entre tablas se disean como relaciones entro
clases:
Doctrine 1.2
$elena = new Alumno();
$elena->nombre ="Elena Nito del Bosque";
$elena->matricula = 70212;
Alumnos
tienen
$elena->Notas[] = $nota;
Notas
$nota->Alumno = $elena;
$elana->save();
ALUMNOS
Matrcula
Nombre
70212
DAW 51
NOTAS
Matrcula
Asignatura
Calificacin
70212
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
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
DAW 54
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,
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
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;
}
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;
DAW 57
// El resto
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
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
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
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);
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");
DAW 62
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
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');
DAW 64
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
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
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
OneToMany
inverted by
mapped by
ManyToOne
Nota::alumno
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
DAW 68
Doctrine 2
Definicin de relaciones:
Direccionalidad:
Las relaciones pueden ser uni- o bi-direccionales (inversibles).
Referencia:
http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html
DAW 69
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
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
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;
}
DAW 72
Doctrine 2
Ejemplo (creacin):
use Entity\Alumno,
Entity\Nota;
DAW 73
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
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
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
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