criado por Rubens Takiguti Ribeiro em 16/12/2009 12:38am
O que PDO?
PDO (PHP Data Objects) um mdulo de PHP montado sob o paradigma Orientado a Objetos e cujo objetivo prover uma padronizao da forma com que PHP se comunica com um banco de dados relacional. Este mdulo surgiu a partir da verso 5 de PHP. PDO, portanto, uma interface que define um conjunto de classes e a assinatura dos mtodos de comunicao com uma base de dados.
Cada sistema gerenciador de bancos de dados (SGBD) pode prover um driver para PDO. Apesar de PDO definir a assinatura dos mtodos que cada driver deve implementar, alguns recursos podem no ser suportados. Logo, a chamada a um mtodo pode ser "intil" dependendo do driver utilizado ou da verso/modelo do servidor de Banco de Dados. Por exemplo, algumas engines do SGBD MySQL no do suporte a transaes, logo, o mtodo "beginTransaction" (responsvel por iniciar uma transao) simplesmente no ter efeito sob tais condies.
Ao contrrio do que algumas pessoas pensam, PDO no uma camada de abstrao de SQL. Cada SGBD relacional possui uma sintaxe prpria para construo de SQL. Embora muitos deles se aproximem da especificao da SQL-92, algumas diferenas existem. Portanto, usar PDO no significa que seu sistema ser portvel entre diferentes SGBDs. Significa apenas que voc se comunicar com uma base de dados atravs de um conjunto determinado de mtodos e classes.
Observao Criar uma camada da aplicao para abstrao de SQL extremamente complexo. Vrias variveis devem ser levadas em conta e, possivelmente, preciso abrir mo de muitos recuros especficos. Portanto, existem duas linhas de desenvolvimento: uma defende a utilizao de um nico tipo de SGBD por aplicao, para que os recursos especficos sejam utilizados ao mximo e de forma otimizada, enquanto outra defende a generalizao e o suporte a diferentes bases de dados, tornando o sistema mais portvel. Tudo depende do objetivo da aplicao.
Por que usar PDO?
Antes da chegada de PDO, a linguagem PHP oferecia suporte comunicao com diferentes modelos de SGBD atravs de mdulos especficos. A maioria deles provia uma biblioteca de funes e utilizava um resource para representar a conexo e outro para representar um resultset (o resultado de uma consulta). As operaes eram feitas sobre as variveis de resource.
Cada driver implementava suas operaes conforme imaginavam ser mais adequados. Embora alguns deles tivessem um funcionamento semelhante, a ordem dos parmetros nem sempre era a mesma e podia causar uma certa confuso entre programadores.
Quem j trabalhou com a biblioteca de funes de MySQL ou PostgreSQL, deve conhecer este funcionamento:
$resultado = pg_query($c, 'SELECT nome FROM usuarios'); while ($obj = pg_fetch_object($resultado)) { echo $obj->nome; } pg_free_result($resultado); pg_close($c);
Note que a forma de conexo feita atravs de estratgias diferentes: MySQL passava os dados de conexo atravs de parmetros, j o PostgreSQL utilizava uma string de conexo (com vrios dados), que uma alternativa mais extensvel. Observe, ainda, que MySQL costuma receber o resource de conexo como ltimo parmetro de suas funes, enquanto o PostgreSQL costuma receber o resource como primeiro parmetro.
PDO juntou o que havia de melhor em cada driver e gerou uma especificao. Embora a especificao no trabalhe com resource explicitamente, ela define duas classes com significados semelhantes: PDO (que representa uma conexo) e PDOStatement (que representa uma consulta/resultado). Alm destas, existe a classe PDOException, que disparada por alguns mtodos para que seja realizado o tratamento de excees.
Utilizar PDO tende a ser mais simples do que utilizar biblioteca de funes, mas continua exigindo conhecimento da sintaxe SQL especfica do modelo de SGBD envolvido. Embora muitos programadores ainda utilizam as funes de conexo, existe a promessa de que PDO ser o padro de conexo em PHP 6, enquanto as bibliotecas de funes passaro a ser extenses PECL, precisando ser instaladas a parte. Como utilizar PDO?
Para utilizar PDO, primeiro instanciado um objeto da classe PDO, que representa a conexo com um banco. No construtor da classe, deve ser informado o chamado "DSN", que uma string de conexo semelhante quela vista anteriormente na funo de conexo com PostgreSQL. Cada driver PDO especifica uma forma de como montado o DSN para o SGBD correspondente. Alm do DSN, tambm informado, por parmetro, o usurio, a senha de acesso e as opes adicionais.
// Exemplo de conexao com MySQL via PDO $dsn = 'mysql:host=host;port=3306;dbname=bd'; $usuario = 'usuario'; $senha = 'senha'; $opcoes = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_CASE => PDO::CASE_LOWER );
Aps abrir uma conexo, as consultas podem ser feitas de duas maneiras: 1 - Atravs da prpria conexo, com o mtodo "exec" ou o "query"; 2 - Montando uma prepared statement com o mtodo "prepare", que devolve um objeto da classe PDOStatement, e depois executando o mtodo "execute" (desta classe).
O mtodo "query" utilizado para consultas que retornam resultados tabulares (como o SELECT) e devolve um objeto da classe PDOStatement com o resultado. J o mtodo "exec" utilizado para consultas que no retornam resultados tabulares (como o INSERT, UPDATE, DELETE) e retorna apenas o nmero de linhas afetadas.
Estes mtodos so teis para executar consultas fixas (no-variveis). Afinal, se envolvessem valores recebidos do usurio, estes valores precisariam ser escapados atravs do mtodo "quote" (para evitar falhas de segurana com SQL Injection).
J o mtodo "prepare" til para montar uma consulta com dados variveis. possvel especificar uma SQL com pontos de substituio que, ao serem substituidos, so escapados pela classe automaticamente. Vejamos alguns exemplos:
// Usando "query" $stmt = $pdo->query('SELECT nome, login FROM usuarios');
// Percorrento um resultset com while while ($obj = $stmt->fetchObject()) { ... }
// Percorrendo um resultset com foreach foreach ($stmt as $linha) { ... }
Note que a classe PDOStatement (objeto $stmt) implementa a interface Traversable, indicando que ela pode ser percorrida por uma estrutura "foreach".
Existem diferentes formas de se executar uma prepared statement com PDO: // 1 - Usando "?" nos pontos-chave $stmt = $pdo->prepare('INSERT INTO usuarios (nome, login) VALUES (?,?)');
// Passando os valores a serem usados no primeiro e segundo "?" $dados = array('Rubens', 'rubens'); $consultou = $stmt->execute($dados);
// Executando a SQL com os valores definidos com binding $consultou = $stmt->execute();
Prepared statements tendem a ser mais rpidas que as consultas convensionais, j que a consulta fica previamente "compilada" e pronta para execuo com novos valores. Ao invs do SGBD interpretar toda a SQL, ele apenas atribui novos valores aos pontos chave e realiza a operao. Funcionalidade muito til para inseres ou atualizaes em massa em uma tabela. Outros benefcios
1 - Obteno padronizada de erros ocorridos em consultas, atravs do mtodo "errorInfo" e "errorCode" da classe PDO e PDOStatement.
2 - Suporte a inicializao e encerramento de transaes de forma padronizada (esta funcionalidade depende do suporte do SGBD), atravs dos mtodos "beginTransaction", "commit" e "rollBack".
3 - Suporte para trabalhar com handle de arquivos para realizar inseres ou consultas a grandes volumes de dados, para economizar memria. Isso acontece pois a prpria classe PDO fica responsvel por transmitir o arquivo "aos poucos", sem precisar carreg-lo inteiramente na memria, como seria feito da forma tradicional. Um handle de arquivo utiliza uma varivel do tipo resource, que funciona como um "ponteiro" para o arquivo. Concluso
O objetivo deste artigo motivar programadores a utilizar PDO. Nota-se que muitos programadores ainda no utilizam PDO pois j esto acostumados com as antigas bibliotecas de funes de conexo e no mudam por comodidade.
Porm, deve-se atentar ao futuro de PHP, que est caminhando cada vez mais para o paradigma orientado a objetos. Neste futuro, que j presente, est inserido o PDO.