php - 如何在 laravel 中扩展 JoinClause 类
问题描述
我们想扩展 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()
所以我一直在四处寻找解决这个问题的方法,发现上面的 join 函数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
(除了 fromuse
语句和命名空间 ofc)。尽管如此,即使有这种细微的变化(只分配了新类,它是原始类的精确副本),所有查询都会开始失败,并出现以下错误:SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax
.
如果有人对如何解决此问题有一些提示,或者有任何在 laravel 上扩展 JoinClause 类的经验,欢迎提供任何帮助 :) 如果您认为您需要更多信息,请告诉我。
解决方案
推荐阅读
- php - 为什么这个while循环没有在它应该结束的时候结束?
- node.js - !推送被拒绝,无法编译 Node.js 应用程序。!推送失败
- python - 在 Python 中使用 Spotify 的 API 从播放列表中获取曲目的 ID
- c++ - 带可变参数的函数调用不正确
- sql - SQL 计数值保持不变的记录数
- c# - 列表
与 ArrayBufferWriter 的行为不同 ? - python - 使用 for 循环时出现索引错误
- javascript - 多个复选框选定的元素传递到数组并从另一个数组显示在 vue js 中选中
- c# - 如何找到 n 个最常见的元素?
- dropzone - DropZone:如何接受 .csv 文件?