web-dev-qa-db-fra.com

Quelle est la différence entre $ with et $ joinWith dans Yii2 et quand les utiliser?

Dans la documentation de l'API, il est spécifié que 

  • $joinWith - Liste des relations avec lesquelles cette requête doit être jointe avec 
  • $with - Une liste des relations que cette requête devrait être effectuée avec

Quelle est la différence entre ces propriétés ActiveQuery et dans quelle situation devrions-nous utiliser $joinWith et $with?

28
NAT3863

Différence entre with et joinWith

En utilisant la méthode with, on obtient les requêtes SQL suivantes

$users = User::find()->with('userGroup');

SELECT * FROM `user`;
SELECT * FROM `userGroup` WHERE userId = ...

... lors de l'utilisation de joinWithwill, cette requête SQL 

$users = User::find()->joinWith('userGroup', true)

SELECT * FROM user LEFT JOIN `userGroup` userGroup ON user.`id` = userGroup.`userId`;

J'utilise donc joinWith lorsque je dois filtrer ou rechercher des données dans les tables associées. 

Informations supplémentaires

Le docu -> http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#joining-with-relations vous indiquera ceci: 

"Lorsque vous travaillez avec des bases de données relationnelles, une tâche courante consiste à joindre plusieurs tables et à appliquer divers paramètres et conditions de requête à l'instruction JOIN SQL. Au lieu d'appeler yii\db\ActiveQuery :: join () explicitement pour créer la commande JOIN requête, vous pouvez réutiliser les définitions de relation existantes et appeler yii\db\ActiveQuery :: joinWith () pour atteindre cet objectif. "

Ce qui signifie que vous êtes maintenant capable de gérer vous-même joins, innerJoins, outerJoins et tout ce qui se rapporte à Yii2. Yii (pas Yii2) utilise uniquement join à la place sans laisser à l'utilisateur le choix du type de jointure. Détails sur "Join's" -> c'est une chose basée sur SQL. Vous pouvez lire à ce sujet ici http://en.wikipedia.org/wiki/Join_(SQL)

21
lin

joinWith utilise JOIN pour inclure les relations dans la requête d'origine, alors que with ne le fait pas.

Pour illustrer davantage, considérons une classe Post avec une relation comments comme suit:

class Post extends \yii\db\ActiveRecord {
    ...
    public function getComments() {
        return $this->hasMany(Comment::className(), ['post_id' => 'id']);
    }
}

En utilisant with le code ci-dessous:

$post = Post::find()->with('comments');

résulte dans les requêtes SQL suivantes:

SELECT `post`.* FROM `post`;
SELECT `comment`.* FROM `comment` WHERE post_id IN (...)

Considérant que le code joinWith ci-dessous:

$post = Post::find()->joinWith('comments', true)

résultats dans les requêtes:

SELECT `post`.* FROM post LEFT JOIN `comment` comments ON post.`id` = comments.`post_id`;
SELECT `comment`.* FROM `comment` WHERE post_id IN (...);

Par conséquent, lorsque vous utilisez joinWith, vous pouvez classer par/filtre/groupe par relation. Il se peut que vous deviez désambiguïser les noms de colonne vous-même.

Référence: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#lazy-eager-loading

33
topher

Veuillez noter qu'en plus des réponses ci-dessus qui m'ont aidé à comprendre comment utiliser joinWith(), que chaque fois que vous voulez utiliser joinWith() et que vous avez des noms de colonne ambigus, Yii/ActiveRecord semble choisir automatiquement une colonne aléatoire, au lieu de ce que vous êtes. attend habituellement (la table la plus à gauche). Il est préférable de spécifier la table la plus à gauche dans la clause SELECT, en spécifiant quelque chose comme $query->select("post.*"). Je récupérais les identifiants de certaines tables intérieures et ils s'habituaient comme s'ils étaient depuis la table la plus à gauche, jusqu'à ce que je le sache.

Un autre point à noter est que vous pouvez spécifiez un alias pour la relation joinwith, afin que vous puissiez dire quelque chose comme:

$post->find()
->joinWith(["user u"])
->where(["u.id"=>$requestedUser->id])
->select("post.*")
->orderBy(["u.created_at"=>SORT_DESC]);
0
Dhiraj Gupta