Laravel 4 Éloquent Générateur de Requêtes Complexes et des jointures avec la variable
Je suis en train de reproduire une jointure comme l'utilisation de la laravel générateur de requêtes:
LEFT JOIN content_userdata
ON content_id = content.id
AND user_id = $user_id
J'ai découvert que je peux faire des "on" à l'aide de la fonction suivante dans mon modèle qui s'étend Éloquent
public function scopeJoinUserData($query, $user_id)
{
return $query->leftJoin('content_userdata', function($join)
{
$join->on('content_userdata_content_id', '=', 'content.content_id')->on('content_userdata_user_id', '=', 10);
});
}
Mais cela crée deux problèmes. Tout d'abord, je ne peut pas obtenir le $user_id variable dans la fonction et d'autre part, même si j'ai coder en dur les fins de test comme je l'ai fait ci-dessus (à l'int "10") Laravel enveloppe en ce sens qu'il est interprété comme un nom de colonne quand il ne devrait pas être, comme suit:
left join `content_userdata`
on `content_id` = `content`.`id`
and `user_id` = `10`
Alors maintenant, j'ai deux problèmes.
- Je ne peux pas obtenir le $user_id dans la fonction join lors de l'utilisation de requêtes étendues
- Même si je le pouvais, je ne peut pas envoyer une variable à la joindre depuis toujours, il l'interprète comme un nom de colonne
Pourquoi voudrais-je faire cela?
Je me rends compte qu'une seule réponse peut être de le placer dans un cas. Cependant, je suis en train de faire de cette façon que la jointure ne sont pas nécessairement renvoyer des résultats (d'où la jointure gauche), depuis le content_userdata table contient des choses comme l'un des utilisateurs de notation pour un morceau de contenu. Si j'utilise ensuite les résultats avec rien dans le content_userdata de table ne seront pas retournés, si je peux le mettre dans le rejoindre, ils seront retournés en raison de la jointure gauche.
Est-il de toute façon à atteindre dans Laravel et si non quelles sont les alternatives, de toute évidence en train de changer complètement d'amerrissage Laravel est sur le dessus, mais la seule alternative que je peux penser est d'obtenir les données de l'utilisateur dans une requête distincte.
OriginalL'auteur John Mellor | 2013-07-05
Vous devez vous connecter pour publier un commentaire.
Vous avez besoin pour passer une variable à la fermeture à l'aide de la
use
de mots - clés qui les importations de la variable dans la portée. Exemple:C'est une syntaxe PHP liées question et pas un Laravel limitation de!
Vous devez utiliser
DB::raw($user_id)
dans ce cas 🙂Je suis inquiet à propos de SQL Injection si j'utilise cette méthode. Est-il possible d'empêcher cela?
Pour Laravel 4, utilisation
DB::getPdo()->quote($variable)
. Pour Laravel 3, utilisationDB::escape($variable)
.À l'aide de
PDO::quote
défait le but de requêtes paramétrées. Au lieu de cela, voir ma réponse. Cheers!OriginalL'auteur Half Crazed
Dans la accepté de répondre, tout en ajoutant des guillemets autour de la
DB::raw
partie de la requête ne pourra pas le protéger contre l'injection sql. Il suffit de passer quelques citations dans votre user_id et voir. Pour paramétrer vous pouvez faire quelque chose comme ceci:Remarquer dans cet exemple que vous n'avez pas à passer la variable dans la fermeture. Sinon, vous pouvez essayer d'écrire cette partie complètement raw.
Mise à JOUR: Taylor a ajouté
joinWhere
,leftJoinWhere
... si vous avez une fonction de rejoindre juste utiliser->where
et->orWhere
de l'intérieur de la Clôture.OriginalL'auteur prograhammer
J'ai réussi à le réparer moi-même, il y a une note au bas de la pourquoi il n'est pas complètement optimal, mais voici comment le faire de toute façon:
Notez l'utilisation de "use ($user_id)" comme l'a suggéré à Demi-Folle.
DB::raw() est utilisé pour envelopper $user_id entre guillemets, même si c'est un entier, et non une chaîne de caractères. Cela va arrêter Laravel automatiquement en utilisant ce qui est de MySQL, de l'interpréter comme un nom de colonne.
Performance: Une chose à noter est que les requêtes MySQL peut être beaucoup plus rapide lors de l'utilisation d'un entier plutôt qu'une chaîne de caractères et les interprètent comme une chaîne de caractères si il est enveloppé dans des guillemets. Je ne suis pas à s'en inquiéter pour l'instant, mais j'ai pensé que je devrais mentionner si les autres le sont à l'aide de cette solution.
OriginalL'auteur John Mellor
Pourquoi ne pas vous suffit d'utiliser les relations? C'est tout l'intérêt d'un ORM comme Éloquent?
Quelque chose comme cela;
modifier pour montrer que vous pouvez faire ce que vous voulez avec les relations
Option 1:
ou Option 2:
Les deux donnent des résultats différents - mais vous voyez l'idée
oui - vous pouvez inclure querrys sur les relations - laravel.com/docs/eloquent#querying-relations
Ce lien ne signifie pas que vous pouvez le faire de la manière que je l'ai dit, ou d'une manière qui pourrait être utile dans ce cas? Je ne suis pas encore sûr que vous avez lu la question ou comprendre le problème correctement, en particulier le bit après "pourquoi voudrais-je faire cela", néanmoins j'ai déjà posté et accepté la réponse correcte maintenant.
Une jointure est tout simplement une relation. Éloquent les relations de gérer toutes les jointures pour vous. Vous pouvez inclure querrys sur les jointures, comme mon editted réponse ci-dessus. Il fait exactement ce que vous voulez, comprennent la remise de résultats, sans relation - donc la résolution de votre "pourquoi je veux faire cela".
OriginalL'auteur Laurence
Votre premier problème: Vous devez utiliser la syntaxe PHP pour la fermeture de la réponse de La moitié.
À propos de votre deuxième problème, je pense que la partie
AND user_id = $user_id
de la requête n'appartient pas à une clause de JOINTURE, mais une clause where, car il ne dépend que d'une seule table, mais pas les deux dans cet assemblage relation. Je pense que vous devriez utiliser une sous-requête comme ceci:Cependant, comme vous le voyez, laissez-assurez-vous que le
$user_id
variable est sûr parce que nous utilisons\DB:raw
méthode.OriginalL'auteur Hieu Le