Um Database Access Object (DAO
) é responsável por executar consultas de banco de dados para ler e gravar informações do banco de dados.
As aplicações PKP suportam MySQL e PostgreSQL.
Cada DAO
é emparelhado com uma Entidade e converte dados entre as da entidade Classe DataObject
e tabelas no banco de dados.
O DAORegistry
contém uma instância de cada DAO
na aplicação.
$authorDao = DAORegistry::getDAO('AuthorDAO');
Quando um DAO tem um nome diferente em OJS e OMP, você pode recuperá-lo por meio do Application
.
// Obtém um `JournalDAO` ou `PressDAO`
$contextDao = Application::get()->getContextDAO();
// Obtém um`ArticleGalleyDAO` ou `PublicationFormatDAO`
$representationDao = Application::get()->getRepresentationDAO();
// Obtém um `SectionDAO` ou `SeriesDAO`
$sectionDao = Application::get()->getSectionDAO();
Use o método retrieve()
para obter algo do banco de dados.
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
$result = $reviewRoundDao->retrieve(
'SELECT * FROM review_rounds WHERE review_round_id = ?',
[$reviewRoundId]
);
if ($result->RecordCount()) {
$tableRow = $result->GetRowAssoc(false);
}
DAO
s possuem um método _fromRow()
para converter uma linha retornada na classe DataObject
.
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
$result = $reviewRoundDao->retrieve(
'SELECT * FROM review_rounds WHERE review_round_id = ?',
[$reviewRoundId]
);
if ($result->RecordCount()) {
$reviewRound = $reviewRoundDao->_fromRow($result->GetRowAssoc(false));
}
A maioria dos DAO
s tem um método auxiliar para obter um DataObject
por ID.
$reviewRound = DAORegistry::getDAO('ReviewRoundDAO')->getById($reviewRoundId);
Use o método retrieveRange()
para obter um conjunto de linhas do banco de dados.
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO');
$result = $reviewRoundDao->retrieveRange(
'SELECT * FROM queries',
[],
new DBRange($count, $pageNumber)
);
$resultFactory = new DAOResultFactory($result, $reviewRoundDao, '_fromRow');
Itere sobre um DAOResultFactory
para acessar cada resultado no conjunto.
while ($reviewRound = $resultFactory->next()) {
echo 'Review Round: ' . $reviewRound->getData('round');
}
Ou converta o DAOResultFactory
em uma matriz de objetos.
$reviewRounds = $resultFactory->toArray();
Para consultas complexas, use o QueryBuilder.
Use o método update()
para inserir ou atualizar registros.
// Fecha todas as consultas para uma submissão específico
$queryDao = DAORegistry::getDAO('QueryDAO');
$queryDao->update(
'UPDATE queries
SET closed = 1
WHERE assoc_type = ?
AND assoc_id = ?',
[
ASSOC_TYPE_SUBMISSION,
$submissionId,
]
);
A maioria dos DAO
s inclui métodos auxiliares para inserir, atualizar ou excluir registros quando passados por um DataObject
.
$reviewRoundDao->insertObject($reviewRound);
$reviewRoundDao->updateObject($reviewRound);
$reviewRoundDao->deleteObject($reviewRound);
Você também pode excluir registros por ID de um objeto.
$reviewRoundDao->deleteById((int) $reviewRoundId);
Um query builder deve ser usado para construir consultas complexas. As query builders estendem o Query builder do Laravel e fornecem uma API expressiva para buscar registros de um Entidade.
Por exemplo, o SubmissionQueryBuilder
pode ser usado para recuperar submissões com base em vários parâmetros de filtro.
$qb = new \APP\Services\QueryBuilders\SubmissionQueryBuilder;
$qb->filterByContext($contextId)
->assignedTo($userId)
->orderBy('title');
Uma vez configurado, use o query builder para gerar a query string e as ligações de parâmetro a serem passadas para um DAO
.
$qo = $qb->getQuery();
$submissionDao = DAORegistry::getDAO('SubmissionDAO');
$result = $submissionDao->retrieve($qo->toSql(), $qo->getBindings());
Use o método getCount()
para obter uma contagem de linhas correspondentes.
$count = $qb->assignedTo($userId)->getCount();
Use o método getIds()
para obter uma matriz de ids de objeto.
$assignedIds = $qb->assignedTo($userId)->getIds();
Na maioria dos casos, um QueryBuilder
ajudará a preencher os EntityReadInterface
métodos correspondentes da classe Service.
Um QueryBuilder
também pode ser usado com os métodos de consulta do Laravel.
$qb = new \APP\Services\QueryBuilders\UserQueryBuilder();
$qb->filterByContext($contextId);
// Recebe todos os e-mails correspondentes
$emails = $qb->getQuery()->pluck('u.email');
// Obtém o primeiro resultado correspondente
$user = $qb->getQuery()->first();
// Obtém o último usuário cadastrado
$user = $qb->getQuery()->max('u.date_registered');
Se uma entidade for definida usando um esquema, seu DAO
deve estender a classe SchemaDAO
. O SchemaDAO
implementa o insertObject()
, updateObject()
, deleteObject()
e _fromRow()
métodos baseados no esquema.
Um DAO
pode implementar métodos adicionais para realizar atualizações em massa ou minimizar consultas SQL intensivas. Por exemplo, o seguinte removerá todos os DOIs de todos as edições.
DAORegistry::getDAO('IssueDAO')->deleteAllPubIds($contextId, 'doi');
Um método DAO
como este deve ser encapsulado por um método Service que executa a ação para que notificações possam ser enviadas, hooks possam ser chamados, e tarefas relacionadas podem ser executadas.
Ao decidir se deve ou não escrever tal método, considere os benefícios de desempenho de seu método DAO
personalizado em relação às seguintes desvantagens:
A maioria das entidades na aplicação são representadas no banco de dados por duas tabelas. Por exemplo, a tabela journals
contém uma linha para cada revista.
mysql> describe journals;
+----------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+----------------+
| journal_id | bigint(20) | NO | PRI | NULL | auto_increment |
| path | varchar(32) | NO | UNI | NULL | |
| seq | double | NO | | 0 | |
| primary_locale | varchar(14) | NO | | NULL | |
| enabled | tinyint(4) | NO | | 1 | |
+----------------+-------------+------+-----+---------+----------------+
Todos os dados adicionais, incluindo dados multilíngues, são armazenados na tabela journal_settings
.
mysql> describe journal_settings;
+---------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| journal_id | bigint(20) | NO | PRI | NULL | |
| locale | varchar(14) | NO | PRI | | |
| setting_name | varchar(255) | NO | PRI | NULL | |
| setting_value | text | YES | | NULL | |
+---------------+--------------+------+-----+---------+-------+
Por exemplo, o nome de um periódico que aparece em inglês e portguês brasileiro é armazenado em duas linhas na tabela journal_settings
.
mysql> select * from journal_settings where setting_name="name";
+------------+--------+--------------+--------------------------------------+
| journal_id | locale | setting_name | setting_value |
+------------+--------+--------------+--------------------------------------+
| 1 | en_US | name | Journal of Public Knowledge |
| 1 | pt_BR | name | Revista do Conhecimento Público |
+------------+--------+--------------+--------------------------------------+
As propriedades no esquema de uma entidade que são uma matriz ou objeto são serializadas quando são armazenadas na tabela de configurações.
mysql> select * from journal_settings where setting_name="supportedLocales";
+------------+--------+------------------+------------------------+
| journal_id | locale | setting_name | setting_value |
+------------+--------+------------------+------------------------+
| 1 | | supportedLocales | a:1:{i:1;s:5:"en_US";} |
+------------+--------+------------------+------------------------+
Os dados serializados não podem ser pesquisados com eficiência, portanto, nunca devem incluir dados que você deseja consultar.
Saiba mais sobre o Sistema de Plugins.