我遇到了同样的问题(PHP 7.2 + Laravel 5.3),但我在这里没有看到任何“好的”答案。对我来说,当我尝试从模型上的范围方法启动 Builder 时出现问题:SomeModel::forUser() calls scopeForUser()。尝试构建一个新查询时,它会在没有初始值 (null) 的 count($this->wheres) 上跳闸。因为对作用域的神奇静态调用启动了构建器,所以没有在对象中放置其他条件,所以此时属性仍然是 null。
我认为值得先分享我的解决方案,然后再看看为什么我认为它比 Ben 的答案更好。这不是个人的,我只是不同意。
解决方案
我从 this answer 那里得到了关于覆盖一些核心 Illuminate\Database 类的提示...
- 扩展
Illuminate\Database\Eloquent\Model
我的是App\Overrides\Database\Eloquent\Model
- 扩展
Illuminate\Database\Eloquent\Builder
我的是App\Overrides\Database\Eloquent\Builder
- 扩展
Illuminate\Database\Query\Builder
猜一下? App\Overrides\Database\Query\Builder
- 告诉 Laravel 使用你的
Eloquent\Model:
config/app.php 'aliases' 数组,替换 'Eloquent' 值
与您的Eloquent\Model FQN
我的Model:
namespace App\Overrides\Database\Eloquent;
/*
* Notes:
* * Using replacement Query\Builder with ALIAS
* * Use of Builder in this class is MY Eloquent\Builder
*/
use App\Overrides\Database\Query\Builder as QueryBuilder;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Model extends EloquentModel
{
public function newEloquentBuilder($query)
{
return new Builder($query);
}
protected function newBaseQueryBuilder()
{
$conn = $this->getConnection();
$grammar = $conn->getQueryGrammar();
return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
}
}
我的Eloquent\Builder:
namespace App\Overrides\Database\Eloquent;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
class Builder extends EloquentBuilder
{
public function __construct($query)
{
parent::__construct($query);
/*
* FIX #1: Set properties treated AS arrays
* to empty arrays on construct.
*/
$this->wheres = [];
// Any other properties treated as arrays should also be initialized.
}
}
我的Query\Builder:
namespace App\Overrides\Database\Query;
use Illuminate\Database\Query\Builder as QueryBuilder;
class Builder extends QueryBuilder
{
public function __construct()
{
parent::__construct(...func_get_args());
/*
* FIX #2: Set properties treated AS arrays
* to empty arrays on construct.
*/
$this->wheres = [];
// Any other properties treated as arrays should also be initialized.
}
}
这可以安全地保留框架的功能,因为您所做的唯一实际更改是初始化本应放在首位的属性。其他所有内容都将通过用于动态加载和依赖注入的instanceof 检查。
意见
虽然我同意 @ben-harold 关于他所说的“永远不要编辑供应商代码”的每条评论,但我不同意“解决方案”。这是对更复杂的问题的过度简化。
升级 Laravel:为确保对 PHP 7.2 的支持,升级几个次要版本(如果不是主要版本)对于许多团队来说是不切实际的。作为一个长期目标,当然可以。作为我可以做些什么来摆脱我的最后期限的错误?没有。随着结构、名称和功能的变化,升级需要大量的计划和频繁的重写。这是需要优先考虑的事情,但不是现在需要的答案。
降级 PHP:同样的问题。降级到 PHP 5.x 意味着 A) PHP 是 EOL,这对于许多拥有安全策略的客户来说可能是一个交易破坏者,并且 B) 任何使用 PHP 7.x 语言功能的行为都必须废弃。与升级框架一样,这很可能会引起很多麻烦。这也是一个更没用的解决方案,因为在语言中倒退只会让你落后,需要更多的长期努力。