Comment faire avec des critères requête complexe dans le cadre Yii?
Question
Je recherche comme ceci:
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;
J'essayer d'utiliser model()->findAllBySql($sql)
et il fonctionne. Mais je veux le faire en utilisant CDbCriteria
, si vous avez une autre solution me le faire savoir: D
La solution
Vous pourriez encore construire cette déclaration avec un CDbCriteria je pense ... quelque chose comme:
$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);
Comme ce stade, vous pourriez tout aussi bien écrire une déclaration régulière SQL, mais il pourrait y avoir des avantages à le faire de cette façon. Params lier, les critères de fusion, l'ajout de critères supplémentaires, etc
Autres conseils
Tant que vos travaux SQL simples, vous êtes en sécurité. Il y a beaucoup de moments où je dois jeter Active Record loin et juste faire le travail dans le vieux chemin de Saner.
J'ai essayé de traduire cette requête dans une construction CDbCriteria lisible. Mauvaise idée. Yu suce quand il s'agit de la requête des données complexes.
La réponse se trouve ici: http://www.yiiframework.com/doc /guide/1.1/en/database.dao#executing-sql-statements
Dans votre cas:
$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 juste que, parfois, vous devez jeter enregistrement actif par la fenêtre. Cela est particulièrement vrai si vous faites des mises à jour de masse où une boucle à travers de nombreux modèles est terriblement inefficace.
Il suffit d'utiliser CSqlDataProvider http://www.yiiframework.com/doc/api/1.1/CSqlDataProvider
Disclaimer: Je sais que ce n'est pas de réponse précise à cette question particural mais il pourrait aider à contourner le problème qui a été donné. Je soupçonne que le but principal de cette question devient moyen d'utiliser CGridView, etc. CListView avec SQL arbitraire.
J'utilise CDbCriteria
pour les requêtes complexes dans lesquelles utiliser la fonction de with
.
Vous pouvez construire des critères complexes comme celui-ci:
$dbCriteria->with=array(
'<relation1>'=>array( 'condition'=>'<condition for given relation>',
'with'=>array('<relation2:relation of relation1>'
=>array(<conditions for relation2>)
)
'scopes'=><scopes for relation1>
)
);
Je n'ai pas vérifié comment OR
peut entrer dans le jeu ici.
En utilisant les étendues, vous pouvez également insérer des critères plus complexes et toujours garder votre lisible état de recherche.
Ceci est assez puissant. Je ne vois pas un « tutoriel » sur ce encore; Je genre de concluais ce à partir du code source.