如何自定义Laravel的Database \ Query \ Builder(使子查询更好) [英] How to customize Laravel's Database\Query\Builder (make better subquery)

查看:275
本文介绍了如何自定义Laravel的Database \ Query \ Builder(使子查询更好)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究Laravel 4. 据我所知,我可以执行子查询:

I'm working on Laravel 4. As I knew, I can do subquery:

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

我发现了一些麻烦,因为我无法在子查询中使用作用域并禁用soft_delete,这使我改变了源代码太多了.......................................................................................................................................................................................................................................................................

I found complications, that I can't use scope in subquery and disable soft_delete make me change source code so much.

我希望是这样

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

现在,我可以添加范围,轻松禁用soft_delete.

Now, I can add scope, disable soft_delete easily.

我尝试并找到了解决方案,我必须更改Laravel的Database \ Query \ Builder代码(函数whereInSub,第786行).

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

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

收件人:

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

修改Laravel框架的供应商是有害的.所以我想问一下如何安全地做它.

It's harmful to modify Laravel framework's vendor. So I want to ask how to do it safely.

对不起,因为我的英语不好.

Sorry because my bad English.

感谢您阅读.

推荐答案

哦!这很棘手,因为您的模型将扩展Eloquent,然后Eloquent使用Illuminate\Database\Query\Builder.

Oooh! This is quite a tricky one since your model would extend Eloquent, then Eloquent uses Illuminate\Database\Query\Builder.

但是我注意到的是Eloquent实际上是app/config/app.php文件中的别名.因此,您可以按照以下步骤进行操作.

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

  1. 使用自定义whereInSub()Illuminate\Database\Query\Builder扩展到MyQueryBuilder.
  2. Illuminate\Database\Eloquent\Model扩展为MyModel,并将其设置为use您的MyQueryBuilder.
  3. app/config/app.php中的Eloquent别名设置为新的MyModel类.
  1. Extend Illuminate\Database\Query\Builder to MyQueryBuilder with your custom whereInSub().
  2. Extend Illuminate\Database\Eloquent\Model to MyModel and make it use your MyQueryBuilder.
  3. Set Eloquent alias in app/config/app.php to your new MyModel class.

类似这样的东西:

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

请注意,我在此处放置了长长的use列表,因为.另外,为了简单起见,我没有将MyQueryBuilderMyModel放在命名空间中.根据我们使用的Laravel版本,我的use列表也可能与您的列表不同,所以也请检查用法.

Note that I put long lists of use up there because "use" keyword does not get inherited. Also I did not put MyQueryBuilder and MyModel in a namespace for the sake of simplicity. My use list might also be different from yours depending on Laravel versions we use, so please check the uses too.

这篇关于如何自定义Laravel的Database \ Query \ Builder(使子查询更好)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆