How to configure Laravel Database \ Query \ Builder (make the best subquery)

I am working on Laravel 4. As I knew, I can make a subquery:

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

I found complications that I cannot use the scope in the subquery and disable soft_delete to change the source code.

I would like to:

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

Now I can add an area, it is easy to disable soft_delete.

I tried and found a solution that I should change the code Laravel Database \ Query \ Builder, function whereInSub, line 786.

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

in

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

This is bad for modifying the Laravel infrastructure provider. So I want to ask how to do it safely.

Sorry because my bad english.

Thanks for reading.

+6
source share
1 answer

Ohhhh! This is quite complicated, since your model extends Eloquent , then Eloquent uses Illuminate\Database\Query\Builder .

But I noticed that Eloquent is actually an alias in the app/config/app.php . So what you can do is follow these steps.

  • Extend Illuminate\Database\Query\Builder to MyQueryBuilder with your custom whereInSub() .
  • Extend Illuminate\Database\Eloquent\Model to MyModel and make it use your MyQueryBuilder .
  • Set the Eloquent alias in app/config/app.php for your new MyModel class.

Something like that:

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 { } 

application /Config/app.php:

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

Please note that I put long use lists there because the "use" keyword does not get inherited . Also, I just did not put MyQueryBuilder and MyModel in the namespace for simplicity. My use list may also differ from yours, depending on the versions of Laravel we use, so please also check the usage.

+12
source

Source: https://habr.com/ru/post/971708/


All Articles