2015-09-12 7 views
5

Ich versuche Tage zu verstehen, wie ich eine SQL-Abfrage in eine Abfrage Builder-Stil in Laravel konvertieren kann.konvertieren SQL-Abfrage in Query Builder-Stil

My SQL-Abfrage ist:

$tagid = Db::select("SELECT `id` FROM `wouter_blog_tags` WHERE `slug` = '".$this->param('slug')."'"); 

$blog = Db::select("SELECT * 
      FROM `wouter_blog_posts` 
      WHERE `published` IS NOT NULL 
      AND `published` = '1' 
      AND `published_at` IS NOT NULL 
      AND `published_at` < NOW() 
      AND (

      SELECT count(*) 
      FROM `wouter_blog_tags` 
      INNER JOIN `wouter_blog_posts_tags` ON `wouter_blog_tags`.`id` = `wouter_blog_posts_tags`.`tags_id` 
      WHERE `wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id` 
      AND `id` 
      IN (
      '".$tagid[0]->id."' 
      )) >=1 
      ORDER BY `published_at` DESC 
      LIMIT 10 
      OFFSET 0"); 

Wo ich jetzt an den Query Builder Ende zu konvertieren ist:

$test = Db::table('wouter_blog_posts') 
->where('published', '=', 1) 
->where('published', '=', 'IS NOT NULL') 
->where('published_at', '=', 'IS NOT NULL') 
->where('published_at', '<', 'NOW()') 
    ->select(Db::raw('count(*) wouter_blog_tags')) 
->join('wouter_blog_posts_tags', function($join) 
{ 
$join->on('wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id') 
->on('wouter_blog_posts_tags.post_id', '=', 'wouter_blog_posts.id') 
->whereIn('id', $tagid[0]->id); 
}) 
->get(); 

Ich habe gelesen, dass ich nicht bei dem in einem Join verwenden kann. Der Fehler, den ich jetzt bekommen:

Call to undefined Methode Illuminate \ Database \ Abfrage \ JoinClause :: worin()

ich wirklich weiß nicht, wie ich meine SQL umwandeln kann Builder abzufragen. Ich hoffe, wenn ich eine gute Umsetzung meiner Anfrage sehe, kann ich verstehen, wie ich es beim nächsten Mal machen muss.

+0

ich habe nicht versucht, aber vielleicht verwenden '> whereRaw ([$ MarkierungslD [0] -> id]) '. Stellen Sie einfach sicher, dass der Bindungsparameter am Ende ein Array ist.Ich weiß jedoch nicht, warum Sie WHERE IN für einen Wert verwenden - $ tagid [0] -> id. Gibt dies ein Array oder etwas zurück? Hier ist eine alternative Lösung http://stackoverflow.com/questions/26913776/laravel-4-add-wholein-clause-to-a-join-condition –

Antwort

0

Diese Arbeit für mich:

DB :: Tabelle ('wouter_blog_posts') -> whereNotNull ('veröffentlicht') -> where ('veröffentlicht', 1) -> whereNotNull (‘ published_at ') -> whereRaw (' published_at < NOW() ') -> whereRaw ("(SELECT COUNT (*) FROM wouter_blog_tags INNER JOIN wouter_blog_posts_tags ON wouter_blog_tagsid = wouter_blog_posts_tagstags_id.. 0 WO wouter_blog_posts_tags. post_id = wouter_blog_posts. id UND id IN ( ' "$ MarkierungslD.."' ))> = 1") -> orderBy ('published_at', 'desc') -> überspringen (0) -> nehmen (10 ) -> Paginieren ($ this-> property ('postsPerPage')); - '? id IN'

0

Die folgende Query Builder Code geben Sie die genaue SQL-Abfrage Sie in Ihrem haben DB::select:

DB::table('wouter_blog_posts') 
    ->whereNotNull('published') 
    ->where('published', 1) 
    ->whereNotNull('published_at') 
    ->whereRaw('`published_at` < NOW()') 
    ->where(DB::raw('1'), '<=', function ($query) use ($tagid) { 
     $query->from('wouter_blog_tags') 
      ->select('count(*)') 
      ->join('wouter_blog_posts_tags', 'wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id') 
      ->whereRaw('`wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`') 
      ->whereIn('id', [$tagid[0]->id]); 
    }) 
    ->orderBy('published_at', 'desc') 
    ->skip(0) 
    ->take(10) 
    ->get(); 

Die Unterabfrage Zustand rückgängig gemacht werden musste, weil Sie nicht eine Unterabfrage als ersten Parameter der haben kann where Methode und immer noch in der Lage, den Zustandswert zu binden. Also ist es 1 <= (subquery), was (subquery) >= 1 entspricht. Die Abfrage nach dem obigen Code erzeugt wird wie folgt aussehen:

SELECT * 
FROM `wouter_blog_posts` 
WHERE `published` IS NOT NULL 
     AND `published` = 1 
     AND `published_at` IS NOT NULL 
     AND `published_at` < Now() 
     AND 1 <= (SELECT `count(*)` 
       FROM `wouter_blog_tags` 
         INNER JOIN `wouter_blog_posts_tags` 
           ON `wouter_blog_tags`.`id` = 
           `wouter_blog_posts_tags`.`tags_id` 
       WHERE `wouter_blog_posts_tags`.`post_id` = 
         `wouter_blog_posts`.`id` 
         AND `id` IN (?)) 
ORDER BY `published_at` DESC 
LIMIT 10 offset 0 

Mein Prozess, wenn komplexere Abfragen zu schaffen ist, zuerst sie, um sie in einer SQL-Umgebung zu erstellen und versuchen, um sicherzustellen, dass sie als indended arbeiten. Dann implementiere ich sie Schritt für Schritt mit dem Query Builder, aber anstatt get() am Ende der Abfrage zu verwenden, verwende ich toSql(), die mir eine String-Repräsentation der Abfrage geben wird, die vom Query Builder erzeugt wird, damit ich vergleichen kann das zu meiner ursprünglichen Abfrage, um sicherzustellen, dass es das gleiche ist.

+0

der Query Builder funktioniert völlig anders, als ich erwarten würde. Ich verstehe das nicht: -> '1', '<=', Funktion ($ query) benutze ($ tagid [0] -> id). Es gibt keine Spalte 1 Der Fehler, den ich bekomme: Syntaxfehler, unerwartete '' 1 '' (T_CONSTANT_ENCAPSED_STRING), erwartet Bezeichner (T_STRING) oder Variable (T_VARIABLE) oder '{' oder '$' – Wouter

+0

Das war mein Fehler, ich habe nicht Beachten Sie, dass, weil ich die Bedingung invertierte, der erste Parameter der where-Methode in Anführungszeichen gesetzt wird, weil dort eine Spalte erwartet wird. Ich habe meine Antwort aktualisiert, um 'DB :: raw' zu verwenden, was das behebt. – Bogdan