Data Access Objects (DAO, Objetos de Acesso a Dados), fornecem uma API genérica para acessar dados em diferentes tipos de bancos de dados. Como resultado, pode-se alterar o sistema de banco de dados sem haver a necessidade de alterar o código que utiliza DAO para fazer o acesso.
O DAO do Yii é feito utilizando a extensão PHP Data Objects (PDO),
que fornece um acesso de dados unificado para muitos SGBD populares, tais como
MySQL e PostgreSQL. Por esse motivo, para utilizar o DAO no Yii, a extensão PDO
deve estar instalada, bem como o driver PDO específico para o banco de dados
utilizado (por exemplo, PDO_MYSQL
).
O DAO no Yii, consiste, basicamente, das quatro classes seguinte:
A seguir, apresentaremos a utilização do DAO no Yii em diferente cenários.
Para estabelecer uma conexão com o banco de dados, criamos uma instância de CDbConnection e a ativamos. É necessário o nome da fonte de dados (data source name, DSN) para conectar-se ao banco. Também podem ser necessários o nome de usuário e senha para o acesso. Uma exceção será disparada caso ocorra um erro ao estabelecer a conexão (por exemplo, um DSN incorreto, ou usuário/senha inválidos).
$connection=new CDbConnection($dsn,$username,$password);
// estabelece a conexão. Você pode utilizar um try... catch tratar exceções
$connection->active=true;
......
$connection->active=false; // fecha a conexão
O formato do DSN depende do driver PDO em uso. Geralmente, o DSN é formado pelo nome do driver PDO, seguido por ":", seguido pela sintaxe de conexão específica do driver. Veja PDO documentation para mais informações. Abaixo temos uma lista dos formatos de DSN mais utilizados:
sqlite:/path/to/dbfile
mysql:host=localhost;dbname=testdb
pgsql:host=localhost;port=5432;dbname=testdb
mssql:host=localhost;dbname=testdb
oci:dbname=//localhost:1521/testdb
Como a classe CDbConnection estende a classe CApplicationComponent, podemos
utiliza-la como um componente da aplicação.
Para isso, configure um componente chamado db
(ou qualquer outro nome) na
configuração da aplicação,
como no código a seguir:
array(
......
'components'=>array(
......
'db'=>array(
'class'=>'CDbConnection',
'connectionString'=>'mysql:host=localhost;dbname=testdb',
'username'=>'root',
'password'=>'password',
'emulatePrepare'=>true, // necessário em algumas instalações do MySQL
),
),
)
Podemos então acessar a conexão com o banco via Yii::app()->db
, que é
ativada automaticamente, a não ser que se configure a propriedade
CDbConnection::autoConnect para false. Dessa maneira, uma única conexão com o
banco de dados pode ser compartilhada entre diversas partes de seu código.
Uma vez que a conexão com o banco de dados tenha sido estabelecida, comandos SQL podem ser executados utilizando-se a classe CDbCommand. Você pode criar uma instância de CDbCommand utilizando o método CDbConnection::createCommand(), com a instrução SQL desejada:
$command=$connection->createCommand($sql);
// se necessário, a instrução SQL pode ser alterada da seguinte maneira:
// $command->text=$newSQL;
Uma instrução SQL pode ser executada via CDbCommand de duas maneiras:
execute(): executa uma instrução SQL que não retorna
resultados, tal como INSERT
, UPDATE
e DELETE
. Em caso de sucesso, retorna
a quantidade de registros afetados pela consulta.
query(): executa uma instrução que retorna registros,
tal como SELECT
. Em caso de sucesso, retorna uma instância de CDbDataReader,
que pode ser utilizada para acessar os registros encontrados. Por conveniência,
um conjunto de métodos queryXXX()
também está implementado, e retornam
diretamente o resultado da consulta.
Uma exceção será disparada caso ocorram erros durante a execução de instruções SQL.
$rowCount=$command->execute(); // executa uma consulta que não retorna resultados
$dataReader=$command->query(); // executa uma consulta SQL
$rows=$command->queryAll(); // consulta e retorna todos os resultados encontrados
$row=$command->queryRow(); // consulta e retorna apenas o primeiro registro do resultado
$column=$command->queryColumn(); // consulta e retorna a primeira coluna do resultado
$value=$command->queryScalar(); // consulta e retorna o primeiro campo do primeiro registro
Depois que o método CDbCommand::query() gerar uma instância de CDbDataReader,
você pode recuperar os registros do resultado através do método CDbDataReader::read(),
repetidamente. Você também pode utilizar um CDbDataReader dentro de um loop
foreach
, para recuperar os registros, um a um:
$dataReader=$command->query();
// executando read() repetidamente, até que ele retorne false
while(($row=$dataReader->read())!==false) { ... }
// utilizando foreach para "navegar" por cada registro encontrado
foreach($dataReader as $row) { ... }
// recuperando todos os registros de uma vez, em um vetor
$rows=$dataReader->readAll();
Nota: Diferente do método query(), todos os métodos
queryXXX()
, retornam os dados diretamente. Por exemplo, o método queryRow() retorna um vetor representando o primeiro registro do resultado da consulta.
Quando uma aplicação executa algumas consultas, seja lendo ou gravando informações no banco de dados, é importante garantir que todas as consultas tenham sido executadas. Nesse caso, uma transação, representada por uma instância de CDbTransaction, pode ser iniciada:
O fluxo acima pode ser implementado como no código a seguir:
$transaction=$connection->beginTransaction();
try
{
$connection->createCommand($sql1)->execute();
$connection->createCommand($sql2)->execute();
//.... outras execuções de comandos SQL
$transaction->commit();
}
catch(Exception $e) // uma exceção é disparada caso uma das consultas falhe
{
$transaction->rollBack();
}
Para evitar ataques de SQL injection e aumentar a performance ao executar instruções SQL repetidamente, você pode "preparar" um comando SQL com marcadores opcionais que serão substituídos pelos valores reais, durante o processo de vinculação de parâmetros.
Os marcadores de parâmetros podem ser nomeados (representados por tokens únicos) ou anônimos (representados por interrogações). Execute o método CDbCommand::bindParam() ou CDbCommand::bindValue() para substituir esses marcadores pelos parâmetros reais. Eles não precisam estar entre aspas: o próprio driver do banco de dados faz isso para você. A vinculação de parâmetros deve ser realizada antes da instrução SQL ser executada.
// uma consulta com dois marcadores ":username" e ":email"
$sql="INSERT INTO users(username, email) VALUES(:username,:email)";
$command=$connection->createCommand($sql);
// substitui o marcador ":username" com o valor atual de $username
$command->bindParam(":username",$username,PDO::PARAM_STR);
// substitui o marcador ":email" com o valor atual de $email
$command->bindParam(":email",$email,PDO::PARAM_STR);
$command->execute();
// insere um novo registro com um novo conjunto de parâmetros
$command->bindParam(":username",$username2,PDO::PARAM_STR);
$command->bindParam(":email",$email2,PDO::PARAM_STR);
$command->execute();
Os métodos bindParam() e bindValue() são similares. A única diferença entre eles é que o primeiro vincula um parâmetro utilizando uma referência para a variável enquanto o outro utilizar um valor. Para parâmetros que representem uma grande quantidade de dados em memória, o primeiro é mais recomendado, devido a uma melhor performance.
Para mais detalhes sobre a vinculação de parâmetros, veja a documentação do PHP.
Ao recuperar os resultados de uma consulta, você também pode vincular colunas à variáveis, de forma que elas sejam automaticamente preenchidas cada vez que um novo registro é recuperado:
$sql="SELECT username, email FROM users";
$dataReader=$connection->createCommand($sql)->query();
// vincula a 1ª coluna (username) à variável $username
$dataReader->bindColumn(1,$username);
// vincula a 2ª coluna (email) à variável $email
$dataReader->bindColumn(2,$email);
while($dataReader->read()!==false)
{
// $username e $email contém o nome de usuário e a senha do registro atual
}
Signup or Login in order to comment.