如何在laravel中扩展joinclause类

4nkexdtk  于 2021-06-15  发布在  Mysql
关注(0)|答案(0)|浏览(215)

我们想扩展query\builder用来制定连接子句的joinclause类。
我们已经像这样扩展了basemodel的查询生成器:(本质上,corebasemodel只是一个带有一些额外函数的模型。)

abstract class BaseModel extends CoreBaseModel
{
    function newBaseQueryBuilder()
    {
        return new BaseModelQueryBuilder($this->getConnection());
    }
}

basemodelquerybuilder中的示例代码:

class BaseModelQueryBuilder extends Builder
{
    function findOverlapping($from, $till, $from_column, $till_column)
    {
        return $this
            ->orWhereBetween($from_column, [$from, $till])
            ->orWhereBetween($till_column, [$from, $till])
            ->orWhere(function($query) use($from_column, $till_column, $from, $till)
            {
                //Around
                $query
                    ->where($from_column, '<=' , $from)
                    ->where($till_column, '>=', $till);
            });
    }
}

这很好,因为您可以使用findoverlapping函数,不仅在该模型的每个查询中,而且在每个子查询中。
问题是,这对高级联接子句不起作用:

BaseModel::join('table_name', function($join)
{
    $join->where(function($query)
    {
        $query->findOverlapping('2018-01-01', '2018-21-31', 'from', 'till');
    });
});

错误是:

Call to undefined method Illuminate\Database\Query\JoinClause::findOverlapping()

所以我一直在努力寻找解决这个问题的方法,在 Illuminate\Database\Query\Builder 看起来是这样的:

/**
 * Add a join clause to the query.
 *
 * @param  string  $table
 * @param  \Closure|string  $first
 * @param  string|null  $operator
 * @param  string|null  $second
 * @param  string  $type
 * @param  bool    $where
 * @return $this
 */
public function join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false)
{
    $join = new JoinClause($this, $type, $table);

    // If the first "column" of the join is really a Closure instance the developer
    // is trying to build a join with a complex "on" clause containing more than
    // one condition, so we'll add the join and call a Closure with the query.
    if ($first instanceof \Closure) {
        call_user_func($first, $join);

        $this->joins[] = $join;

        $this->addBinding($join->getBindings(), 'join');
    }

    // If the column is simply a string, we can assume the join simply has a basic
    // "on" clause with a single condition. So we will just build the join with
    // this simple join clauses attached to it. There is not a join callback.
    else {
        $method = $where ? 'where' : 'on';

        $this->joins[] = $join->$method($first, $operator, $second);

        $this->addBinding($join->getBindings(), 'join');
    }

    return $this;
}

所以我把函数复制到 BaseModelQueryBuilder ,制作了一份 Illuminate\Database\Query\JoinClause 类,并将其分配给重写联接函数的第一条语句: $join = new BaseModelJoinClause($this, $type, $table) 请注意,我没有改变任何代码中 BaseModelJoinClause 类与原始类比较 JoinClause 类别(除 use 语句和命名空间(ofc)。尽管如此,即使有这种细微的变化(只分配了一个与原始类完全相同的新类),所有查询都会失败,并出现如下错误: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax .
如果有人知道如何解决这个问题,或者有任何在laravel上扩展joinclause类的经验,欢迎任何帮助:)如果您认为需要更多信息,请告诉我。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题