我正在研究Laravel 4。 据我所知,我可以做子查询:
Project::whereIn('project_id', function($q) {
$q->select('project_id')
->from('company')
->whereNull('deleted_at');
});
我发现了并发症,我无法在子查询中使用范围并禁用soft_delete让我更改源代码。
我希望是:
Project::whereIn('project_id', function(&$q) {
$q = Company::select('project_id')->getQuery();
});
现在,我可以添加范围,轻松禁用soft_delete。
我试过,并找到了一个解决方案,我必须更改Laravel的Database \ Query \ Builder代码,函数whereInSub,第786行。
call_user_func($callback, $query = $this->newQuery());
为:
$query = $this->newQuery();
call_user_func_array($callback, array(&$query));
修改Laravel框架的供应商是有害的。所以我想问一下如何安全地做到这一点。
抱歉,因为我的英语不好。
感谢您的阅读。
答案 0 :(得分:13)
哦!这非常棘手,因为您的模型会扩展Eloquent
,然后Eloquent
会使用Illuminate\Database\Query\Builder
。
但我注意到Eloquent
实际上是app/config/app.php
文件中的别名。所以你可以做的就是遵循这些步骤。
Illuminate\Database\Query\Builder
将MyQueryBuilder
扩展为whereInSub()
。Illuminate\Database\Eloquent\Model
扩展为MyModel
并将use
MyQueryBuilder
Eloquent
。app/config/app.php
中的MyModel
别名设置为新的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;
}
}
课程。这样的事情:
<强> MyQueryBuilder.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
{
}
<强> MyModel.php:强>
'aliases' => array(
...
'Eloquent' => 'MyModel',
...
);
应用/配置/ app.php:强>
use
请注意,由于"use" keyword does not get inherited,我在其中列出了MyQueryBuilder
长列表。另外,为简单起见,我没有将MyModel
和use
放在命名空间中。根据我们使用的Laravel版本,我的{{1}}列表可能与您的列表不同,因此请检查用途。
答案 1 :(得分:2)
您可以创建一个自定义查询构建器并像这样使用它。
我的自定义查询生成器:
use Illuminate\Database\Query\Builder as QueryBuilder;
class MyCustomBuilder extends QueryBuilder{
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;
}
}
在任何模型中都覆盖方法newBaseQueryBuilder()并返回您自己的查询生成器的实例
class MyModel extends Model{
protected function newBaseQueryBuilder()
{
$connection = $this->getConnection();
return new MyQueryBuilder(
$connection, $connection->getQueryGrammar(),
$connection->getPostProcessor()
);
}
}