Este documento fornece um resumo sobre abstração de banco de dados com PHP Doctrine. Ele discute o que é ORM e Doctrine, apresentando seus principais recursos como models, DQL, fixtures e caching. O documento também fornece um exemplo prático de como configurar e usar o Doctrine.
1. abstração do banco de dados com
PHP Doctrine
Marcelo Akira – marcelo.akira@gmail.com
Otávio Calaça – otaviocx@gmail.com
Goiânia, 02 de outubro de 2009
2. Grupo de Desenvolvedores
PHP de Goiás
Criado em dezembro de 2007;
Lista de Discussão:
− Mais 300 membros.
Encontros:
− Palestras;
− Networking.
Site:
− www.gophp.com.br
Eventos:
− FLISOL, FGSL, Latinoware, Conisli, CONSOFT, PHP
Conference Brasil ...
3. Abstração do banco de dados
com PHP Doctrine
Roteiro
• O que é ORM?
– Por que classes e não tabelas?
• O que é Doctrine?
– Models
• Padrão Active Record
– Principais Recursos
• Arquivos YAML de Schema ●
DQL
• Data fixtures ●
Listeners
• Caching ●
Behaviors
• Exemplo Prático
3
4. Abstração do banco de dados
com PHP Doctrine
O que é ORM?
• Mapeamento Objeto-Relacional;
• Ponte entre objetos e um BD Relacional;
• Tabelas são representadas por Classes;
• Registros por Objetos;
• Relações são Associações;
• Abstrai detalhes do SGBD (SQL e métodos
nativos);
4
5. Abstração do banco de dados
com PHP Doctrine
Por que classes e não tabelas?
• Em uma linguagem orientada a objetos,
como PHP, é mais fácil lidar com classes e
objetos que com tabelas relacionais;
• Classes possuem métodos que podem
introduzir comportamentos às entidades
(antes tabelas) do sistema.
5
6. Abstração do banco de dados
com PHP Doctrine
O que é Doctrine?
• Uma framework ORM para PHP;
• Funciona com PHP 5.2.3+;
• Inspirado no Hibernate (Java) e no
ActiveRecord (Ruby on Rails);
• Possui uma linguagem orientada a objetos
em substituição ao SQL (DQL).
6
7. Abstração do banco de dados
com PHP Doctrine
Mais sobre o Doctrine
• Foi criado por 2006 por Konsta Vesterinen
(Inativo);
• Há um brasileiro participando no 'core
team' (Guilherme Blanco);
• A versão 1.0 foi lançada em Setembro de
2008;
• É utilizado no framework Symphony;
7
8. Abstração do banco de dados
com PHP Doctrine
Abstração de base de dados
• Utiliza PDO (PHP Data Objects): uma
implementação oficial do PHP para
abstração de acesso a dados;
• Banco de dados suportados: MySQL,
PostgreSQL, Oracle, MS SQL, Firebird,
etc.
• A utilização de PDO diminui a dependência
de Banco de Dados, aumentando a
portabilidade de seu sistema;
8
9. Abstração do banco de dados
com PHP Doctrine
Padrão ActiveRecord
• O Doctrine implementa o padrão de projeto
Active Record;
• Este padrão foi definido por Martin Fowler,
que mapeia tabelas como classes e
linhas como objetos e define métodos de
acesso;
9
10. Abstração do banco de dados
com PHP Doctrine
Exemplo: Active Record
class Funcionario {
private $nome, $matricula, $salario ...
public function salvar() ...
public static function localizar($campo, $valor)...
public function aumentarSalario( $percentual )...
public function calcularFerias() ....
...
}
$f = Funcionario::localizar('matricula', '123');
$f.aumentarSalario( 1000 );
$f.salvar();
10
11. Abstração do banco de dados
com PHP Doctrine
Active Record: Models do Doctrine
class User extends Doctrine_Record {
public function setTableDefinition() {
$this->hasColumn('username', 'string', 255, array(
'type' => 'string', 'length' => '255'
)
);
$this->hasColumn('password', 'string', 255, array(
'type' => 'string', 'length' => '255'
)
);
}
public function setUp() {
$this->hasMany('Group as Groups', array(
'refClass' => 'UserGroup',
'local' => 'user_id',
'foreign' => 'group_id'
)
);
}
}
11
12. Abstração do banco de dados
com PHP Doctrine
Active Record: Models do Doctrine
class Group extends Doctrine_Record {
public function setTableDefinition() {
$this->setTableName('groups');
$this->hasColumn('name', 'string', 255, array(
'type' => 'string', 'length' => '255'
)
);
}
public function setUp() {
$this->hasMany('User as Users', array(
'refClass' => 'UserGroup',
'local' => 'group_id',
'foreign' => 'user_id'
)
);
}
}
12
13. Abstração do banco de dados
com PHP Doctrine
Active Record: Models do Doctrine
• Usando um model:
$group = new Group();
$group1 = new Group(); $group->name = 'Palestrantes';
$group1->name = 'Palestrantes';
$user1 = new User();
$group2 = new Group(); $user1->username = 'otavio';
$group2->name = 'PHP'; $user1->password = '123456';
$user = new User(); $user2 = new User();
$user->username = 'otavio'; $user2->username = 'akira';
$user->password = '123456'; $user2->password = '654321';
$user->Groups[] = $group1;
$user->Groups[] = $group2; $group->Users[] = $user1;
$group->Users[] = $user2;
$user->save(); $group->save();
13
14. Abstração do banco de dados
com PHP Doctrine
Onde começar?
• Baixe o pacote Sandbox (caixa de areia)
– http://www.doctrine-project.org/download
• Siga a introdução My First Project (Meu
primeiro Projeto), disponível em:
– http://www.doctrine-
project.org/documentation/cookbook/1_1/e
n/my-first-project
14
15. Abstração do banco de dados
com PHP Doctrine
Diretórios do Sandbox
$ cd Doctrine1.1.4Sandbox
$ ls
config.php – configuração do doctrine
data/ pasta para dados iniciais (fixture)
doctrine utilitário de linha de comando
doctrine.php – códigofonte do utilitário
index.php um exemplo de arquivo inicial
lib/ bibliotecas do doctrine
migrations/ pasta para classes de migração
models/ pasta para arquivos de modelos
schema/ pasta para arquivos de estruturas
15
16. Abstração do banco de dados
com PHP Doctrine
Configurando o Doctrine
$ vi config.php
define('SANDBOX_PATH', dirname(__FILE__));
define('DOCTRINE_PATH', SANDBOX_PATH . DIRECTORY_SEPARATOR . 'lib');
... define vários outros caminhos ...
// Configurar o DSN é importante para definir o BD
define('DSN', 'mysql://root:123456@localhost/doctrine_testes');
... outras configurações ...
16
17. Abstração do banco de dados
com PHP Doctrine
Utilitário de linha de comando
$ cd Doctrine1.1.4Sandbox
$ ./doctrine
...
./doctrine createtables – cria tabelas
./doctrine loaddata – carrega dados inicial
./doctrine dql – executa dql
./doctrine generateyamlmodels – gera modelos
... vários outros comandos ...
17
18. Abstração do banco de dados
com PHP Doctrine
Definindo estrutura com YAML 1/2
• Uma das formas de definir uma estrutura, é
criando um arquivo schema.yml no
diretório schema.
18
19. Abstração do banco de dados
com PHP Doctrine
Definindo estrutura com YAML 2/2
... continuação ... continuação
User: Group: UserGroup:
columns: tableName: groups columns:
id: columns: user_id: integer(4)
primary: true id: group_id: integer(4)
autoincrement: true primary: true relations:
type: integer(4) autoincrement: true User:
username: string(255) type: integer(4) onDelete: CASCADE
password: string(255) name: string(255) Group:
relations: onDelete: CASCADE
Groups:
class: Group
refClass: UserGroup
foreignAlias: aUsers
Continua ... Continua ...
19
20. Abstração do banco de dados
com PHP Doctrine
Gerando tabelas e modelos
• Uma vez criado o arquivo .yml no diretório schema, você
pode executar o comando seguinte para criar
automaticamente a base de dados, as tabelas e as
classes-modelos.
$ ./doctrine buildall
buildall Generated models successfully from YAML schema
buildall Successfully created database for connection "doctrine"
named "doctrine_testes"
buildall Created tables successfully
20
21. Abstração do banco de dados
com PHP Doctrine
Testando
<?php Esse resultado abaixo é
esperado, uma vez que a base
require_once('config.php'); de dados está vazia.
Doctrine::loadModels('models');
<pre>
$query = new Doctrine_Query();
$query->from('User u, u.Groups g'); // resulta => Array
(
$users = $query->execute(); )
</pre>
echo '<pre>';
print_r($users->toArray(true));
echo '</pre>';
?>
21
22. Abstração do banco de dados
com PHP Doctrine
Utilizando fixture
• Para popular dados no bd, pode-se criar
um arquivo dados.yml em data/fixtures:
User:
zyne:
username: zYne
password: changeme
Groups: [founder, lead, documentation]
jwage:
username: jwage
password: changeme
Groups: [lead, documentation]
Group:
founder:
name: Founder
lead:
name: Lead
documentation:
name: Documentation
22
23. Abstração do banco de dados
com PHP Doctrine
Populando a base de dados
• Pode-se carregar novamente as bases de dados e
popular o BD:
$ ./doctrine buildallreload
buildallreload Are you sure you wish to drop your databases?
(y/n)
y
buildallreload Successfully dropped database for connection
"doctrine" named "doctrine_testes"
buildallreload Generated models successfully from YAML schema
buildallreload Successfully created database for connection
"doctrine" named "doctrine_testes"
buildallreload Created tables successfully
buildallreload Data was successfully loaded
23
24. Abstração do banco de dados
com PHP Doctrine
Testando novamente
$ php index.php
Array
(
[0] => Array
(
[id] => 1
[username] => zYne
[password] => changeme
[Groups] => Array
(
[0] => Array
(
[id] => 1
[name] => Founder
)
Dados do BD ...
24
25. Abstração do banco de dados
com PHP Doctrine
Caching
• Armazenar consultas em memória, não
sendo necessário conectar no banco
novamente para fazer a mesma consulta.
• Memcache:
$options = array();
$cacheDriver = new Doctrine_Cache_Memcache($options);
• DB:
$cacheConn = Doctrine_Manager::connection(new PDO('sqlite::memory:'));
$cacheDriver = new Doctrine_Cache_Db(array('connection' => $cacheConn));
• APC: $cacheDriver = new Doctrine_Cache_Apc();
25
26. Abstração do banco de dados
com PHP Doctrine
Caching
• Usando:
$q = Doctrine_Query::create()
->from('Post p')
->leftJoin('p.Comentarios c')
->leftJoin('p.Tags t')
->useResultCache($cacheDriver);
• Ou:
$manager->setAttribute(Doctrine::ATTR_RESULT_CACHE, $cacheDriver);
$q = Doctrine_Query::create()
->from('Post p')
->leftJoin('p.Comentarios c')
->leftJoin('p.Tags t')
->useResultCache(true);
26
27. Abstração do banco de dados
com PHP Doctrine
Doctrine Query Language
• Consultas ao banco de dados usando
orientação a objetos;
• Gera SQLs complexas a partir de coisas
simples;
• Funções específicas do DB são
suportadas.
27
28. Abstração do banco de dados
com PHP Doctrine
Doctrine Query Language
• DQL: • SQL:
SELECT
u.id AS u__id,
u.is_active AS u__is_active,
$q = Doctrine_Query::create() u.is_super_admin AS u__is_super_admin,
u.first_name AS u__first_name,
->from('User u') u.last_name AS u__last_name,
->leftJoin('u.Phonenumbers p'); u.username AS u__username,
u.password AS u__password,
u.type AS u__type,
u.created_at AS u__created_at,
u.updated_at AS u__updated_at,
p.id AS p__id,
p.user_id AS p__user_id,
p.phonenumber AS p__phonenumber
FROM user u
LEFT JOIN phonenumber p ON u.id = p.user_id
28
29. Abstração do banco de dados
com PHP Doctrine
Listeners
• O Doctrine possui listeners para
transações, conexões, querys e records;
• Exemplo:
class User extends Doctrine_Record
{
// ...
public function preInsert(Doctrine_Event $event)
{
$event->getInvoker()->created = date('Y-m-d', time());
$event->getInvoker()->updated = date('Y-m-d', time());
}
public function preUpdate(Doctrine_Event $event)
{
$event->getInvoker()->updated = date('Y-m-d', time());
}
}
29
30. Abstração do banco de dados
com PHP Doctrine
Behaviors
• Comportamentos;
– Versionable;
– Timestampable;
– Sluggable;
– I18n;
– outros...
30
31. Abstração do banco de dados
com PHP Doctrine
Behaviors
• Exemplo:
class User extends Doctrine_Record
{
// ...
public function setUp()
{
// ...
$this->actAs('Timestampable');
$this->actAs('Sluggable', array(
'unique' => true,
'fields' => array('titulo'),
'canUpdate' => true
)
);
}
}
31
33. Abstração do banco de dados
com PHP Doctrine
Referências
• Site do Doctrine: http://www.doctrine-project.org
• Padrão Active Record: http://pt.wikipedia.org/wiki/Active_record
• Slides s/ Doctrine: http://www.slideshare.net/guilhermeblanco
• PDO: http://br2.php.net/pdo
• Manual do Doctrine:
33
34. Abstração do banco de dados
com PHP Doctrine
FIM
Perguntas?
Marcelo Akira – marcelo.akira@gmail.com
Otávio Calaça – otaviocx@gmail.com
Obrigado!
34