2014-07-03 5 views
6

Sto lavorando su laravel 4. come sapevo, posso fare subquery:Come personalizzare Database di laravel Query Builder (fare un migliore subquery)

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

ho trovato complicazioni, che posso' t usare scope in subquery e disabilitare soft_delete mi fa cambiare codice sorgente così tanto.

vorrei che fosse:

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

Ora, posso aggiungere portata, disabilitare soft_delete facilmente.

ho provato, e hanno trovato una soluzione, che devo cambiare il codice di laravel Database \ Query \ Builder, la funzione whereInSub, linea 786.

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

a:

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

E 'dannoso per modificare Il fornitore del framework Laravel. Quindi voglio chiedere come farlo in modo sicuro.

Scusa perché il mio pessimo inglese.

Grazie per la lettura.

risposta

12

Oooh! Questo è piuttosto complicato dal momento che il tuo modello dovrebbe estendere Eloquent, quindi Eloquent utilizza Illuminate\Database\Query\Builder.

Ma quello che ho notato è che Eloquent è in realtà un alias nel file app/config/app.php. Quindi quello che puoi fare è seguire questi passaggi.

  1. Estendere Illuminate\Database\Query\Builder per MyQueryBuilder con la vostra abitudine whereInSub().
  2. Estendere Illuminate\Database\Eloquent\Model a MyModel e renderlo use il MyQueryBuilder.
  3. Impostare Eloquent alias in app/config/app.php nella nuova classe MyModel.

Qualcosa di simile a questo:

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

Nota che ho messo lunghe liste di use lassù perché "use" keyword does not get inherited. Inoltre non ho inserito MyQueryBuilder e MyModel in uno spazio dei nomi per motivi di semplicità. La mia lista use potrebbe anche essere diversa dalla tua, a seconda delle versioni di Laravel che utilizziamo, quindi controlla anche gli usi.

+4

Ho risolto la mia domanda perché ho trovato una soluzione. È necessario eseguire l'override della funzione protetta newBaseQueryBuilder() nella nuova classe MyModel –

+0

Non è necessario includere elenchi di "utilizzo" a meno che non si stia effettivamente ... utilizzandoli nella sottoclasse. In questo caso hai solo bisogno del tuo MyQueryBuilder, che verrebbe utilizzato nella versione sovrascritta di newBaseQueryBuilder() come @ LêTrầnTiếnTrung ha puntualizzato con precisione. – LePhleg

Problemi correlati