Conectando-se a bases de dados:
Para conexão com a base de dados são necessários os parâmetros básicos, host, usuário, senha, nome do banco etc. Isto tanto para MySQL, PostgreSQL ou outros bancos.
A conexão se dá pela instância da classe PDO. Passando para seu __construct os parâmetros necessários para a conexão. Ex:
try {
$db = new PDO("pgsql:host=localhost dbname=sistema user=postgres password=bananaamassada");
} catch (PDOException $e) {
print $e->getMessage();
}
A partir de agora a variável $db é um objeto PDO, e através dele pode-se executar vários métodos, trabalhar com transações, preparar e executar "queries", modificar alguns atributos da classe etc.
Um recurso muito interessante e útil da PDO é o tratamento de exceções, dessa forma a classe não retorna erros, mas sim gera exceções que são muito mais fáceis para tratar e debugar, para isto use o método setAttribute() para alterar o atributo PDO::ATTR_ERRMODE, que é a forma como a PDO vai trabalhar com os erros, o valor para esse atributo pode ser PDO::ERRMODE_EXCEPTION, que faz a PDO trabalhar com exceções como descrito acima:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Também é possível trabalhar com conexões persistentes junto ao banco de dados. Para isto o atributo PDO::ATTR_PERSISTENT deve ser true, pode-se utilizar o atributo direto como parâmetro no momento da conexão ou utilizando o método setAttribute.
$db->setAttribute(PDO::ATTR_PERSISTENT,true);
Executando query
Uma vez conectado a base de dados podemos utilizar alguns dos métodos da PDO para executar nossas "queries", o próprio método "query" pode ser utilizado, porém opções como prepare e execute tornam seu uso muito mais flexível e inteligente.
A execução de uma query vai retornar um outro objeto o Statement. Objetos Statements são o resultado da execução ou da preparação para execução de uma query e provêem vários métodos para obter-se informações sobre a query e sua execução. Métodos para "fetch", pegar informações sobre as colunas, linhas entre outros. Recursos semelhantes com os que utiliza-se nas funções nativas mysql nas quais um resultset é passado como parâmetro, ex: mysql_num_rows($resultset).
Dando poder a suas queries
Normalmente a arte de compor queries exige um esforço grande em concatenar e "escapar" strings, formatar valores de acordo com o tipo do campo entre outros. Ex:
$sql="INSERT INTO produtos (produ_nome,grupo_id,categ_id,produ_detalhe,produ_fotos) VALUES ( ". addslashes("Teclado ABNT2 mobil 'T" )".",'2','1',addslashes($detalhe),"tec.png")";
$rs = $db->query($sql);
Essa query pode ser executada normalmente no mysql, mas em outros bancos pode ocorrer problemas com os campos grupo_id e categ_id, que são inteiros e estão entre apóstrofes. Além do programador ter que preocupar-se com o escape das strings e outros fatores.
Uma medida que ameniza e evita muitos problemas é o uso do método prepare da PDO. São os famosos prepared statements. Ex:
try {
$res = $db->prepare(INSERT INTO produtos (produ_nome, grupo_id, categ_id, produ_detalhe, produ_fotos) VALUES (?, ?, ?, ?, ?);
$valores = array("Teclado ABNT2 mobil 'T",2,1,$detalhe,'tec.png');
$res->execute($valores);
} catch ( PDOException $e) {
print "Erro: Código:" . $e->getCode() . "Mensagem" . $e->getMessage();
}
Note que não houve nenhuma preocupação em cuidar de apóstrofes e nem se o valores são strings, inteiros ou real, apenas preparamos uma query para a execução e passamos 5 parâmetros "?" e logo em seguida a query é executada com o método execute onde um array com os valores na ordem dos campos a ser inseridos "?". Dessa forma a query funcionaria independente do banco, a PDO cuidaria do trabalho bruto de escape e blindagem dos dados. O programador preocupa-se apenas para que os dados seja enviados na ordem correta para o método execute.
O mesmo serve para outras instruções sql como Update e Selects.
Ainda há a possibilidade de utilizar nomes ao invés de "?" no método prepare, para isso deve-se utilizar o método bindParam para fazer a tradução do parâmetro (consulte a documentação desse método).
Recuperando dados
Com a técnica acima também facilita-se muito na recuperação de dados, uma vez que não há a necessidade de verificar tipos de dados escapes etc. Ex:
$sql = "SELECT * FROM produtos WHERE produ_id = ?";
try {
$res = $db->prepare($sql);
$res->execute(array($produ_id));
} catch ( PDOException $e) {
print "Erro: Código:" . $e->getCode() . "Mensagem" . $e->getMessage();
}
Nesse caso $res é um objeto da classe Statement com métodos e atributos. Na maioria dos casos esse tipo de objeto nos desperta apenas alguns interesses, os dados retornados, o número de linhas e as colunas retornados.
Para acessar os dados retornados podemos utilizar o método fetch, fetchObjetc ou fetchAll.
O método fetch retorna a linha ativa do statement na forma de um array onde os valores podem ser acessados pelo número da coluna iniciando em 0 (zero) ou o nome da coluna.
Um método muito poderoso é o fetchAll, que retorna um array indexado de 0 ao número de linhas retornadas, e cada item desse array é um outro array exatamente como o retornado pelo método fetch.
Enquanto que fetchObject retorna um objeto com a linha ativa do resultset tendo as colunas como propriedades.
Uma observação importante é que pode-se modificar o tipo de retorno dos métodos fetch e fetchAll passando o tipo de "fetch" desejado na chamada do método ou utilizando o método setFetchMode do statement.
Os valores mais utilizados são:
- PDO::FETCH_ASSOC - faz com que seja retornada a linha ativa do resultset na forma de um array indexado pelas colunas retornadas;
- PDO::FETCH_OBJ: - faz com que o retorno seja um objeto como o retornado em fetchObject.
Ainda existem outros métodos de fetch que podem ser utilizados, o PDO::FETCH_BOUND cria variáveis no php com os nomes da colunas da linha atual do resultset e PDO::FETCH_BOTH, que é o padrão de "fetch" do statements que retorna a linha atual como descrito no método fetch.
Ex.:
$dado = $res->fetch(PDO::FETCH_ASSOC);
print_r($dado);
A saída seria:
Array(
[produ_id] => 1
[produ_nome] =>Teclado ABNT2 mbil 'T
[grupo_id] => 2
[categ_id] =>1
[produ_detalhe] =>teclado ergométrico
[produ_foto] =>tec.png
)
Para alterar o modo de fetch também podemos utilizar o método setFetchMode e passar como parâmetro o método de fetch a ser utilizado. Ex.:
$res->setFetchMode(PDO::FETCH_OBJ);
$dados = $res->fetchAll();
Nesse caso $dados seria um array indexado de 0 ao número de linhas do resultset e cada item do array é um objeto que tem as colunas como propriedades.