Sei sulla pagina 1di 11

Capítulo 6

PHP Data Objects (PDO)

6.1 O que é o PDO?

Muitas aplicações ainda utilizam a extensão clássica do MySQL, ou então as exten-


sões nativas de PostgreSQL e SQLite, para comunicação com estes bancos. Não só
as aplicações ficam atreladas a um banco específico, mas a manutenção se torna
difícil e, imagine então, se for necessária uma migração de um banco de dados para
outro, por exemplo do MySQL para PostgreSQL? O PDO é uma solução inteligente
para esse problema bastante complexo. O PDO é uma camada de abstração de
acesso a dados, que significa que, independente do banco de dados que você está
utilizando, poderá usar as mesmas funções para executar queries e consultar da-
dos.

Vamos ver, na prática, exemplos de como usar o PDO, como ele torna seu código
mais fácil de manter, e porque é importante não atrelar sua aplicação a um banco
de dados específico. O PDO, PHP Data Objects, foi introduzido no PHP 5.1 e dá
suporte a várias sistemas gerenciadores de banco de dados, como MySQL, Post-
greSQL, SQLite, Informix, Oracle, SQL Server, IBM, entre outros. Além disso, ele
torna fácil a criação de prepared statements e transactions nestes sistemas, se pre-
cisar atrelar seu sistema a funcionalidades específicas de cada extensão de cada
banco de dados.

63
6.2 Conexão 4Linux – www.4linux.com.br

6.2 Conexão

A conexão com um banco de dados através do PDO se dá durante a instanciação do


objeto da classe PDO, passando as informações de conexão com o banco na forma
de uma DSN, ou data source name, além das credenciais de acesso. Portanto, o
método construtor da classe PDO espera três parâmetros:

1 <? php
2
3 // MySQL
4 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
5
6 // PostgreSQL
7 $db = new PDO (" pgsql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
8
9 // SQLite
10 $db = new PDO (" sqlite : meubanco . sqlite ");

Uma vez que o objeto da classe PDO tenha sido instanciado, estamos conectados
com nosso banco. Para desconectarmos, podemos matar o objeto ou aguardar que
ele seja morto automaticamente ao final do script.

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4
5 unset ( $db );

Página 64 Desenvolvimento Orientado a Objetos com PHP


4Linux – www.4linux.com.br 6.3 Executando comandos

6.3 Executando comandos

Depois de conectar com o banco de dados instanciando um objeto da classe PDO,


podemos chamar alguns métodos desse objeto para executarmos comandos em
nosso sistema gerenciador de banco de dados usando a linguagem SQL. Para exe-
cutar estes comandos, vamos fazer uso do método exec.

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $db -> exec (" CREATE TABLE posts ( id INT AUTO_INCREMENT , titulo VARCHAR
(255) , conteudo TEXT )");

Através do método exec podemos manipular nosso banco de dados da maneira que
quisermos utilizando SQL. Este método sempre retornará o número de linhas afe-
tadas pelos nossos comandos. Observe que, caso nenhuma linha seja afetada, o
método retornará zero.

6.4 Fazendo consultas

Podemos utilizar o método exec para executar qualquer comando SQL em nosso
banco, mas quando quisermos fazer consultas, precisamos utilizar outro método. O
método query executa um comando SQL e retorna um objeto da classe PDOSta-
tement contendo os resultados da consulta feita. Objetos da classe PDOStatement
podem ser iterados, já que são uma coleção de dados retornados pela nossa con-
sulta.

1 <? php
2

Desenvolvimento Orientado a Objetos com PHP Página 65


6.4 Fazendo consultas 4Linux – www.4linux.com.br

3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $dados = $db -> query (" SELECT * FROM posts ");

Agora que já temos nossa consulta feita, precisamos acessar os dados retornados
por ela de alguma forma, certo? Os métodos fetch e fetchAll servem para isso. O
método fetch irá retornar apenas um resultado de nossa consulta, enquanto o método
fetchAll irá retornar todos os resultados. Estes métodos podem retornar um array ou
um objeto, dependendo dos parâmetros passados.

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $dados = $db -> query (" SELECT * FROM posts ");
5 $todos = $dados -> fetchAll () ;
6 $um = $dados -> fetch () ;
7
8 print_r ( $todos );
9 print_r ( $um );

Observe que, por padrão, os métodos fetch e fetchAll retornam índices associativos
(com os nomes de nossas colunas) e numéricos (dando uma posição para cada
coluna de acordo com a ordem original). Podemos fazer com que somente índices
associativos sejam trazidos, ou apenas numéricos:

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $dados = $db -> query (" SELECT * FROM posts ");
5 $associativo = $dados -> fetchAll ( PDO :: FETCH_ASSOC );
6 $numerico = $dados - > fetchAll ( PDO :: FETCH_NUM );
7

Página 66 Desenvolvimento Orientado a Objetos com PHP


4Linux – www.4linux.com.br 6.5 Transactions

8 print_r ( $associativo );
9 print_r ( $numerico );

Podemos configurar os métodos fetch e fetchAll para, ao invés de retornarem um


array, retornarem um objeto anônimo onde as propriedades são nossas colunas:

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $dados = $db -> query (" SELECT * FROM posts ");
5 $obj = $dados -> fetchAll ( PDO :: FETCH_OBJ );
6
7 echo $obj -> titulo ;

6.5 Transactions

Transactions, ou transações, são uma sequência de operações feitas em um sistema


gerenciador de banco de dados, tratadas de maneira coerente e confiável, indepen-
dente de outras transações. As transações têm o objetivo de isolar programas que
acessam um banco concorrentemente e proporcionar uma maneira de recuperar in-
formações a partir de um desastre. Uma transação de banco de dados deve possuir,
por definição, atomicidade, consistência, isolamento e durabilidade (ACID).

Com transações podemos garantir que sempre iremos manipular nosso banco de
dados de maneira confiável. Por exemplo: estamos cadastrando uma compra em
nosso banco de dados. Além de inserir as informações de compra em uma tabela,
precisamos inserir e alterar informações em outras tabelas, como a tabela de esto-
que, pedido, cliente e logística. Caso haja um erro em qualquer um destes passos,
teríamos um grande problema em mãos. Imagine um problema na inserção de in-
formações na tabela de logística. O cliente pagou, tudo ocorreu aparantemente bem

Desenvolvimento Orientado a Objetos com PHP Página 67


6.5 Transactions 4Linux – www.4linux.com.br

para ele e para o sistema, mas não foi inserido o pedido de entrega na tabela de
logística. E agora?

As transações garantem que jamais teremos estes tipos de problema. Podemos


definir transações em nossas aplicações com o PDO utilizando o método beginTran-
saction. Após a chamada deste método, todos os comandos feitos não serão auto-
maticamente executados. O PDO irá aguardar pelo método commit para executar os
comandos, ou pelo comando rollBack, para desfazer tudo que foi feito.

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $db -> beginTransaction () ;
5
6 $db -> exec (" UPDATE pedidos SET compra = 5641 ");
7 $db -> exec (" UPDATE cliente SET compra = 5641 ");
8 $db -> exec (" INSERT INTO logistica ( compra ) VALUES (5641) ");
9
10 // Caso tudo tenha dado certo
11 $db -> commit () ;
12
13 // Ou caso tenha dado errado , podemos desfazer
14 $db -> rollBack () ;

Podemos verificar a consistência de nossa operação de diversas formas. Uma apli-


cação pode ter falhas somente em suas queries, enquanto outras podem ter falhas
em diferentes pontos da transação.

Página 68 Desenvolvimento Orientado a Objetos com PHP


4Linux – www.4linux.com.br 6.6 Prepared statements

6.6 Prepared statements

Prepared statements são comandos SQL pré-construídos, que podem ser manipula-
dos utilizando parâmetros variáveis. Suas queries só precisam ser lidas uma única
vez, enquanto são executadas múltiplas vezes com parâmetros diferentes. Isso torna
a execução da query muito mais rápida, agindo como um cache dinâmico. Além do
benefício de performance, prepared statements garantem que nenhuma query que
foi preparada pode sofrer um ataque de SQL injection.

Imagine a inserção de 300 registros em uma tabela. Quais são as únicas informações
que mudam em cada query? As informações de cada registro. A tabela e as colunas
não mudam. Um prepared statement criar um INSERT genérico, que vai inserir em
tabela e colunas pré-determinadas, enquanto apenas os valores irão mudar.

Para prepararmos nossas queries, o PDO possui um método chamado prepare. Ele
é muito similar aos métodos exec e query, mas ao utilizá-lo, o comando não será
executado, apenas preparado para ser executado posteriormente. O método pre-
pare retorna um objeto da classe PDOStatement. Quando criamos prepared state-
ments, precisamos criar placeholders, ou substitutos. São como buracos, que serão
futuramente substituídos pelos valores que queremos que estejam naquela query.

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4
5 $statement = $db -> prepare (" INSERT INTO posts ( titulo , conteudo )
VALUES (? , ?) ");

Observe as interrogações em nossa query. Elas são nossos placeholders, que serão
substituídos mais tarde por variáveis em nosso aplicação. Para executarmos um
comando preparado, usamos o método execute, passando como parâmetro um array
de variáveis que serão substituídas pelos placeholders.

Desenvolvimento Orientado a Objetos com PHP Página 69


6.7 Stored procedures 4Linux – www.4linux.com.br

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4
5 $statement = $db -> prepare (" INSERT INTO posts ( titulo , conteudo )
VALUES (? , ?) ");
6
7 $statement -> execute ( array (" Meu post " , " Meu primeiro post !"));
8 $statement -> execute ( array (" Outro post " , " Meu segundo post !"));
9 $statement -> execute ( array (" Mega post " , " Meu terceiro post !"));

Observe que temos apenas uma query, mas a executamos três vezes, com três valo-
res diferentes. Estamos passando um array de informações para o método execute,
que pegará estas informações e as colocará no lugar dos placeholders.

6.7 Stored procedures

Stored procedures são um conjunto de comandos SQL que podem ser armazenados
no sistema gerenciador de banco de dados. Uma vez que isso tenha sido feito, os
clientes não precisam reenviar os comandos individuais mas sim, fazer referência
aos stored procedures. Isso pode resultar em um aumento de performance, já que
menos informações são passadas entre nossa aplicação e o banco de dados, mas
em contrapartida, temos uma carga maior no banco de dados, para o processamento
dos dados.

O uso de stored procedures é mais comum em operações que exigem uma segu-
rança muito grande, deixando as aplicações de fora do processo e priorizando o
processamento de dados no próprio banco. Também é comum o uso de stored pro-
cedures quando muitas aplicações existem, escritas em diferentes linguagens e/ou
diferentes plataformas, mas que precisam executar as mesmas operações em um

Página 70 Desenvolvimento Orientado a Objetos com PHP


4Linux – www.4linux.com.br 6.7 Stored procedures

mesmo banco de dados.

Vamos criar uma simples procedure em nosso banco de dados:

1 DELIMITER $$
2 CREATE PROCEDURE ‘ listarposts ‘( IN _id INT )
3 BEGIN
4 IF ( _id IS NULL ) THEN
5 SELECT * FROM posts ;
6 ELSE
7 SELECT * FROM posts where id = _id ;
8 END IF ;
9 END $$
10 DELIMITER ;

Observe que a definição de uma procedure é similar a definição de uma função.


Temos os delimitadores DELIMITER $$ e DELIMITER; que mostram que estamos
criando uma nova procedure. Usamos o comando CREATE PROCEDURE para criar
a procedure. Observe o comando entre parênteses, ele define que esta procedure
pode receber um parâmetro, assim como funções. Os parâmetros de nossa proce-
dure podem ser IN, apenas de entrada, OUT, apenas de saída e INOUT, entrada
e saída. Os tipos de dados dos parâmetros são os mesmo tipos de dados que já
conhecemos (INT, VARCHAR, etc).

Vamos agora executar nossa procedure em nossa aplicação com o auxílio do PDO.
Para executar procedures, usamos o comando SQL CALL:

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4
5 $statement = $db -> prepare (" CALL listarposts (?) ");
6 $um = $statement -> execute ( array (1) );

Desenvolvimento Orientado a Objetos com PHP Página 71


6.8 Controle de erros 4Linux – www.4linux.com.br

7 $todos = $statement -> execute () ;


8
9 print_r ( $um -> fetch () );
10 print_r ( $todos -> fetchAll () );

6.8 Controle de erros

Por padrão, o PDO oferece três modos de controle de erros. O primeiro deles,
PDO::ERRMODE_SILENT, é o modo habilitado por padrão. Neste modo, quando
houver qualquer problema durante a conexão ou comunicação com o banco de da-
dos, o PDO não fará nada, forçando que você implemente seu próprio controle de
erros com base nos métodos errorCode e errorInfo. O segundo modo disponível,
PDO::ERRMODE_WARNING, faz com que o PDO lance warnings toda vez que pro-
blemas sejam encontrados. Enquanto o terceiro modo, PDO::ERRMODE_EXCEPTION,
faz com que o PDO lance exceções toda vez que problemas sejam encontrados.

Para configurarmos o modo de erro que queremos utilizar, vamos usar o método
setAttribute. Este método permite que configuremos uma instância do PDO:

1 <? php
2
3 $db = new PDO (" mysql : host = localhost ; dbname = banco " , " root " , " 123456 " )
;
4 $db -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );

Desta forma, podemos utilizar o PDO com nossos já conhecidos blocos de try e
catch:

1 <? php
2

Página 72 Desenvolvimento Orientado a Objetos com PHP


4Linux – www.4linux.com.br 6.8 Controle de erros

3 try {
4 $db = new PDO (" mysql : host = lochsot ; dbname = banco " , " root " , " 123456 " )
;
5 $db -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );
6 } catch ( PDOException $e ) {
7 echo " Falha na conex ão: " . $e -> getMessage () ;
8 }

Desenvolvimento Orientado a Objetos com PHP Página 73

Potrebbero piacerti anche