segunda-feira, 16 de agosto de 2010

Acesso a Banco de Dados com PDO

php

Quando eu comecei a programar PHP muitas práticas interessantes não faziam parte do meu cotidiano. Eu tive que aprender muita coisa errando e pesquisando na net. Trocar o banco de uma aplicação de mysql pra postgres pode dar bastante dor de cabeça. E esquecer de escapar as querys pode resultar em SQL injections. Muitos programadores não conhecem os perigos dos SQLs.

Bom, uma das ferramentas que deveríamos usar em nosso dia a dia é o PDO, ou algum DO (data object) qualquer. Por exemplo, você lembra de escapar todas as querys que você roda? Eu não culpo, eu também esqueceria. Mas isso leva a uma falha de segurança grave. E implementar usando PDO pode ser muito menos doloroso do que possa parecer.

Na verdade eu não vou mostrar como implementar uma conexão com PDO, mas sim usando Zend_DB. Optei por essa por ser possível integrar posteriormente com o Zend_Config e com o padrão MVC (algo que eu quero mostrar mais tarde). Mas fique tranquilo, as diferenças no que irei mostrar para o PDO em si são mínimas

$db = Zend_Db::factory('Pdo_Oci', array(
'host'     => 'banco.xxxxxx.com.br',
'port'    => '1521',
'username' => 'adm',
'password' => 'xxx',
'dbname'   => 'banco'
));

Este é o código usado para a conexão com o banco. Nada de mistério até aqui. Fácil de entender, fácil de implementar, sem traumas como eu prometi.

$nome = "admin' or 1 = 1 --"; 
$result1 = $db->fetchAll("select * from sistemas where nome = ?", $nome); 
$result2 = $db->fetchAll("select * from sistemas where nome = '$nome'"); 

var_dump($result1, $result2, $nome,  $db->quote($nome)); 
/*
Outputs

array(0) { 
  } 
array(8) { 
   //dump da tabela
} 
string(18) "admin' or 1 = 1 --" 
string(21) "'admin'' or 1 = 1 --'"
*/

Este segundo trecho pode ser bem mais interessantes. Existem algumas coisas aqui que realmente valem a pena serem detalhadas:

Statement

A sql dentro do fetchAll ganharão um statement, independente do SGDB que você usa. Eu digo isso por 2 motivos:

  • Nem todo mundo utiliza as statements.
  • Nem todo mundo utiliza da forma correta ou ótima.

Statements afirmam que essa sql será reutilizada da forma que ela esta escrita, o que permite o banco se preparar para executa-la de maneira otimizada. Isso representa um ganho de desempenho muito interessante. Ainda, muitas vezes as statements são feitas como "select * from id = $id". O que acontece nesse caso é que cada nova execução gera uma sql diferente a anterior. Então o cache do banco sera feito uma vez para cada possibilidade, como "select * from id = 9" e assim por diante.

Escaping

Quantas vezes você se esqueceu de escapar os dados? Você sabe o que é sql injection, então você está preocupado sobre isso certo? Então boas novas, muitas das suas preocupações vão embora. Com o uso de um DO você tem o escaping em todas as suas SQLs sem força.

Acesso a banco flexível

Trocar de banco de dados pode ser uma dor de cabeça certo? Bom, metade dos seus problemas você resolve com PDO. Sendo que você só precisa trocar o driver que o você vai usar na ora de criar a conexão só vai precisar trocar as SQL que você não usou SQL standard, certo? Errado! Se você for um pouquinho mais fundo, vai ver que existem construções de query dentro do Zend_Db que abstraem o SQL, então as preocupações com SQL standard vão embora

$select = $db->select()
    ->from(' ...specify table and columns... ')
    ->where(' ...specify search criteria... ')
    ->order(' ...specify sorting criteria... ');

Mas isso é um assunto mais long, e vai precisar de um outro post pra explorar =D. Bacana né? Fácil? Também.

Um comentário:

George disse...

A utilização do Zend_Db é interessante não só por estas características de abstração de DBMS e de higienização, mas também por possibilitar a utilização de alguns patterns de Mapeamento objeto-relacional (e.g. Table Data Gateway, Row Data Gateway).

Parabéns pelo material. Muito bacana!

[]s,
George

Postar um comentário