Neste artigo veremos passo a passo de como realizar a conexão com o banco de dados MySQL através do PHP e como utilizar os recursos desta conexão. Utilizaremos para este artigo um recurso chamado PDO, que irá nos auxiliar e facilitar a conexão com o MySQL, mas antes de começar com a “mão na massa” é importante e necessário entender o que é o PDO e como ele irá nos auxiliar.

PDO

PDO ou PHP Data Objects define uma interface consistente para acesso a banco de dados em PHP, ou seja, com o PDO podemos conectar não só ao MySQL mas também a muitos outros bancos como PostgreSQL, SQLServer, Oracle e assim por diante, basta utilizarmos o driver adequado.

Você pode questionar: "Se eu vou utilizar apenas MySQL, não é melhor instalar as bibliotecas dependentes dele e utilizar apenas as funções relacionadas ao MySQL?" A resposta é não. Você nunca deve ficar “amarrado” ao banco de dados em que está trabalhando (este é um princípio simples relacionados a boas práticas), e quando você opta por usar as funções nativas do MySQL, sem nenhuma camada de abstração (Como o PDO, por exemplo), você está colocando todo seu projeto em risco, totalmente dependente de uma tecnologia que amanhã ou depois pode não ser mais viável.

Imagine se daqui a dois ou três anos é decidido que o banco de dados da sua aplicação será migrado de MySQL para Oracle por questões de performance. Nesse caso você terá um trabalho árduo em converter todas as funções que antes eram apenas entendidas pelo MySQL para o Oracle, um trabalho que seria poupado facilmente se você tivesse optado por usar PDO.

Com o PDO você abstrai o banco de dados que está sendo utilizado pela aplicação, ou seja, a aplicação não sabe qual banco de dados está usando, podendo ser MySQL, PostgreSQL, Oracle e etc, não importa. Se você precisa mudar de banco e dados, apenas o Driver ligado ao PDO será alterado mas o seu código principal continuará intacto e ileso.

Iniciando configuração do PDO

Bom, antes de mais nada é necessário ter o driver do PDO para MySQL instalado no seu PHP, e para isso basta executar o comando da Listagem 1 (partindo do princípio que você está trabalhando com Linux/Ubuntu).


sudo pecl install pdo
sudo pecl install pdo_mysql
Listagem 1. Instalando PDO para MySQL no PHP

Depois de instalado o PDO e o PDO para o MySQL então iremos ativá-lo no php.ini, que pode ser encontrado em /etc/php5/apache2/php.ini. Você deve incluir as linhas da Listagem 2 no php.ini.


extension=pdo.so
extension=pdo_mysql.so
Listagem 2. Ativando PDO no php.ini

Obviamente que nosso exemplo está voltado apenas para o MySQL, mas estivem diversos outros drivers para outros bancos, como por exemplo: pdo_oci (oracle), pdo_pgsql (postgresql), pdo_sqlite e etc.

Desenvolvendo

Já temos todo o conceito do funcionamento do PDO em mente, temos também ele instalado e configurado em nosso ambiente, agora só nos resta começar a desenvolver nosso projeto.

Para começar, iremos criar uma classe chamada Conexao que será responsável por gerenciar as conexões com o banco de dados. É através dessa classe que toda nossa aplicação conversará com o banco e neste exato ponto é que temos a ponte de abstração do PDO. Observe a Listagem 3.


<?php
 
class Conexao {
 
    public static $instance;
 
    private function __construct() {
        //
    }
 
    public static function getInstance() {
        if (!isset(self::$instance)) {
            self::$instance = new PDO('mysql:host=localhost;
            dbname=basedetestes', 
            'root', '123456', array(PDO::MYSQL_ATTR_INIT_COMMAND 
            => "SET NAMES utf8"));
            self::$instance->setAttribute(PDO::ATTR_ERRMODE, 
            PDO::ERRMODE_EXCEPTION);
            self::$instance->setAttribute(PDO::ATTR_ORACLE_NULLS, 
            PDO::NULL_EMPTY_STRING);
        }
 
        return self::$instance;
    }
 
}
 
?>
Listagem 3. Classe Conexao.php

Acima temos a nossa Classe Conexao que implementa um padrão de projeto chamado Singleton, que nos garante que apenas uma instância de Conexao será mantida durante toda a aplicação.

Ao solicitar um “getInstance()” na nossa classe Conexao, é verificado se a mesma já possui uma instância criada em memória, caso contrário ele irá iniciar o processo de criação, que explicaremos abaixo.

A classe PDO recebe como construtor quatro parâmetros: São eles:

  1. Local onde está armazenado nosso banco de dados ('mysql:host=localhost;dbname=basedetestes');
  2. Usuário do banco de dados (root);
  3. Senha do banco de dados (123456);
  4. Um array com vários parâmetros aceitos pelo PDO. Em nosso caso setamos apenas um parâmetro que diz respeito ao charset utilizado pelo MYSQL, que será UTF8.

Logo depois setamos alguns atributos que você pode conhecer melhor lendo o manual do PDO no site oficial do PHP, isso porque eles são muitos e você pode realizar diversas operações com eles, mas estes fogem do escopo do nosso artigo.

Por fim, temos nossa conexão criada e configurada via PDO com nossa base de dados MYSQL. Lembra que falamos que é neste ponto que ocorre a comunicação direta da nossa aplicação com a base de dados? Então é exatamente aqui o único local que precisaremos mudar caso seja necessário mudar nosso banco de dados de MYSQL para qualquer outro.

Vamos prosseguir com nosso artigo mostrando como utilizar nossa classe Conexao.php em nossa aplicação, mas para isso iremos montar um cenário de teste para melhor entendimento.

Nosso cenário: Vamos criar uma estrutura para cadastro do usuário, onde teremos POJO + DAO. Não entraremos em detalhes para que serve um POJO ou um DAO, pois são conceitos relacionados a padrão de projeto e como dissemos anteriormente, fogem do escopo deste artigo. Mesmo que você não os conheça (recomendamos que você os estude urgentemente), você poderá continuar com este artigo e entender o uso do PDO.

Primeiro vamos a criação do nosso POJO Usuario.php, conforme a Listagem 4.


<?php
 
class PojoUsuario {
 
    private $cod_usuario;
    private $nome;
    private $email;
    private $senha;
    private $ativo;
    private $perfil;
 
    public function getCod_usuario() {
        return $this->cod_usuario;
    }
 
    public function setCod_usuario($cod_usuario) {
        $this->cod_usuario = $cod_usuario;
    }
 
    public function getNome() {
        return $this->nome;
    }
 
    public function setNome($nome) {
        $this->nome = $nome;
    }
 
    public function getEmail() {
        return $this->email;
    }
 
    public function setEmail($email) {
        $this->email = strtolower($email);
    }
 
    public function getSenha() {
        return $this->senha;
    }
 
    public function setSenha($senha) {
        $this->senha = $senha;
    }    
    
    public function getAtivo() {
        return $this->ativo;
    }
 
    public function setAtivo($ativo) {
        $this->ativo = strtolower($ativo);
    }
    
    public function getPerfil() {
        return $this->perfil;
    }
 
    public function setPerfil($perfil) {
        $this->perfil = $perfil;
    }
 
}
 
?>
Listagem 4. Usuario.php

Vamos partir direto para nosso DAO, chamado de DaoUsuario, onde faremos todas as operações com o banco de dados utilizando nosso PDO. Para não tornar o artigo muito maçante de código fonte, iremos começar por um simples método que insere um usuário no banco de dados, conforme a Listagem 5.


public function Inserir(PojoUsuario $usuario) {
    try {
        $sql = "INSERT INTO usuario (    
            nome,
            email,
            senha,
            ativo,
            cod_perfil)
            VALUES (
            :nome,
            :email,
            :senha,
            :ativo,
            :cod_perfil)";

        $p_sql = Conexao::getInstance()-&gt;prepare($sql);

        $p_sql-&gt;bindValue(":nome", $usuario-&gt;getNome());
        $p_sql-&gt;bindValue(":email", $usuario-&gt;getEmail());
        $p_sql-&gt;bindValue(":senha", $usuario-&gt;getSenha());
        $p_sql-&gt;bindValue(":ativo", $usuario-&gt;getAtivo());
        $p_sql-&gt;bindValue(":cod_perfil", $usuario-&gt;getPerfil()-&
        gt;getCod_perfil());


        return $p_sql-&gt;execute();
    } catch (Exception $e) {
        print "Ocorreu um erro ao tentar executar esta ação, 
        foi gerado um LOG do mesmo, tente novamente mais tarde.";
        GeraLog::getInstance()-&gt;inserirLog("Erro: Código: " 
        . $e-&gt;getCode() . " Mensagem: " . $e-&gt;getMessage());
    }
}
Listagem 5. Método inserir da classe DaoUsuario

Na primeira linha montamos todo nosso SQL e gravamos em um variável chamado $sql. Todo nosso SQL é baseado em parâmetros, ou seja, nome é relativo ao “:nome” e assim por diante.

Na seguinte linha:


$p_sql = Conexao::getInstance()-&gt;prepare($sql);

Estamos pedindo ao PDO que prepare a sentença SQL para que possamos realizar os “binds” necessários, e ao realizar o “prepare()” o PDO retorna um objeto pronto para realizamos a operação necessária.

Os “binds” são as operações de atribuição de valores aos nossos parâmetros, ou seja, o parâmetro “:nome” terá o valor armazenado em “$usuario-&gt;getNome()” e assim por diante. Utilizando o método “bindValue()” do PDO garantimos uma série de segurança extra para nosso código, tais como prevenção a SQL Injection.

Por último, chamamos o método “execute()” que irá executar nosso SQL no banco de dados, retornando TRUE Em caso de sucesso ou FALSE em caso de falha.

Vamos agora ver nosso DAO completo como ficou e explicar alguns pontos importantes. Observe a Listagem 6.


&lt;?php

class DaoUsuario {

  public static $instance;

  private function __construct() {
      //
  }

  public static function getInstance() {
      if (!isset(self::$instance))
          self::$instance = new DaoUsuario();

      return self::$instance;
  }

  public function getNextID() {
      try {
          $sql = "SELECT Auto_increment FROM information_schema.tables 
          WHERE table_name='usuario'";
          $result = Conexao::getInstance()-&gt;query($sql);
          $final_result = $result-&gt;fetch(PDO::FETCH_ASSOC);
          return $final_result['Auto_increment'];
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function Inserir(PojoUsuario $usuario) {
      try {
          $sql = "INSERT INTO usuario (    
              nome,
              email,
              senha,
              ativo,
              cod_perfil)
              VALUES (
              :nome,
              :email,
              :senha,
              :ativo,
              :cod_perfil)";

          $p_sql = Conexao::getInstance()-&gt;prepare($sql);

          $p_sql-&gt;bindValue(":nome", $usuario-&gt;getNome());
          $p_sql-&gt;bindValue(":email", $usuario-&gt;getEmail());
          $p_sql-&gt;bindValue(":senha", $usuario-&gt;getSenha());
          $p_sql-&gt;bindValue(":ativo", $usuario-&gt;getAtivo());
          $p_sql-&gt;bindValue(":cod_perfil", 
          $usuario-&gt;getPerfil()-&gt;getCod_perfil());


          return $p_sql-&gt;execute();
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function Editar(PojoUsuario $usuario) {
      try {
          $sql = "UPDATE usuario set
          nome = :nome,
              email = :email,
              ativo = :ativo,
              cod_perfil = :cod_perfil WHERE cod_usuario = :cod_usuario";

          $p_sql = Conexao::getInstance()-&gt;prepare($sql);

          $p_sql-&gt;bindValue(":nome", $usuario-&gt;getNome());
          $p_sql-&gt;bindValue(":email", $usuario-&gt;getEmail());
          $p_sql-&gt;bindValue(":ativo", $usuario-&gt;getAtivo());
          $p_sql-&gt;bindValue(":cod_perfil", $usuario-&gt;getPerfil()-&
          gt;getCod_perfil());
          $p_sql-&gt;bindValue(":cod_usuario", $usuario-&gt;getCod_usuario());

          return $p_sql-&gt;execute();
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }
  
      public function EditarComSenha(PojoUsuario $usuario) {
      try {
          $sql = "UPDATE usuario set
  nome = :nome,
              email = :email,
              ativo = :ativo,
              senha = :senha,
              cod_perfil = :cod_perfil WHERE cod_usuario = :cod_usuario";

          $p_sql = Conexao::getInstance()-&gt;prepare($sql);

          $p_sql-&gt;bindValue(":nome", $usuario-&gt;getNome());
          $p_sql-&gt;bindValue(":email", $usuario-&gt;getEmail());
          $p_sql-&gt;bindValue(":ativo", $usuario-&gt;getAtivo());
          $p_sql-&gt;bindValue(":senha", $usuario-&gt;getSenha());
          $p_sql-&gt;bindValue(":cod_perfil", $usuario-&gt;getPerfil()-&
          gt;getCod_perfil());
          $p_sql-&gt;bindValue(":cod_usuario", $usuario-&gt;getCod_usuario());

          return $p_sql-&gt;execute();
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }
  
  public function AlterarSenhaAlreadyCripted($cod_usuario, $senha_nova_md5) {
      try {

              $sql = "UPDATE usuario set
              senha = :senha_nova
              WHERE
              cod_usuario = :cod_usuario";

              $p_sql = Conexao::getInstance()-&gt;prepare($sql);

              $p_sql-&gt;bindValue(":senha_nova", $senha_nova_md5);
              $p_sql-&gt;bindValue(":cod_usuario", $cod_usuario);

              return $p_sql-&gt;execute();
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, foi gerado um 
          LOG do mesmo, tente novamente mais tarde.";
          GeraLog::getInstance()-&gt;inserirLog("Erro: Código: " 
          . $e-&gt;getCode() . " Mensagem: " . $e-&gt;getMessage());
      }
  }

  public function AlterarSenha($cod_usuario, $senha_antiga, $senha_nova) {
      try {

          $pojoUsuario = $this-&gt;BuscarPorCOD($cod_usuario);
          if ($pojoUsuario-&gt;getSenha() == md5(trim(strtolower($senha_antiga)))) {

              $sql = "UPDATE usuario set
              senha = :senha_nova
              WHERE
              cod_usuario = :cod_usuario
              and senha = :senha_antiga";

              $p_sql = Conexao::getInstance()-&gt;prepare($sql);

              $p_sql-&gt;bindValue(":senha_nova", md5(trim(strtolower($senha_nova))));
              $p_sql-&gt;bindValue(":senha_antiga", md5(trim(strtolower($senha_antiga))));
              $p_sql-&gt;bindValue(":cod_usuario", $cod_usuario);

              return $p_sql-&gt;execute();
          }
          else
              return false;
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function Deletar($cod) {
      try {
          $sql = "DELETE FROM usuario WHERE cod_usuario = :cod";
          $p_sql = Conexao::getInstance()-&gt;prepare($sql);
          $p_sql-&gt;bindValue(":cod", $cod);

          return $p_sql-&gt;execute();
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function BuscarPorEmailSenha($email, $senha) {
      try {
          $sql = "SELECT * FROM usuario WHERE email = :email and senha = :senha";
          $p_sql = Conexao::getInstance()-&gt;prepare($sql);
          $p_sql-&gt;bindValue(":email", $email);
          $p_sql-&gt;bindValue(":senha", $senha);
          $p_sql-&gt;execute();
          return $this-&gt;populaUsuario($p_sql-&gt;fetch(PDO::FETCH_ASSOC));
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, foi 
          gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function BuscarPorCOD($cod) {
      try {
          $sql = "SELECT * FROM usuario WHERE cod_usuario = :cod";
          $p_sql = Conexao::getInstance()-&gt;prepare($sql);
          $p_sql-&gt;bindValue(":cod", $cod);
          $p_sql-&gt;execute();
          return $this-&gt;populaUsuario($p_sql-&gt;fetch(PDO::FETCH_ASSOC));
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function BuscarPorEmail($email) {
      try {
          $sql = "SELECT * FROM usuario WHERE email = :email";
          $p_sql = Conexao::getInstance()-&gt;prepare($sql);
          $p_sql-&gt;bindValue(":email", $email);
          $p_sql-&gt;execute();
          return $this-&gt;populaUsuario($p_sql-&gt;fetch(PDO::FETCH_ASSOC));
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function BuscarTodos() {
      try {
          $sql = "SELECT * FROM usuario order by nome";
          $result = Conexao::getInstance()-&gt;query($sql);
          $lista = $result-&gt;fetchAll(PDO::FETCH_ASSOC);
          $f_lista = array();

          foreach ($lista as $l)
              $f_lista[] = $this-&gt;populaUsuario($l);

          return $f_lista;
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  public function BuscarTodos_Ativo() {
      try {
          $sql = "SELECT * FROM usuario WHERE ativo = 's' order by nome";
          $result = Conexao::getInstance()-&gt;query($sql);
          $lista = $result-&gt;fetchAll(PDO::FETCH_ASSOC);
          $f_lista = array();

          foreach ($lista as $l)
              $f_lista[] = $this-&gt;populaUsuario($l);

          return $f_lista;
      } catch (Exception $e) {
          print "Ocorreu um erro ao tentar executar esta ação, 
          foi gerado um LOG do mesmo, tente novamente mais tarde.";
      }
  }

  private function populaUsuario($row) {
      $pojo = new PojoUsuario;
      $pojo-&gt;setCod_usuario($row['cod_usuario']);
      $pojo-&gt;setNome($row['nome']);
      $pojo-&gt;setEmail($row['email']);
      $pojo-&gt;setSenha($row['senha']);
      $pojo-&gt;setAtivo($row['ativo']);
      $pojo-&gt;setPerfil(ControllerPerfil::getInstance()-&
      gt;BuscarPorCOD($row['cod_perfil']));
      return $pojo;
  }

}
?&gt;
Listagem 6. DAO Completo com PDO

Nossa classe DAO é Singleton, o que nos garante apenas uma instância na aplicação. Perceba que utilizamos com muita frequência o “Conexao::getInstance()”, pois ele retorna a instância atual do PDO, ou seja, a conexão atual com o banco de dados e é através dele que faremos as operações necessárias.

O restante dos método utilizados pelo PDO podem ser todos vistos com detalhes no manual oficial do PDO, mas com a listagem acima você consegue ter uma visão geral de todas as funcionalidades básicas necessárias para construir um CRUD com o PDO conectado ao MYSQL.

Este artigo é a base/core para qualquer CRUD que sua aplicação necessite, você apenas deve adaptar para sua necessidade mas o princípio e lógica de como tudo funciona está incluso aqui. Detalhes mais técnicos de funções específicas do PDO podem ser encontrados em seu site oficial.

O melhor de tudo é que você poderá aplicar este artigo a qualquer banco de dados, seja ele MySQL, PostgreSQL, Oracle ou SQLServer. A única coisa que você terá que se preocupar e gastar um pouco a mais de tempo é na classe Conexao para criar os parâmetros necessários para o seu banco de dados e instalar o PDO necessário no seu ambiente, fora isso, todo restante do processo não muda.