Objota O mundo orientado a objetos

Usando classe de conexão com PDO – (exemplos práticos)

Posted on novembro 1, 2010

Este artigo é uma complementação para o artigo anterior sobre PDO. Neste artigo viso ressaltar alguns detalhes não abordados anteriormente e utilizar de exemplos práticos.

Como mencionado no artigo anterior o uso do pdo facilitou muito mudar de banco de dados, porém isso não irá te livrar de uma diferença na sintaxe dos seus comandos SQL. Isso mesmo! Nem tudo é um mar de rosas com PDO.  Digamos que ele é um grande avanço para o php - afinal o Java já fazia uso deste tipo de estrutura. E como OOP agora é a bola da vez vemos pouco a pouco a transformação do php.

Outra coisa a mencionar é que não abordei como instalar o PDO, pois as atuais distribuições do php já vêm com PDO habilitado. Uma dica para os que quiserem saber quais drivers estão disponíveis para o seu servidor:

É comum não termos acesso ao php.ini de nossa hospedagem então, este é um modo de ver os drivers que estão habilitados na hospedagem que contratamos.


foreach(PDO::getAvailableDrivers() as $driver){
    echo $driver.'<br />';
}

Mas agora vamos ao que interessa, neste artigo vamos utilizar uma tabela no banco de dados Mysql para fazer algumas operações com ela utilizando pdo. Não será abordado como iniciar, pois outros artigos neste blog já descrevem este processo.

Nota: Sendo a única coisa a ressaltar de diferente do artigo anterior sobre PDO é que utilizei um array com argumentos no construtor:

array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)

Pois estes permitem que erros sejam capturados como exceções por um bloco try/catch. Veja mais detalhes na documentação

Utilize este comando SQL para criar nosso banco e tabela clientes de exemplo ou crie manualmente.


CREATE DATABASE `objota` ;

CREATE TABLE `objota`.`clientes` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`nome` VARCHAR( 255 ) NOT NULL ,
`telefone` VARCHAR( 100 ) NOT NULL ,
`email` VARCHAR( 100 ) NOT NULL
) ENGINE = MYISAM ;

A primeira coisa que vamos fazer é inserir dados no banco. Abaixo um exemplo de inserção utilizando a classe PDO:


try{
    //executa as instruções SQL
    $oConexao->exec("INSERT INTO clientes (nome,telefone,email) VALUES ('Rodrigo', '11-333-555', 'rodrigo@objota.com.br')");
    $oConexao->exec("INSERT INTO clientes (nome,telefone,email) VALUES ('Marcos', '55-555-888', 'marcos@mm.com.br')");
    $oConexao->exec("INSERT INTO clientes (nome,telefone,email) VALUES ('Maria', '11-888-9999', 'maria@maria.com.br')");
}catch (PDOException $e){
        //se houver exceção, exibe
        echo $e->getMessage();
}

Como vemos utilizamos o método exec para executar comando SQL no banco de dados. Neste caso inserimos três registros.

Agora veremos como consultar utilizando os recursos da classe PDO:


try{
    //executa uma instrução de consulta
    $result = $oConexao->query("SELECT * FROM clientes");
    if($result){
          //percorre os resultados via o laço foreach
           foreach($result as $item){
                  //exibe o resultado
                  echo "Nome: ".$item['nome'] . " - " . $item['telefone'] . $item['email'] ."<br>\n";
           }
    }
}catch (PDOException $e){
        echo $e->getMessage();
}

Como vimos para executar uma consulta utilizamos a função query que retorna um objeto de resposta PDOStatement que pode ser percorrido utilizando um laço foreach.

Também é possível percorrer um objeto PDOStatement utilizando o método fetch dele e tratar cada linha da consulta como um objeto.

Vejamos:


try{
    //executa a instrução de consulta
    $result = $oConexao->query("SELECT * FROM clientes");

    if($result){
        //percorre os resultados via o fetch()
        while ($item = $result->fetch(PDO::FETCH_OBJ)){
            //exibe resultado
             echo "Nome: ".$item->nome. " - " . $item->telefone . $item->email . "<br>\n";
        }
    }
}catch (PDOException $e){
    echo $e->getMessage();
}

Agora veremos um recurso muito interessante do PDO, que consiste em preparar o comando antes de executá-lo. Como era de se esperar, vamos utilizar a função do PDOStatement, a prepare(). Vejamos abaixo:


try{
    //executa a instrução de consulta
    $oConexao->beginTransaction();

    $stmt = $oConexao->prepare("INSERT INTO clientes (nome,telefone,email) VALUES (?, ?, ?)");
    $stmt->bindValue(1, "Helio");
    $stmt->bindValue(2, "33-4444-5555");
    $stmt->bindValue(3, "helio@m.com.br");
    $stmt->execute();

    $oConexao->commit();

}catch (PDOException $e){
    $oConexao->rollBack();
    echo $e->getMessage();
}

Veja que neste caso eu utilizei o método beginTransaction() do objeto pdo, nosso objeto de conexão, este método abre uma transação com o banco de dados e desliga o "autocommit". A vantagem de se utilizar dele é que a operação só é commitada depois de toda a execução. E é você que tem que escrever esta função para finalizar a transação commit(), porém se o pdo capturar alguma exceção.

Ele pula para o bloco catch e a função rollback() se encarrega de retroceder as alterações feitas no banco, assim é possível garantir a medida do possível a integridade do banco e de seus dados.

Leia mais sobre transações sem autocommit em:

http://dev.mysql.com/doc/refman/4.1/pt/commit.html

Considerações finais:

Este artigo veio para fortalecer e complementar o artigo anterior sobre pdo. Espero que tenha sido esclarecedor. E mais uma observação. No início do artigo falei a respeito de alterar um atributo do pdo com esta estrutura inserida no construtor:

array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)

Na documentação do pdo existem várias constantes como estas podendo ser utilizadas para as mais diversas coisas. Por tanto vale a pena dar uma olhada na documentação. Desta vez vou disponibilizar os arquivos necessários para a execução deste exercício. Até a próxima 😉

Download: Arquivos de Trabalho

Posted by Rodrigo Ireno

Comentários (7) Trackbacks (1)
  1. Rodrigo, tentei utilizar a transação com Sql Server, mas dá um errro dizendo que não suporta transação.
    This driver doesn’t support transactions

    Por favor, me diga como habilito isso no php.ini.
    Obrigado

    • Então André, até onde eu sei os drivers para o PDO são esperimentais para algumas plataformas http://www.php.net/manual/en/ref.pdo-dblib.php

      só que ele está dizendo claramente que não dá suporte a esse driver.

      utilize este código:

      <?php
      foreach(PDO::getAvailableDrivers() as $driver)
      {
      echo $driver.'’;
      }
      ?>

      e verifique se o drive está mesmo disponível. Caso não esteja aí é com o seu serviço. Como se trata de um driver, pode simplesmente não estar disponível para uso, ou desbilitado.
      Agora.. se você tem como mexer no php.ini pode ver os comandos aqui http://php.net/manual/en/pdo.installation.php

      Espero ter ajudado, boa sorte!

  2. Ops…

    Ja vi que é assim

    class Nomes extends Conexao {

    public function listar(){
    $conexao = Conexao::getInstance();
    ….
    }

    }

    Mais tem um problema…
    quando uso o __construct e chamo a funcao listar gera um erro

    No error: PDO constructor was not called
    Call to a member function execute() on a non-object in

    Pode me ajudar nessa?
    Obrigado!

  3. Muito bom!
    fiquei um bom tempo parado. Mas to voltando agora.
    Na epoca, eu ralei pra aprender a utilizar o PDO.
    (infelismente não sei ingles pra vasculhar o manual :/)
    E nunca achava nehum material bom em português.
    E você explica de uma maneira simples e direta.
    Está de Parabens. Ja adicionei o site aqui nos favoritos.

  4. Boa tarde, Rodrigo Ireno!! Gostei muito do seu site, fiz o download do seu exemplo acima e apenas alterei a configuração do banco de dados, e depois fui tirando os comentários dos exemplos para ver o resultado… acontece que todos os exemplo ocorre um erro parecido com esse:

    Fatal error: Call to a member function beginTransaction() on a non-object in C:\xampp\htdocs\PDO\index.php on line 54

    E como sou leigo nisso, não estou conseguindo arrumar.. me ajuda please!!

  5. Vi que tem um probleminha na parte de transações, antes de iniciar a transação vc deve pegar uma conexão da fábrica de conexões exclusivamente para uso da tua transação, O MySQL por exemplo não suporta múltiplas transações em uma mesma conexão, logo a mesma conexão não pode estar sendo usada simultaneamente por vários pontos no sistema, cada ponto que precisa de transação tem que pegar uma conexão para uso exclusivo e depois de usar devolver à fábrica. Do contrário enquanto vc inicia uma transação, outra thread do programa já fez commit nela e vc não tem mais como fazer rollback, vai ficar tudo inconsistente. Em SGDBs que suportam multiplas transações vc pode criar ids exclusivos para cada transação e usar dentro da conexão, como por exemplo o Firebird, mas a conexão isolada para cada transação penso que mataria o problema do MySQL, Firebird, MS SQL SERVER , ORACLE.. ao mesmo tempo.


Leave a comment