2 votes

Comment utiliser des jointures internes avec des sous-requêtes dans Laravel Eloquent ?

Remarque : il s'agit de Laravel 5.3.

En fait, j'exécute une requête lorsqu'un utilisateur sélectionne la traduction arabe Le code SQL complet ressemble à ceci

select s.ref, t.text as ref_ar 
  FROM stores AS s 
  INNER JOIN 
     (SELECT item, text 
      FROM translator_translations 
      WHERE locale ='ar' 
        AND namespace ='*' 
        AND item like 'store.ref%'
      ) AS t 
   ON substring(s.ref_translation from 14 for 26) = t.item;

Je ne vois pas beaucoup de documentation sur les sous-requêtes dans la documentation officielle de Laravel (il y a des trucs sur les jointures internes, mais ce n'est pas suffisant) et les conseils de SO semblent extra-hacky des conseils ?

contexte

ceci sera utilisé comme une portée à l'intérieur d'un modèle, donc cela fonctionne par exemple :

public function scopeFilterLanguage($query, $language_id)
{
    if (!$language_id || intval($language_id) != LanguageConstants::ARABIC_LANGUAGE_ID) {
        return $query;
    }
    return $query->whereRaw("
    substring(ref_translation from 14 for 26) in 
                                    (select item 
                                     from 
                                     translator_translations 
                                     where 
                                     locale ='ar' and namespace ='*' 
                                     and 
                                     item like 'store.ref%')");

}

mais ça ne me donne pas ce que je veux. (c'est à dire que je dois utiliser la version plus grande au début de ce post).

3voto

abbood Points 5959

Cela a fonctionné (ignorez les trucs dynamiques comme this->getClassName etc.). la logique de base fonctionne très bien.

public function scopeAddTranslations($query)
{
    $t = new Translation();

    $subq = $t->select('item','text as ref_ar')
              ->where('locale','=','ar')
              ->where('item','like',$this->getClassName().'.ref%');

    $query->leftjoin(\DB::raw('('.$subq->toSql().') as t'), 
      function ($join) use ($subq) { 
          $join->on(\DB::raw('SUBSTRING('.$this->getTable().'.ref_translation 
                              FROM 14 FOR 26)'),
                                 '=',
                                 \DB::raw('t.item'))
                   ->addBinding($subq->getBindings());
            });
    return $query;
}

2voto

Voici mon effort totalement non testé et ma meilleure estimation.

public function scopeFilterLanguage($query, $language_id)
{
    if (!$language_id || intval($language_id) != LanguageConstants::ARABIC_LANGUAGE_ID) {
        return $query;
    }
    return $query->join('translator_translations', function($join) {
        $join->selectSub(function($q) {
               $q->where('t.locale' => 'ar')
               $q->where('t.namespace', '*')
               $q->where('t.item', 'like', $this->ref . '%')
          }, 't');
     })->on('t.item', '=', substr($this->ref_translation, 14, 26))
       ->select('t.text', 'ref');
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X