37

我面临着奇怪的情况。我在生产环境中遇到错误,而不是在开发环境中它工作正常。

开发:Laravel 5.4.28 PHP 7.0.13 MYSQL 5.7.17

生产:Laravel 5.4.28 PHP 7.2.1 MYSQL 5.7.20

在实现代码中。我用了:

namespace App;
use Illuminate\Support\Facades\Storage;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;

class Artwork extends Model
{
  use Searchable;

在开发中它工作正常。但在生产中它给了我这个错误:count(): Parameter must be an array or an object that implement Countable in Builder.php (line 936)

正如你在这张照片中看到的:

在此处输入图像描述

知道这背后的原因是什么吗?以及如何解决?

4

14 回答 14

64

将此代码放在route文件的开头,它将正常工作

if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
    error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
于 2018-11-22T07:29:44.560 回答
51

这是PHP 7.2 中记录的更改。您需要将 Laravel 更新到 5.6 或将 PHP 降级到 7.1 版。

于 2018-03-12T22:01:28.970 回答
16

代替

$originalWhereCount = count($query->wheres);

经过

$originalWhereCount = count((array)$query->wheres);

\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php

于 2019-08-27T08:14:08.720 回答
8

我在 Laravel 5.6 中遇到了类似的问题。基于对象的数组在哪里出现错误。我知道该特定变量中的数据将始终保留为对象,因此我曾经将对象转换为数组。这是代码示例: $objectData = (array)$objectData; echo "Total Elements in array are: ".count($objectData);

于 2018-09-15T05:59:00.880 回答
7

当我更新到 PHP 7.2时,我的服务器在PHP 7.1上,我遇到了同样的问题。

经过搜索,我发现了为什么会发生这种情况。(这是由于 PHP 更新而发生的。)。

所以在我的情况下,错误是通过类型转换解决的。

我只是更新了我曾经计算过的所有代码

//this is before     
count($adminDetails)

更新后

//after update all i typecast all the code where i used count
count((array)$adminDetails)

祝你好运

于 2020-10-05T10:32:44.673 回答
5

在 php 7.2+ 中计数不适用于关系对象,您需要使用:

$model->relation()->exists()

不是这个(低于 php 7.2):

count($model->relation)
于 2020-05-15T18:38:14.213 回答
2

我遇到了同样的问题(PHP 7.2 + Laravel 5.3),但我在这里看不到任何“好”的答案。对我来说,当我尝试从模型上的范围方法启动生成器时会出现问题:SomeModel::forUser() calls scopeForUser(). 尝试构建一个新的 Query,它count($this->wheres)会在没有初始值 ( null) 的情况下跳闸。因为对作用域的神奇静态调用启动了构建器,所以没有在对象中放置其他条件,所以属性仍然null在那个点。

我认为值得先分享我的解决方案,然后再看看为什么我认为它比 Ben 的答案更好。这不是个人的,我只是不同意。

解决方案

我从这个答案中得到了关于覆盖一些核心Illuminate\Database类的提示......

  1. 扩展Illuminate\Database\Eloquent\Model
    我的是App\Overrides\Database\Eloquent\Model
  2. 扩展Illuminate\Database\Eloquent\Builder
    我的是App\Overrides\Database\Eloquent\Builder
  3. 扩展Illuminate\Database\Query\Builder
    你能猜到吗?App\Overrides\Database\Query\Builder
  4. 告诉 Laravel 使用 YOUR Eloquent\Model:
    config/app.php 'aliases'数组,将'Eloquent'
    替换为Eloquent\ModelFQN

我的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 语言功能的任何使用。与升级框架一样,这很可能会引起很多麻烦。这也是一个更没用的解决方案,因为在语言中倒退只会让你更落后,并且需要更多的长期努力。

于 2020-05-29T21:38:51.057 回答
1

我在使用外部创建的表(不使用迁移或命令)时遇到了同样的问题,在创建模型后,我只是分配了一个表名,但问题出在我的模型protected $fillable中,我分配了字符串而不是数组并且发生了错误。有两种可能的解决方案。

  1. 将数组分配给您的protected $fillable = ['filed1', 'filed2'];
  2. 完全删除protected $fillable(不推荐)
class Abc extends Model
{
     protected  $table = 'cities';
     protected $fillable = ['field1','field2', ...];
}
于 2019-11-07T09:33:00.417 回答
1

寻找可数参数的模型:

class ClassName extend Model {
    protected $fillable=['column_name']; // column in DB of Model is in array
}
于 2020-01-25T10:29:53.670 回答
0

将下面的 ob 代码放在控制器中的类名之前

if (version_compare(PHP_VERSION, '7.2.0', '>=')) {
// Ignores notices and reports all other kinds... and warnings
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
// error_reporting(E_ALL ^ E_WARNING); // Maybe this is enough
}
于 2018-11-07T03:02:10.590 回答
0

我在这种情况下使用 laravel 6.x,你可以这样使用:

 $id = \DB::table('xxxx')->where('id', $id)->count();
于 2020-11-25T08:45:43.247 回答
0

发生此错误是因为您使用的是更高的 PHP 版本,并且您的 Laravel 应用程序使用的是旧的 PHP 版本。

✅ 简单的解决方案:

打开:app/Providers/AppServiceProvider.php

并在:public function register() { ... } function 添加以下代码:

if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
    error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
于 2021-12-06T04:51:49.413 回答
-1

'vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php' 到:

$originalWhereCount = is_array($query->wheres) ? count($query->wheres) : 0;
于 2019-12-30T07:34:22.563 回答
-3

我在 Laravel 5.6 中解决了这个问题

// 在控制器中

public function index()
{
$todos = Todo::all();
return view('todos.index')->with(['todos' => $todos]);

}

// 在视图页面中

@if(count($todos) > 0)
  @foreach($todos as $todo)
    <div class="well">
      <h3>{{$todo->text}}</h3>
      <span class="label label-danger">{{$todo->due}}</span>
    </div>
  @endforeach
@endif
于 2018-05-17T04:25:18.337 回答