Objota O mundo orientado a objetos

PHP – Problema com caracteres na conexão com o banco de dados utilizando PDO

Posted on setembro 13, 2012

Posted by Pedro

Olá galera, fica aqui uma dica bacana para quem está tendo problemas com caracteres na conexão com o banco de dados utilizando PDO.

Problemas com charset geralmente ocorrem quando você processa os dados no seu site em um formato X e no banco em um formato diferente. Ai começam os problemas. Um exemplo simples é o uso de ISO-8859-1 na codificação do seu site e um banco de dados configurado para trabalhar com charset UTF-8.

Nesse exemplo vou configurar parâmetros de conexão como o banco de dados MySQL já que é geralmente o mais utilizando com PHP, e trabalhar com  os dados no formato UTF-8.


//Exemplo da classe em PHP com extends na classe PDO. Aqui vamos atribuir todas as variáveis da nossa conexão pra trabalhar no formato UTF-8.

class MysqlConnection extends PDO {

public function Connection($dsn, $username = "", $password = "", $driverOptions = array()) {

parent::__construct ( $dsn, $username, $password, $driverOptions );

$this->exec("SET NAMES utf8");

$this->exec("SET character_set='utf8'");

$this->exec("SET collation_connection='utf8_general_ci'");

$this->exec("SET character_set_connection='utf8'");

$this->exec("SET character_set_client='utf8'");

$this->exec("SET character_set_results='utf8'");

}

}


//Aqui é a string de conexão / $dsn que vamos usar para conectar ao nosso banco

$dsn = "mysql:host=localhost;dbname=meu_banco_de_dados;charset=utf8";

Bom é isso. Muito simples, certo?

Qualquer dúvida pode postar um comentário que irei responder.

Até a próxima.

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

Posted on novembro 1, 2010

Posted by Rodrigo Ireno

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

Classe de conexão com php utilizando PDO

Posted on agosto 22, 2010

Posted by Rodrigo Ireno

Olá neste artigo vamos aprender a fazer conexão com um banco de dados utilizando um recurso muito bacana que o php nos oferece, o PDO (PHP Data Object). Ele é um objeto que possibilita tornar sua "fábrica de conexões" - já vou exeplicar também - portável.

Imagine que você está usando o banco de dados MySql e que a vida é bela e seu sistema sempre usará este banco! lindo esse sonho não? 🙂

Tá! agora acorda! e veja como o mundo é cruel e as coisas não tão simples assim. Pois se você se baseia totalmente em usar funções como mysqli_connect() , mysqli_.. qualquer coisa., trate de terminar de ler este artigo!

E se esta galera! Estes métodos estão misturados em diversas partes do seu código! Vai te dar uma dor de cabeça sem tamanho, só de pensar em mudar de banco de dados. Pensando nessa, foi que desenvolveram um recurso no php, o PDO. Uma classe que se encarrega de fazer o gerenciamento dos drivers pra você. Isso mesmo! parece que existe uma luz no fim do túnel!

E lembra do que falei? - "fábrica de conexões"

Este é outro conceito muito usado, para garantir tanto uma certa organização quanto a integridade do banco de dados. É o pattern conhecido como Singleton.

Qual é a idéia? Manter uma instância única para que toda a aplicação possa utilizá-la. Veja como isso faz sentido ser utilizado principalmente para conectar-se com um banco. Toda vez que se conecta o banco abre uma porta, e se você criar conexões sem nenhum controle, dependendo do número de acessos que o seu site tiver ele vai derrubar o banco.

O conceito deste pattern está bem explícito na própria wikipedia, mas vamos fazer um código aqui também. Então vamos ao que intereça:

O PDO


/*
 Chega de funções, e funções. Tudo no método construtor do PDO
*/
$pdo = new PDO("tipoDeBanco:host=EnderecoDoHost;dbname=nomeDoBanco", "usuário", "senha" );

Veja só, o objeto já faz tudo numa tacada só. Depois disso é só ir trabalhando com ele e seus métodos de interface.

Executando uma query

Se estiver executando local, o host é localhost, senha não tem e usuário é root. Há e o tipo de banco de dados também!

<?php
try {
	// PDO em ação!
	$pdo = new PDO ( "mysql:host=localhost;dbname=tutorial", "root", "" );

	// Com o objeto PDO instanciado
	// preparo uma query a ser executada
	$stmt = $pdo->prepare("SELECT * FROM cliente");

	// Executa query
	$stmt->execute();

	// lembra do mysql_fetch_array?
	//PDO:: FETCH_OBJ: retorna um objeto anônimo com nomes de propriedades que
	//correspondem aos nomes das colunas retornadas no seu conjunto de resultados
	//Ou seja o objeto "anônimo" possui os atributos resultantes de sua query
	while ( $obj = $stmt->fetch ( PDO::FETCH_OBJ ) ) {

		// Resultados podem ser recuperados atraves de seus atributos
		echo "<b>Nome:</b> " . $obj->nome . " - <b>Telefone:</b> " . $obj->fone."</br>";
	}
	// fecho o banco
	$pdo = null;
	// tratamento da exeção
} catch ( PDOException $e ) {
	echo $e->getMessage ();
}
?>

obs: com a função fetch() é possível trazer os resultados de várias maneiras, este foi só um exemplo. O que determina o tipo de retorno é a constante "PDO::FETCH_OBJ", para mais informações vide manual. Sobre a função fetch().

Compare! um exemplo com o modo tradicional de conexão com MySql

Veja que está tudo dentro de um bloco try, catch. Para quem não sabe, o programa quando encontra um erro dentro de um bloco try, salta para o catch e consegue recuperar a exceção ou erro, por um objeto de exceção que vem por parâmetro. Para mais informações sobre o uso de pdo visite seu manual no site oficial do php.

A fabrica de conexões

Se você seguiu o link que existe ali em cima, já deve ter visto a página da wikipedia com exemplos em diversas linguagens do pattern Singleton, mas vamos terminar a coisa aqui pra não ficar dúvida! 🙂


<?php
class Conexao extends PDO {

	private static $instancia;

	public function Conexao($dsn, $username = "", $password = "") {
		// O construtro abaixo é o do PDO
		parent::__construct($dsn, $username, $password);
	}

	public static function getInstance() {
		// Se o a instancia não existe eu faço uma
		if(!isset( self::$instancia )){
			try {
				self::$instancia = new Conexao("mysql:host=localhost;dbname=conteudo", "root", "");
			} catch ( Exception $e ) {
				echo 'Erro ao conectar';
				exit ();
			}
		}
		// Se já existe instancia na memória eu retorno ela
		return self::$instancia;
	}
}
?>

Então fazendo uso desta classe toda vez que eu quiser fazer conexão com o banco eu uso o método implementado getInstance(), pois ele é quem vai me retornar uma conexão existente ou criá-la para mim.

Veja que eu coloquei direto alí os valores, senhas e talls.. pra conectar certo. Então, porém tanto pra php quanto pra java - falando de web - o ideal é centralizar todas as configurações em um único arquivo, para o site. Em java se faz uso do arquivo de configuração web.xml, já no php este arquivo de configuração geral é mais conhecido como config.

É nada mais nada menos que um arquivo com extensão .php que contem todas as configurações necessárias para o site. Acho que esse assunto ainda rende um post, vou colocar algo a respeito futuramente!
é isso obrigado por ler este post, e até a próxima! vlew 🙂

:: Este post possui uma complementação neste outro artigo! Usando Classe de Conexão com PDO (exemplos práticos)