Cap. 3 - PHP Orientado a Objetos
3.2 - PDO para Acessar Mysql
Objetivo: Acessar mysql via PDO.
Conteúdo da Aula:
1. Introdução ao PDO
A partir do PHP 5.5, a biblioteca MySQL, do PHP, com funções como mysql_connect e mysql_query é considerada obsoleta. A alternativa mais recomendada é usar a extensão PDO.
Figura 1: PDO, PHP Data Objects, é uma classe que provê ferramentas para acesso do php a banco de dados. Vide mais em introd.pdo.php (The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP. )
O que é PDO
PDO significa PHP Data Objects (Objetos de Dados do PHP, em tradução livre). Ele é uma biblioteca que define uma interface para conexão e operações com sistemas de gerencia de banco de dados. Ou, dizendo de uma forma mais simples, usando a nomemclatura de Orientação a Objetos, podemos entender o PDO como uma classe para gerenciar conexões com bancos de dados. Ou seja, é possível usar PDO para conectar com diversos SGBDs, dentre eles MySQL, PostreSQL, SQLite, MS SQL Server, Oracle. Vide figura 1.
Figura 2: Representação do PDO: uma camada (ou interface) entre o banco e seu programa em PHP.
O termo CRUD é usado como referência para as operações fundamentais de um banco de dados. Dizemos que o PDO é usado para efetuar essas 4 operações básicas: criar, ler, atualziar, deletar dados. Além obviamente de fazer consultas.
Figura 3: CRUD (Create, Read, Update, Delete): operações básicas com banco de dados que podem ser feitas com o PDO.
Para que usar o PDO
O PDO fornece ferramentas para acessarmos, via PHP, o banco de dados. Uma vez criada a conexão (que, como veremos a seguir, cria um objeto PDO) podemos usar os métodos da classe para fazer consultas ou alterar dados no banco.
A figura 4 abaixo apresenta um diagrama explicando a funcionalidade do PDO: que é usado para conectar com o banco (com o SGBD). De um lado, o php "conversa com o SGBD" e de outro ele "conversa com o navegador"
Figura 4: Esse diagrama mostra a estrutura do PHP em relação ao cliente (browser) e ao servidor de banco de dadsos (mysql , no caso). A conexão e acesso ao SGBD é feita via PDO.
2. Conceitos Básicos
PDO é Orientado a Objetos
PDO é uma classe. Ela segue o padrão da orientação a objetos. Veja a seção sobre PHP-OO clicando aqui..
Para entender como usamos o PDO é importante saber o que são classes, objetos e métodos. E também como instanciar objetos e chamar seus métodos.
Usando o PDO
Em termos conceituais, o uso do PDO é bem intuitivo. Precisamos apenas criar uma conexão e a partir dela, fazer as operações com o banco. A figura 5 apresenta um diagrama das etapas para trabalharmos com o PDO. Obviamente o banco precisa existir no seu SGBD.
Figura 5: Uma representação bem simples do uso do PDO. Precisamos apenas conectar com o banco e depois usar os métodos para acessá-lo (seja inserindo, atualizando, ou consultando tabelas.)
Configurando o php.ini
Antes de começarmos a trabalhar com o PDO, é necessário habilitar o driver do PDO e o driver referente ao banco que será utilizado. Para habilitar o PDO é bem simples, vá ate o seu arquivo php.ini que encontra-se dentro do diretório onde foi instalado o PHP e remova os comentários (;) das linhas abaixo.
Habilitando PDO no Windows (linhas do arquivo php.ini)
extension=php_pdo.dll
extension=php_pdo_mysql.dll
Habilitando PDO no Linux (linhas do arquivo php.ini)
extension=pdo.so
extension=pdo_mysql.so
Podemos verificar se o PDO está habilitado execuntando a função phpinfo(), que mostra as configurações do seu PHP. A figura 6 mostra uma parte da tela do resultado da execução do phpinfo. Na seção "PDO" vemos que o "PDO DRIVE" está habilitado para o mysql.
Figura 6: Uma representação bem simples do uso do PDO. Precisamos apenas conectar com o banco e depois usar os métodos para acessá-lo (seja inserindo, atualizando, ou consultando tabelas.)
Conectando o PHP/PDO com o SGBD
A conexão é feita pelo construtor da classe PDO. Ou seja, basta passarmos os dados de conexão como parâmetro ao instanciarmos a classe PDO, desta forma:
$pdo = new PDO("mysql:host=meu_servidor; dbname=meubanco", "meu_usuario", "minha_senha");
A figura 7 mostra em detalhes os parâmetros que são passados quando instanciamos a classe.
Figura 7: Exemplo de uma instrução para criar o objeto $pdo, que é uma instância da classe PDO. Ela é instanciada com os parâmetros DSN (host + database), usuário e senha.
Em geral, definimos os parâmetros como strings. Uma opção usual é fazermos como no exemplo abaixo.
Trecho de um programa PHP com a conexão PDO a um Banco de Dados
$db = 'CidadeEstado';
$host = '127.0.0.1';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$user = 'marcio';
$pass = 'marcio';
$options="";
$pdo = new PDO($dsn, $user, $pass, $options);
É recomendado testarmos o resultado da conexão. Usualmente fazemos com um par "try-catch", como mostrado abaixo (nesse exemplo usamos o nome do objeto como sendo $conec ao invés de $pdo)
Opção para testarmos se a conexão foi bem sucedida
try {
$conec = new PDO($dsn, $user, $pass);
$conec->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo 'erro ao conectar com BD: ' . $e->getMessage();
exit;
}
echo "conexão com o banco ".$db ." feita com sucesso!";
CRUD Usando PDO
Tendo sida estabelecida a conexão com o Banco de Dados, estamos em condições de acessar suas tabelas. As operações do CRUD (Create, Read, Update e Delete) podem ser feitas usando-se os métodos da classe PDO. Vamos ver as principais operações a partir de exemplos.
Usando o SELECT
A forma mais usual (e elegante) de fazermos consulta ao Banco é a partir dos métodos prepare(), execute() e fetch()
O uso desses métodos é bastante intuitivo. Primeiro "preparamos a consulta", depois "executamos a consulta" e depois "buscamos o resultado"(fetch = buscar).
Método: prepare: prepara uma SQL-query para ser executada
Método: execute: executa uma query e retorna o número de linhas afetadas.
Método: fetch: busca uma determinada linha na tabela.
Trecho de um programa PHP Busca de Todas as linhas de uma Tabela
$sql = 'SELECT sigla, Estado FROM Estados;';
$stmt = $pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch())
{
echo $row[0] . " | " . $row[1] . " | " . "
";
}
A saída da execução desse trecho será:
---------------------------------
AC | ACRE |
AL | ALAGOAS |
AP | AMAPÁ |
AM | AMAZONAS |
BA | BAHIA |
o método fetch
retorna linhas de uma consulta usando um cursor
Métodos disponíveis:
fetch(): Retorna uma unica row da consulta, ideal para poder utilizar em consultas como login, que retorna somente um resultado.
fetchAll(): Retorna um array com todas as linhas da consulta, ideal para uma busca por nome ou por endereço.
Estilos de retorno
Um estilo de retorno é o PDO::FETCH_ASSOC, ou seja, ele retornará um array associativo exemplo:
[“nome”=>”Marcio Lucas”, “login” => “doidera123”, “senha” => “pamonha321”];
Connecting to MySQL
The following index.php script illustrates how to connect to the pdodemo database in MySQL database server with the root account:
Mais sobre o Método fetch()
Após executarmos a query os dados são obtidos por meio do método fetch (). Antes de chamar fetch, podemos definir o formato (ou a estrutura) no qual os dados serão lidos. Temos as seguintes opções:
PDO :: FETCH_ASSOC: retorna uma matriz indexada pelo nome da coluna.
PDO :: FETCH_BOTH (padrão): retorna um array indexado pelo nome e número da coluna.
PDO :: FETCH_BOUND: atribui os valores de suas colunas às variáveis definidas com o método -> bindColumn ().
PDO :: FETCH_CLASS: atribui os valores de suas colunas às propriedades da classe nomeada. Ele criará as propriedades se não houver propriedades correspondentes.
PDO :: FETCH_INTO: atualiza uma instância existente da classe nomeada.
PDO :: FETCH_LAZY: combina PDO :: FETCH_BOTH / PDO :: FETCH_OBJ, criando os nomes das variáveis do objeto à medida que são usados.
PDO :: FETCH_NUM: retorna uma matriz indexada pelo número da coluna.
PDO :: FETCH_OBJ: retorna um objeto anônimo com nomes de propriedades que correspondem aos nomes das colunas.
Na realidade, existem três configurações que cobrirão a maioria das situações: FETCH_ASSOC, FETCH_BOTH, FETCH_OBJ e FETCH_CLASS. Para definir o método fetch, a seguinte sintaxe é usada:
$stmt->setFetchMode(TIPO);
Por exemplo:
$stmt->setFetchMode(PDO::FETCH_ASSOC);
A seguir apresentamos trechos de programas com o uso das configurações FETCH_ASSOC, FETCH_BOTH e FETCH_OBJ, FETCH_CLASS.
O uso das três primeiras configurações é bastante intuitivo e direto. No caso da opção FETCH_CLASS, a usamos para associar o resultado da consulta a uma classe. Veja no exemplo que criamos a classe com os campos "sigla" e "Estado" e fizemos a busca ("fetch") diretamente do banco para a classe.
Exemplos com diferentes configurações para o método FETCH.
//-----------------------------------------------------------
$sql = 'SELECT sigla, Estado FROM Estados limit 5;';
$stmt = $pdo->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_BOTH);
$stmt->execute();
while ($row = $stmt->fetch())
{
echo $row[0]." = ".$row[1]. "
";
echo $row['sigla']." = ".$row['Estado']. "
";
}
// --------------------------------------------------------------
$sql = 'SELECT sigla, Estado FROM Estados limit 5;';
$stmt = $pdo->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
while ($row = $stmt->fetch())
{
echo $row['sigla']." = ".$row['Estado']. "
";
}
//------------------------------------------------------------
$sql = 'SELECT sigla, Estado FROM Estados limit 5;';
$stmt = $pdo->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_OBJ);
$stmt->execute();
while ($row = $stmt->fetch())
{
echo $row->sigla." = ".$row->Estado. "
";
}
//------------------------------------------------------------
class Estados {
public $sigla;
public $Estado;
}
$sql = 'SELECT sigla, Estado FROM Estados limit 5;';
$stmt = $pdo->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Estados');
$stmt->execute();
while ($obj=$stmt->fetch()){
echo $obj->sigla. " = ". $obj->Estado;
echo "
";
}
Inserindo Dados no Banco
Podemos executar uma ação de INSERT de forma semelhante a que fizemos a consulta. Mas no caso não usamos o método fetch() pois não estamos buscando dados e sim inserindo. Veja o exemplo a seguir no qual inserimos uma cidade no banco.
Exemplo de uso do INSERT
$uf = 'MF';
$cidade = 'Sabará';
$sql = "INSERT into Cidades(UF,Cidade) values(?,?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$uf,$cidade]);
if ($stmt){
echo "Dados inseridos com sucesso";
}
else{
echo "problemas na inserção...";
}
O exemplo acima mostra uma estrutura elegante para o uso do INSERT. Ao definirmos a query definimos os campos dos dados com o caractere ? para que os valores sejam definidos no momemento da execução. Assim, no caso do exemplo acima, na linha
$sql = "INSERT into Cidades(UF,Cidade) values(?,?)";
define uma query em que os valores que serão alocados são indeterminados (no momento da criação da string $sql).
Quando executamos a query na linha
$stmt->execute([$uf,$cidade]);
passamos um array de dois valores, que são exatamente os valores correspondentes às duas interrogações que criamos na query.
Essa estrutura é muito útil quando temos valores que serão definidos pelo usuário.
Atualizado Dados
Podemos usar o comando UDPDATE de forma semelhante ao que fizemos com o comando INSERT. Acompanhe o próximo exemplo.
Exemplo de uso do UPDATE
$tabela = 'Cidades';
$sql = 'UPDATE '.$tabela. ' set uf=? where uf=? and Cidade=?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$uf,'MF',$cidade]);
if ($stmt){
echo "Dados atualizados com sucesso";
}
else{
echo "problemas na atualização...";
}
Usamos a mesma estratégia usada no exemplo do comando INSERT: os símbolos ? para serem substituidos pelos valores desejados, quando da execucação da query.
Dicas
É recomendado que tenhamos um arquivo específico para a conexão com o BD. Esse arquivo pode ser inserido (ou pode ter uma função que é chamada) no(s) arquivo(s) que for(em) exexutar a(s) query(ries). Assim, quando você mudar de host, você só precisará alterar os dados da conexão.
Podemos criar funções genéricas que fazem consultas e retornam os dados em objetos ou arrays. Experimente, por exemplo, criar uma função para executar um select. A função deve receber como parâmetros o nome da tabela e as colunas que serão lidas.
Mesmo em processos maiores, com diferentes acessos (que envolvem sessões diferentes do PHP) fazemos apenas uma conexão. Ela fica aberta durante todo o processo.
Exercícios
Exercício 1
Faça um programa PHP para acessar o banco de dados usando a conexão via PDO. Esse programa será usado em todas as suas conexões. Teste-o, inserindo-o em um outro arquivo e fazendo uma consulta simples no Banco de Dados definido.
Exercício 2
Faça o programa PHP para executar os exemplos dados nessa página, para acesso ao Banco de Dados "CidadeEstado".
Exercício 3
Ainda usando o banco de dados "CidadeEstado", faça um programa/página com duas opções PHP/HTML para:
Ler (num formulário html) um estado (ou o DF) e Listar todas as cidades do estado informado.
Inserir cidades nos estados. Para isso, deve-se ler (num formulário html) o nome da cidade que será inserida e seu estado.
Exercício 4
Melhore o programa/página anterior, garantindo que não tenham cidades repetidas em cada estado (ou seja, o nome de um cidade só pode aparecer uma vez em cada estado)..
Exercício 5
Faça um sistema de cadastro e login com registro no Banco de Dados. Use a classe PDO. Crie páginas para cadastro e para login, com acesso via "nome de usuário" e senha. O sistema deve prover também ferramentas para alteração de senha e nos dados cadastrados. Todos os dados devem estar no Banco de Dados. Planeje o banco de dados, pensando nas entidades(tabelas) e relacionamentos. Inclua restrições necessárias (por exemplo, um usuário só pode ter um cadastro). Todo o acesso ao banco deve ser feito usando-se os métodos da classe PDO.
(voltar para o topo)
Uma possível solução para o exercício 3 está feita aqui (veja os arquivos fonte aqui).