Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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
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 );
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.
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
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
8 print_r ( $associativo );
9 print_r ( $numerico );
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
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
para ele e para o sistema, mas não foi inserido o pedido de entrega na tabela de
logística. E agora?
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 () ;
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.
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.
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
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 ;
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) );
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
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 }