Como fazer critérios com consulta complexa na estrutura YII?
Pergunta
Eu tenho consulta assim:
SELECT * FROM activity
WHERE (((userId = 1 OR userId IN(SELECT userId FROM follower WHERE followerId = 1))
AND activityType IN(1, 2, 3))
OR (targetId = 24 AND aType IN(1, 2, 3, 4, 5)))
ORDER BY id DESC;
Eu tento usar model()->findAllBySql($sql)
E funciona. Mas eu quero fazer isso usando CDbCriteria
, se você tiver outras soluções, deixe -me saber: D
Solução
Você ainda pode construir essa afirmação com um CDBCriteria, eu acho ... algo como:
$criteria=new CDbCriteria;
$criteria->condition = '
(
(
userId = 1 OR
userId IN (SELECT userId FROM follower WHERE followerId = 1)
)
AND activityType IN(1, 2, 3)
)
OR (
targetId = 24
AND aType IN(1, 2, 3, 4, 5)
)
';
$criteria->order = 'id DESC';
$results=Activity::model()->findAll($criteria);
Como esse ponto, você também pode escrever uma declaração SQL regular, mas pode haver alguns benefícios em fazê -lo da seguinte maneira: parâmetros vinculativos, critérios de fusão, adicionando critérios adicionais etc.
Outras dicas
Enquanto seu SQL simples funcionar, você está seguro. Há muitas vezes em que tenho que jogar o recorde ativo e apenas fazer o trabalho da maneira mais antiga.
Tentei traduzir essa consulta em uma construção legível de CDBCriteria. Péssima ideia. Yii é péssimo quando se trata de consultar dados complexos.
A resposta pode ser encontrada aqui:http://www.yiiframework.com/doc/guide/1.1/en/database.dao#executing-sql-statements
No seu caso:
$sql = 'SELECT * FROM activity';
$sql .= 'WHERE (((userId = 1 OR userId IN(SELECT userId FROM follower WHERE followerId = 1))';
$sql .= 'AND activityType IN(1, 2, 3))';
$sql .= 'OR (targetId = 24 AND aType IN(1, 2, 3, 4, 5)))';
$sql .= 'ORDER BY id DESC';
$connection = Yii::app()->db;
$command = $connection->createCommand($sql);
$results = $command->queryAll();
@Pestaa está certo de que às vezes você precisa lançar um registro ativo pela janela. Isso é especialmente verdadeiro se você estiver fazendo atualizações em massa onde o loop através de vários modelos é terrivelmente ineficiente.
Basta usar o CSQLDATAPROViderhttp://www.yiiframework.com/doc/api/1.1/csqldataprovider
Isenção de responsabilidade: Eu sei que não é uma resposta precisa para essa pergunta partida, mas pode ajudar a contornar o problema que foi dado. Suspeito que o principal objetivo desta questão seja obter maneira de usar o CGridView, ClistView etc. com SQL arbitrário.
eu uso CDbCriteria
Para consultas complexas nas quais eu uso o with
característica.
Você pode criar critérios complexos como este:
$dbCriteria->with=array(
'<relation1>'=>array( 'condition'=>'<condition for given relation>',
'with'=>array('<relation2:relation of relation1>'
=>array(<conditions for relation2>)
)
'scopes'=><scopes for relation1>
)
);
Eu não verifiquei como OR
pode entrar em jogo aqui.
Ao usar escopos, você também pode inserir alguns critérios mais complexos e ainda manter sua condição de pesquisa legível.
Isso é muito poderoso. Ainda não vi um 'tutorial' completo sobre isso; Eu meio que concluí isso do código -fonte.