2014-07-03 42 views
6

pracuję nad laravel 4. jak wiedziałem, co mogę zrobić podzapytania:Jak dostosować Database laravel za Zapytanie Builder (lepiej podzapytanie)

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

znalazłem komplikacji, że mogę” • użyj zakresu w podkwerendach i wyłącz opcję soft_delete, aby zmienić kod źródłowy tak bardzo.

Życzę było:

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

Teraz mogę dodać zakres, łatwo wyłączyć soft_delete.

Próbowałem i znaleźć rozwiązanie, że muszę zmienić laravel za Database \ Zapytanie \ kod Builder, function whereInSub, linia 786.

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

do:

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

To szkodliwe zmodyfikować Dostawca Laravel framework's. Chciałbym zapytać, jak to zrobić bezpiecznie.

Przepraszam, ponieważ mój zły angielski.

Dziękuję za przeczytanie.

Odpowiedz

12

Oooh! Jest to dość podchwytliwe, ponieważ Twój model będzie rozszerzony o Eloquent, a następnie Eloquent używa Illuminate\Database\Query\Builder. Jest to alias w pliku app/config/app.php. Możesz więc wykonać te kroki.

  1. Extend Illuminate\Database\Query\Builder do MyQueryBuilder ze swoim zwyczajem whereInSub().
  2. Przedłuż Illuminate\Database\Eloquent\Model do MyModel i ustaw go na use pod numer MyQueryBuilder.
  3. Ustaw alias w app/config/app.php na swoją nową klasę .

coś takiego:

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', 
    ... 
); 

Zauważ, że kładę długich list od use tam ponieważ "use" keyword does not get inherited. Również nie wstawiłem MyQueryBuilder i MyModel w przestrzeni nazw ze względu na prostotę. Moja lista use może również różnić się od Twojej w zależności od wersji Laravel, których używamy, więc sprawdź również zastosowania.

+4

Zmieniliśmy moje pytanie, ponieważ znalazłem rozwiązanie. Konieczność zastąpienia funkcji chronionej newBaseQueryBuilder() w nowej klasie MyModel –

+0

Nie ma potrzeby dodawania list "użytkowania", chyba że faktycznie ... używasz ich w swojej podklasie. W tym przypadku potrzebujesz tylko MyQueryBuilder, który byłby użyty w nadpisanej wersji newBaseQueryBuilder() jak dokładnie wskazano @ LêTrầnTiếnTrung. – LePhleg