Data Access Objects (DAO)
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:
- CDbConnection: representa uma conexão com o banco de dados.
- CDbCommand: representa uma instrução SQL a ser executada no banco de dados.
- CDbDataReader: representa um conjunto de registros retornados, navegável apenas para frente.
- CDbTransaction: representa uma transação (transaction) no banco de dados.
A seguir, apresentaremos a utilização do DAO no Yii em diferente cenários.
Estabelecendo uma Conexão com o Banco de Dados
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).
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:
sqlite:/path/to/dbfile
- MySQL:
mysql:host=localhost;dbname=testdb
- PostgreSQL:
pgsql:host=localhost;port=5432;dbname=testdb
- SQL Server:
mssql:host=localhost;dbname=testdb
- Oracle:
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:
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.
Executando Instruções SQL
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:
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
eDELETE
. 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étodosqueryXXX()
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.
Obtendo Resultados de Consultas
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:
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.
Utilizando Transações (Transactions)
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:
- Inicie a transação.
- Execute as consultas, uma a uma. Todas as atualizações no banco de dados não são visíveis aos outros.
- Encerre a transação. Nesse momento, as atualizações tornam-se visíveis, caso a transação tenha encerrado com sucesso.
- Se uma das consultas falhar, toda a transação é desfeita.
O fluxo acima pode ser implementado como no código a seguir:
Vinculando (Binding) Parâmetros
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.
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.
Vinculando Colunas
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:
Utilizando Prefixos de Tabelas
A partir da versão 1.1.0, o Yii framework possui suporte integrado para a utilização
de prefixos em nomes de tabela. Um prefixo é uma string que será anexada ao início dos
nomes das tabelas do banco de dados conectado. Normalmente, eles são utilizados em
ambientes de hospedagem compartilhada, onde múltiplas aplicações utilizam um único
banco de dados e é necessário diferenciar as tabelas de cada aplicação. Por exemplo,
uma aplicação pode utilizar o prefixo tbl_
, enquanto outra utiliza yii_
.
Para utiliza-los, você deverá configurar a propriedade
CDbConnection::tablePrefix com o prefixo desejado. Feito isso, em suas consultas
SQL você deverá utilizar {{NomeDaTabela}}
, onde NomeDaTabela
é o nome da tabela
sem o prefixo. Por exemplo, se um banco de dados contém uma tabela chamada tbl_user
e tbl_
é o prefixo configurado, então você pode utilizar o seguinte código para
realizar consultas nessa tabela: