Este documento resume las Jornadas Symfony que tendrán lugar los días 5 y 6 de julio de 2010 en la Universitat Jaume I de Castellón. Incluye información sobre las charlas de Doctrine y Symfony que se presentarán, así como ejemplos prácticos sobre el uso de Doctrine para crear aplicaciones con Symfony.
9. El modelo (relaciones)
public function setUp()
{
parent::setUp();
$this->hasMany('Tag as Tags', array(
'refClass' => 'TodoTag',
'local' => 'todo_id',
'foreign' => 'tag_id'));
$this->hasMany('Item as items', array(
'local' => 'id',
'foreign' => 'todo_id'));
$this->hasMany('TodoTag', array(
'local' => 'id',
'foreign' => 'tag_id'));
//Behaviour
$timestampable0 = new Doctrine_Template_Timestampable();
$this->actAs($timestampable0);
}
}
Jornadas Symfony http://decharlas.uji.es/symfony
10. Fixtures (Doctrine 1)
Todo:
denver:
name: Cosas que hacer en Denver
description: Cuando hayamos muerto
Item:
gambas:
name: Comer gambas
Todo: denver
gangsters:
name: Cosas de gangsters
Todo: denver
Tag:
turismo:
name: Turismo gangsteril
Todos: [denver]
Jornadas Symfony http://decharlas.uji.es/symfony
11. DQL
●
Simplifica SQL y es portable
●
Incorpora POO a SQL
Jornadas Symfony http://decharlas.uji.es/symfony
12. DQL
$q = Doctrine_Query::create()
->select('l.*, i.name, t.name')
->from('Todo l')
->innerJoin('l.Items i')
->leftJoin('l.Tags t');
echo $q->getSqlQuery();
SELECT t.id AS t__id, t.name AS t__name, t.description
AS t__description, t.created_at AS t__created_at,
t.updated_at AS t__updated_at, i.id AS i__id, i.name AS
i__name, t2.id AS t2__id, t2.name AS t2__name FROM
todo t INNER JOIN item i ON t.id = i.todo_id LEFT JOIN
todo_tag t3 ON (t.id = t3.todo_id) LEFT JOIN tag t2 ON
t2.id = t3.tag_id
Jornadas Symfony http://decharlas.uji.es/symfony
13. Objetos
Métodos de acceso y manipulación
$list = new Todo();
//Manipulación
1 $list->name = "Cosas que hacer en Denver";
2 $list['name'] = "Cosas que hacer en Denver";
3 $list->set('name', "Cosas que hacer en Denver");
//Acceso
1 echo $list->name;
2 echo $list['name']; //Recomendado (hidratación)
3 echo $list->get('name');
Jornadas Symfony http://decharlas.uji.es/symfony
14. Hidratación (I)
●
En objetos
●
En arrays (más rápido)
●
Scalar
●
Single Scalar
●
Bajo demanda
●
…
¿No es suficiente?
¡Escribe el tuyo!
Jornadas Symfony http://decharlas.uji.es/symfony
17. Hidratación (III)
●
El acceso por arrays funciona en los dos
métodos de hidratación
●
La hidratación por arrays es más eficiente
si solo queremos consultar datos directos
de la BD
●
fetchArray() es un alias de execute() con
la hidratación por array
●
Uso de foreach, count(), isset(), unset()
Jornadas Symfony http://decharlas.uji.es/symfony
18. Definiendo setters/getters
class Todo extends BaseTodo
{
//Nuevo getter
public function getDescriptionHtml()
{
return Markdown::parse(htmlspecialchars(
$this->description));
}
//Sobrecarga del setter
public function setDescription($description)
{
return $this->_set('description',
Markdown::parse(htmlspecialchars($description)));
}
}
Jornadas Symfony http://decharlas.uji.es/symfony
19. Relaciones
$list = new Todo();
$list['name'] = "Libros para este verano";
$list->Items[]->name = "Hablemos de Langostas";
$list->save();
//Usando link()
●
Las relaciones son $item = new Item();
intuitivas $item['name'] = "La broma infinita";
$item->link('Todo',array($list['id']));
●
Siempre podemos recurrir $item->save();
a DQL //Borrar
$list->Items[0]->delete();
●
Pero en DQL no se
//Siempre nos quedará DQL
ejecutarán preDelete(), $q = Doctrine_Query::create()
postDelete()... (!) ->delete('Item')
->addWhere('todo_id = ?', $list['id'])
->whereIn('name', array($item['name'], 'otro
nombre'));
$q->execute();
Jornadas Symfony http://decharlas.uji.es/symfony
20. Many to many Array
$q = Doctrine_Query::create() (
[0] => Array
->from('Todo l')
(
->leftJoin('l.TodoTag tt') [id] => 27
->leftJoin('tt.Tag t'); [name] => Cosas que hacer en Denver
print_r($q->fetchArray()); [description] => Cuando hayamos muerto
[created_at] => 2010-06-23 20:35:41
//Equivalente [updated_at] => 2010-06-23 20:35:41
$q = Doctrine_Query::create() [TodoTag] => Array
->from('Todo l') (
->leftJoin('l.Tags t'); [0] => Array
print_r($q->fetchArray()); (
[tag_id] => 2
[todo_id] => 27
●
Podemos “olvidarnos” [Tag] => Array
(
de la tabla intermedia [id] => 2
[name] => Turismo
)
)
)
)
)
Jornadas Symfony http://decharlas.uji.es/symfony
25. Entidades (II)
public function getId()
{
return $this->id;
}
public function getNombre()
{
return $this->nombre;
}
public function setNombre($nombre)
{
$this->nombre = $nombre;
}
public function getDireccion()
{
return $this->direccion;
}
public function setDireccion(Direccion $direccion)
{
if ($this->direccion !== $direccion) {
$this->direccion = $direccion;
$direccion->setUsuario($this);
}
}
}
Jornadas Symfony http://decharlas.uji.es/symfony
26. Entidades (III)
●
No descienden de ninguna clase, están
“separadas” del ORM, aunque mapeadas
por él
●
Menos magia. Es más fácil entender qué
está pasando
●
Más rápidas
●
Herencia
●
Gestionadas por el Entity Manager
●
Sí, se pueden escribir en YAML y XML ;)
Jornadas Symfony http://decharlas.uji.es/symfony
27. Fixtures
$em = $this->getEntityManager();
$user1 = new ModelsUsuario();
$user1->nombre = 'Nacho';
●
Adiós al YAML. Se escriben en PHP
●
¿Por qué?
●
Es más rápido cargarlas
●
El código para tratar fixtures en YAML introdujo muchos
bugs en el pasado
Jornadas Symfony http://decharlas.uji.es/symfony
28. persist() y flush()
$user = new EntitiesUsuario;
$user->setNombre('Nacho');
$entitymanager->persist($user);
$entitymanager->flush();
●
Atención al uso de espacios de nombre
●
Persist “marca” el objeto para guardar
●
Flush ejecuta la unidad de trabajo
Jornadas Symfony http://decharlas.uji.es/symfony
30. Rendimiento (II)
●
Doctrine2 gestiona las transacciones por
nosotros
●
Así que es más rápido que código
PHP+SQL mal optimizado
●
(Por supuesto usar transacciones en
PHP+SQL es más rápido que Doctrine2)
●
También podemos controlar las
transacciones nosotros
Jornadas Symfony http://decharlas.uji.es/symfony
31. Eventos Lifecycle
●
pre/postRemove
●
pre/postPersist
●
pre/postUpdate
●
postLoad : carga desde BD
●
loadClassMetadata : carga desde metadatos
(annotations, yaml, xml)
●
onFlush
/** @Entity @HasLifecycleCallbacks */
class Usuario
{
//(...)
/** @PostPersist */
public function doAlgoOnPostPersist()
{
$this->nombre = 'Me han cambiado en el postpersist';
}
Jornadas Symfony http://decharlas.uji.es/symfony
32. Behaviours (I)
En Doctrine2 son código normal de PHP que
extiende la funcionalidad base de las entidades
/** @HasLifecycleCallbacks */
class BlogPost
{
//(...)
public function __construct()
{
$this->created = $this->updated = new DateTime("now");
}
/**
* @PreUpdate
*/
public function updated()
{
$this->updated = new DateTime("now");
}
}
Jornadas Symfony http://decharlas.uji.es/symfony
33. Behaviours (II)
¿Pero cómo hacer el código reutilizable entre
entidades?
Usando interfaces, eventos y código PHP
orientado a objetos
Ejemplos:
http://github.com/guilhermeblanco/Doctrine2-Sluggable-Functional-Behavior
http://github.com/guilhermeblanco/Doctrine2-Hierarchical-Structural-Behavior
http://www.doctrine-project.org/blog/doctrine2-versionable
Jornadas Symfony http://decharlas.uji.es/symfony
34. Migraciones (I)
Hacen el esquema versionable
BD (antes) BD (después)
Esquema Fichero de
migración
Jornadas Symfony http://decharlas.uji.es/symfony
35. Migraciones (I)
Hacen el esquema versionable
BD (antes) BD (después)
Comparar
Esquema Fichero de
migración
Jornadas Symfony http://decharlas.uji.es/symfony
36. Migraciones (I)
Hacen el esquema versionable
BD (antes) BD (después)
Comparar
Generar
Esquema Fichero de
migración
Jornadas Symfony http://decharlas.uji.es/symfony
37. Migraciones (I)
Hacen el esquema versionable
BD (antes) BD (después)
Comparar
Generar
Esquema Fichero de
migración
Jornadas Symfony http://decharlas.uji.es/symfony
39. Migraciones (II)
Aspecto de un fichero de migración
class Version20100416130401 extends AbstractMigration
{
public function up(Schema $schema)
{
$table = $schema->createTable('users');
$table->addColumn('username', 'string');
$table->addColumn('password', 'string');
}
public function down(Schema $schema)
{
$schema->dropTable('users');
}
}
Jornadas Symfony http://decharlas.uji.es/symfony
40. Migraciones (III)
Gestionadas desde la consola:
●
Diff: tras cambiar una entidad, genera la
migración necesaria para cambiar la BD
●
Dry-run: muestra el SQL para cerciorarnos de
que es lo que esperamos
●
Status: muestra en qué estado (versión,
migraciones posibles, fecha...) estamos
●
Migrate: ejecuta la migración (hacia adelante o
hacia atrás → revertir)
●
Write-sql: en lugar de migrar, escribe el SQL a
un fichero
Jornadas Symfony http://decharlas.uji.es/symfony
41. MongoDB (ODM)
●
El ODM tiene el mismo aspecto que el ORM
(métodos parecidos, Entidad → Documento,
EntityManager → DocumentManager,...)
●
Mañana hay una charla sobre MongoDB y
Symfony ;)
Jornadas Symfony http://decharlas.uji.es/symfony
42. ¿Preguntas?
Si surgen más tarde ;) :
nitram.ohcan@gmail.com
twitter:@nacmartin
http://nacho-martin.com
Jornadas Symfony http://decharlas.uji.es/symfony