Reputation: 451
I'm facing strange case. I face an error in production env not while in dev it's working fine.
Development: Laravel 5.4.28 PHP 7.0.13 MYSQL 5.7.17
Production: Laravel 5.4.28 PHP 7.2.1 MYSQL 5.7.20
In implementation code. I used:
namespace App;
use Illuminate\Support\Facades\Storage;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Artwork extends Model
{
use Searchable;
In development it works fine. But in production it gives me this error: count(): Parameter must be an array or an object that implements Countable in Builder.php (line 936)
as you can see in this pic:
Any idea what is the reason behind this? and how to fix?
Upvotes: 45
Views: 112557
Reputation: 23
Before
count($collection['colors'])
Error:Expected type 'Countable|array'. Found 'string'
After
count((array)$collection['colors'])
It works for me!
Upvotes: 0
Reputation: 629
This error occurs because you are using a higher PHP version and your Laravel application is on an older PHP version.
✅ Simple solution:
Open: app/Providers/AppServiceProvider.php
And in: public function register() { ... } function add following code:
if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
Upvotes: 8
Reputation: 51
In php 7.2+ count does not work on relation objects, you need to use:
$model->relation()->exists()
Not this (less than php 7.2):
count($model->relation)
Upvotes: 5
Reputation: 883
Put this code at the beginning of your route
file, it will work fine
if(version_compare(PHP_VERSION, '7.2.0', '>=')) {
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
}
Upvotes: 73
Reputation: 1053
I;m using laravel 6.x for this case you can use this way:
$id = \DB::table('xxxx')->where('id', $id)->count();
Upvotes: -1
Reputation: 475
i ran into the same problem (PHP 7.2 + Laravel 5.3) but i don't see any "good" answers here. For me, the problem occurs when i tried to start a Builder from a scope method on the model: SomeModel::forUser() calls scopeForUser()
. Trying to build a new Query, it trips on a count($this->wheres)
that gets no initial value (null
). Because the magic static call to the scope starts the builder, no other conditions have been placed in the object so the property is still null
at that point.
i thought it's worth sharing my solution first, then perspective on why i consider it better than Ben's answer. It's not personal, i just disagree.
i took a cue from this answer about overriding some of the core Illuminate\Database
classes...
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
Eloquent\Model
:'aliases'
array, replace the 'Eloquent'
valueEloquent\Model
FQNMy 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());
}
}
My 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.
}
}
My 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.
}
}
This safely preserves the framework's functionality, since the only actual change you're making is initializing properties that should have been in the first place. Everything else will pass instanceof
checks used for dynamic loading and dependency injection.
While i agree with @ben-harold about every comment he made saying "NEVER edit vendor code," i disagree with the "solution." It's an oversimplification to a much more complex problem.
Upgrade Laravel: to ensure support for PHP 7.2, jumping up several minor versions - if not major releases - is impractical for a lot of teams. As a long term objective, yes of course. As something i can do to get rid of the bug for my deadline? Nope. Upgrading takes a lot of planning and frequently a lot of rewrites as structures, names, and functionality change. It's something to prioritize, but not a need-it-now answer.
Downgrade PHP: same problem. Downgrading into PHP 5.x means A) PHP is EOL, which may be a deal breaker for a lot of customers who have security policies, and B) any usage of PHP 7.x language features have to be scrapped. As with upgrading the framework this is very likely to cause a lot of headaches. It's also an even less useful solution, since walking backward in the language just puts you farther behind and will require more long-term effort.
Upvotes: 3
Reputation: 5814
My server was on PHP 7.1 when I updated to PHP 7.2 I got the same issue.
After searching I found why this occurs. (This occurs because of a PHP update.).
so in my case, the error is solved by typecasting.
I just update all code where I used to count
Before
//this is before
count($adminDetails)
After updated
//after update all i typecast all the code where i used count
count((array)$adminDetails)
Goodluck
Upvotes: 9
Reputation: 31
Model looking for countable parameter:
class ClassName extend Model {
protected $fillable=['column_name']; // column in DB of Model is in array
}
Upvotes: 1
Reputation: 11
'vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php' to:
$originalWhereCount = is_array($query->wheres) ? count($query->wheres) : 0;
Upvotes: -1
Reputation: 93
I was facing the same issue with an external created table (Not using migration or command),
After creating the model, I just assigned a table name, but the problem was in my model protected $fillable
where I assign string instead of array and error occurred.
There is 2 possible solution for that.
protected $fillable = ['filed1', 'filed2'];
protected $fillable
completely (Not Recommended)class Abc extends Model
{
protected $table = 'cities';
protected $fillable = ['field1','field2', ...];
}
Upvotes: 1
Reputation: 596
Replace
$originalWhereCount = count($query->wheres);
by
$originalWhereCount = count((array)$query->wheres);
in
\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php
Upvotes: 18
Reputation: 83
place the below line ob code before the class name in your controllers
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
}
Upvotes: 1
Reputation: 294
I was facing similar issue in Laravel 5.6. Where I was getting error for object based array. I knew that data in that particular variable will always remain object so i used to convert the object to array. Here is code sample:
$objectData = (array)$objectData;
echo "Total Elements in array are: ".count($objectData);
Upvotes: 8
Reputation: 1
I Solve this in Laravel 5.6
// in controller
public function index()
{
$todos = Todo::all();
return view('todos.index')->with(['todos' => $todos]);
}
// in view page
@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
Upvotes: -3
Reputation: 6432
This is a documented change in PHP 7.2. You need to either update Laravel to 5.6 or downgrade PHP to version 7.1.
Upvotes: 53