0

Ok Im using Illuminate on my php project and recently upgrade from PHP 5 to PHP 7.2.

I have this scope in my Model

Model.php

public function scopeWhereInOrAny(Builder $query, $field, $value)
    {
        if ($value === null || $value === '' || count($value) === 0) {
            return $query;
        }

        return $query->whereIn($field, $value);
    }

a pretty simple scope to accept null when using whereIn. Now I use it in a function

public function getList($params = []) {
        
        $cancelReasons = CancellationReasons
            ::orderBy('id', 'asc')
            ->whereInOrAny('type_booking', $params['type_booking']) // HERE
            ->where('status', '=', 1)
            ->get(['id','name','type_client']);

        return $cancelReasons;

And when I call that method, it kinda works, it returns what it should return but also adds a warning at the end like this

[{"id":1,"name":"He cancelado mi viaje","type_client":1},{"id":2,"name":"Quiero hacer otra actividad","type_client":1},{"id":3,"name":"Quiero modificar la reserva","type_client":1},{"id":4,"name":"He encontrado un precio m\u00e1s barato en otra web","type_client":1},{"id":5,"name":"El proveedor me ha pedido que cancele","type_client":1},{"id":6,"name":"Otros motivos","type_client":1},{"id":7,"name":"Condiciones climatol\u00f3gicas","type_client":2},{"id":8,"name":"Problemas en el destino","type_client":2},{"id":9,"name":"No hay un n\u00famero m\u00ednimo de personas","type_client":2},{"id":10,"name":"Falta de disponibilidad","type_client":2},{"id":11,"name":"Restricciones Covid","type_client":2},{"id":12,"name":"Cancelaci\u00f3n solicitada por el cliente","type_client":2},{"id":13,"name":"Otros motivos","type_client":2},{"id":14,"name":"Cese de la colaboraci\u00f3n con el proveedor","type_client":3},{"id":15,"name":"El proveedor no realiz\u00f3 la actividad","type_client":3},{"id":16,"name":"Otros motivos","type_client":3}]<br />
<b>Warning</b>:  count(): Parameter must be an array or an object that implements Countable in <b>/var/www/html/newadmin/vendor7/illuminate/database/Eloquent/Builder.php</b> on line <b>1015</b><br />

Now debugging I found the issue is here in Builder.php


/**
     * Apply the given scope on the current builder instance.
     *
     * @param  callable $scope
     * @param  array $parameters
     * @return mixed
     */
    protected function callScope(callable $scope, $parameters = [])
    {
        array_unshift($parameters, $this);

        $query = $this->getQuery();

        // We will keep track of how many wheres are on the query before running the
        // scope so that we can properly group the added scope constraints in the
        // query as their own isolated nested where statement and avoid issues.
        $originalWhereCount = count($query->wheres); // HERE IS THE PROBLEM

        $result = $scope(...array_values($parameters)) ?: $this;

        if (count($query->wheres) > $originalWhereCount) {
            $this->addNewWheresWithinGroup($query, $originalWhereCount);
        }

        return $result;
    }

Aparently $query->wheres is equals null on this case and in php 7.2 when using count on null it throws a warning, now why $query->wheres is equals to null? because there are no other wheres before the custom scope so if I change the order of my wheres to

public function getList($params = []) {
    
        $cancelReasons = CancellationReasons
            ::orderBy('id', 'asc')
            ->where('status', '=', 1) //This where before the scope
            ->whereInOrAny('type_booking', $params['type_booking'])
            ->get(['id','name','type_client']);

        return $cancelReasons;
    }


It works perfectly!, but I don't think this really solves the issue long term, sure it solves this particular case but now every time I want to use a scope I need to add a random where first? even if I don't need it? that doesn't seems to be right. So Im looking for a cleaner solution to this issue that will work with other parts where Im using a scope on the querybuilder.

I hope anybody can help me

  • What Laravel version are you using? Have you checked the `composer.json` for the required version of PHP? – Flame Sep 07 '21 at 12:22
  • If you don't want to upgrade Laravel, just add a `is_array($query->wheres)` test before it tries to `count()` – Machavity Sep 07 '21 at 12:33
  • Ok this is a Laravel incompatibility with PHP 7.2 but was fixed in [this PR](https://github.com/laravel/framework/pull/20258). The fix is in all laravel versions starting from 5.4.31. The code you shared looks like the Laravel 5.4 code but you don't seem to be using the latest patch version. Running `composer update` should fix that (and possibly reveal packages that don't work with PHP 7.2 since 5 to 7.2 is a pretty big jump). – apokryfos Sep 07 '21 at 12:35

0 Answers0