2014-07-03 13 views
6

Ich arbeite an Laravel 4. Als ich wusste, anpassen, ich subquery tun können:Wie Laravel der Datenbank query Builder (besser machen subquery)

Project::whereIn('project_id', function($q) { 
    $q->select('project_id') 
     ->from('company') 
     ->whereNull('deleted_at'); 
}); 

ich Komplikationen festgestellt, dass ich kann‘ t Verwenden Sie den Bereich in der Unterabfrage und deaktivieren Sie soft_delete, damit ich den Quellcode so oft ändere.

Ich wünschte, es war:

Project::whereIn('project_id', function(&$q) { 
    $q = Company::select('project_id')->getQuery(); 
}); 

Nun, ich Umfang hinzufügen, deaktivieren leicht soft_delete.

Ich habe versucht, und fand eine Lösung, dass ich Laravel der Datenbank \ query \ Builder Code, Funktion whereInSub, Linie 786.

call_user_func($callback, $query = $this->newQuery()); 

sich ändern muss:

$query = $this->newQuery(); 
call_user_func_array($callback, array(&$query)); 

Es ist schädlich zu ändern Laravel-Framework-Anbieter. Also möchte ich fragen, wie man es sicher macht.

Sorry, weil mein schlechtes Englisch.

Vielen Dank für das Lesen.

Antwort

12

Oooh! Dies ist ziemlich schwierig, da Ihr Modell Eloquent, dann EloquentIlluminate\Database\Query\Builder erweitert.

Aber was ich bemerkte, ist, dass Eloquent ist eigentlich ein Alias ​​in app/config/app.php Datei. Sie können also die folgenden Schritte ausführen.

  1. Illuminate\Database\Query\Builder zu MyQueryBuilder Extend mit Ihrem eigenen whereInSub().
  2. Erweitern Sie Illuminate\Database\Eloquent\Model zu MyModel und machen Sie use Ihre MyQueryBuilder.
  3. Setzen Sie Eloquent Alias ​​in app/config/app.php auf Ihre neue MyModel Klasse.

Etwas wie folgt aus:

MyQueryBuilder.php:

use Closure; 
use Illuminate\Support\Collection; 
use Illuminate\Database\ConnectionInterface; 
use Illuminate\Database\Query\Grammars\Grammar; 
use Illuminate\Database\Query\Processors\Processor; 

class MyQueryBuilder extends Illuminate\Database\Query\Builder 
{ 
    protected function whereInSub($column, Closure $callback, $boolean, $not) 
    { 
     $type = $not ? 'NotInSub' : 'InSub'; 

     $query = $this->newQuery(); // Your changes 
     call_user_func_array($callback, array(&$query)); // Your changes 

     $this->wheres[] = compact('type', 'column', 'query', 'boolean'); 

     $this->mergeBindings($query); 

     return $this; 
    } 
} 

MyModel.php:

use DateTime; 
use ArrayAccess; 
use Carbon\Carbon; 
use LogicException; 
use Illuminate\Events\Dispatcher; 
use Illuminate\Database\Eloquent\Relations\Pivot; 
use Illuminate\Database\Eloquent\Relations\HasOne; 
use Illuminate\Database\Eloquent\Relations\HasMany; 
use Illuminate\Database\Eloquent\Relations\MorphTo; 
use Illuminate\Support\Contracts\JsonableInterface; 
use Illuminate\Support\Contracts\ArrayableInterface; 
use Illuminate\Database\Eloquent\Relations\Relation; 
use Illuminate\Database\Eloquent\Relations\MorphOne; 
use Illuminate\Database\Eloquent\Relations\MorphMany; 
use Illuminate\Database\Eloquent\Relations\BelongsTo; 
// use Illuminate\Database\Query\Builder as QueryBuilder; 
use Illuminate\Database\Eloquent\Relations\MorphToMany; 
use Illuminate\Database\Eloquent\Relations\BelongsToMany; 
use Illuminate\Database\Eloquent\Relations\HasManyThrough; 
use Illuminate\Database\ConnectionResolverInterface as Resolver; 
use MyQueryBuilder as QueryBuilder; // MyModel should now use your MyQueryBuilder instead of the default which I commented out above 

abstract class MyModel extends Illuminate\Database\Eloquent\Model 
{ 

} 

app/config/app.php:

'aliases' => array(
    ... 
    'Eloquent'  => 'MyModel', 
    ... 
); 

Bitte beachte, dass ich lange Listen von use da oben, weil "use" keyword does not get inherited setzen. Auch habe ich MyQueryBuilder und MyModel aus Gründen der Einfachheit nicht in einen Namensraum gestellt. Meine use Liste könnte sich auch von Ihrer unterscheiden, abhängig von den von uns verwendeten Laravel-Versionen. Überprüfen Sie daher auch die Verwendung.

+4

Ich habe meine Frage editiert, weil ich eine Lösung gefunden habe. Notwendigkeit, die geschützte Funktion newBaseQueryBuilder() in der neuen Klasse MyModel zu überschreiben –

+0

Sie müssen keine "Verwendungs" -Listen hinzufügen, es sei denn, Sie verwenden sie tatsächlich in Ihrer Unterklasse. In diesem Fall benötigen Sie nur Ihren MyQueryBuilder, der in der überschriebenen Version von newBaseQueryBuilder() als @ LêTrầnTiếnTrung genau angegeben würde. – LePhleg

Verwandte Themen