2

Hace unos dias me tope con este error al instalar php 7.2 count() parameter must be an array or an object that implements countable php 7 y quiero compartirles una solucion, que investigando llegue a esta.

me salia ese error porque tenia una funcion que me retornaba de esta forma

public static function verificarUsuarioModel($datos,$tabla){

    $query = Conexion::conectar()->prepare("SELECT id_usuario,dni,nombres,apellidos,num_tel,id_rol,username,CONCAT(nombres,' ',apellidos) AS fullname
                                            FROM $tabla
                                                $datos AND borrado = '0'  ");
    $query -> execute();

    return $query -> fetch(); //esto era lo que retornaba

    $query -> close();
}

y al llamar esa funcion en mi controlador de esta forma

$datos = $where = sprintf("WHERE CONCAT(nombres,' ',apellidos) = '%s' ",$fullname);
$respuesta = Usuario::verificarUsuarioModel($datos,"usuario");

la estaba verificando asi

  if(count($respuesta["nombres"]) > 0){
        return true;
    }

Lo que me generaba el error, ya que en php7.2 no lo reconoce como array y para evitar el error mencionado hice esto

if(!empty($respuesta["nombres"])){
    //procesar datos

}else{/*no tiene datos*/}

utilice esto !empty() por que por teoria al procesar la consulta retorna vacio o con datos, por eso verifique si $respuesta["nombres"] retornaba vacio o con algun dato, ademas que apartir de la version 7.2 de php hacia adelante count() no reconoce a return $query -> fetch(); como un array pero si enviamos de esta forma return $query -> fetchAll(); para el count() si es correcto porque retorna un array de datos entonces solo utilizar count() cuando retornamos con fetchAll(), espero les sirva de mucho

HRCody
  • 21
  • 6
  • Bienvenido a Stackoverflow. Lo que te estaba ocurriendo no es algo que tenga que ver con PHP 7, sino con la forma en que funcionan los métodos `fetch` y `fetchAll`. En resumen, `fetch` activa el puntero para traer los datos **fila por fila**, mientras que `fetchAll` **trae todos los datos de golpe y los mete en un array**. Dado que `count` no se puede aplicar sobre un dato que no sea *contable*, cuando usabas `fetch` te fallaba. [En esta respuesta se explica la diferencia entre `fetch` y `fetchAll`](https://es.stackoverflow.com/a/184343/29967), eso no tiene nada que ver con PHP 7. – A. Cedano Feb 01 '19 at 09:49
  • bueno si digo que me fallaba era porque en versiones anteriores utilizaba count para verificar si mi retorno contenia datos y no me ejecutaba error hasta que empece con php 7 – HRCody Feb 01 '19 at 17:30
  • En muchos aspectos PHP se hizo más estricto y ahora advierte o da error en código que antes dejaba que funcione silenciosamente aunque estuviera mal. Pero aquí el problema no es ni siquiera `count`, sino un error de comprensión sobre cómo funciona `fetch` y `fetchAll`. Si tú usas `fetch` y metes los datos en un array y luego haces `count($arrDatos)` va a funcionar, o si usas `fetch` y haces `count($respuesta)` también va a funcionar. Lo que pasa que si haces `count($respuesta["nombres"])` ya no estás contando en el array, sino en una clave del mismo que es `nombres`. – A. Cedano Feb 01 '19 at 17:42
  • tienes razon mi estimado, una respuesta como la tuya buscaba pero no la encontraba asi que opte por esta solucion, ahora te hago una consulta que pasa si utilizo esto fetch y if( count($respuesta) > 0){ return true; } es valido?? porque tengo entendido que al ejecutar una consulta retorna un array sea vacio o con datos, es que necesito hacer unas validaciones para no entrar en el bucle y generar retraso en la consulta – HRCody Feb 01 '19 at 21:02
  • PDO tiene un método [`rowCount()`](http://php.net/manual/es/pdostatement.rowcount.php), para contar la cantidad de filas, pero OJO: **no es seguro para consultas de tipo `SELECT`**. Entonces sólo quedan dos posibilidades en el caso de `fetch`: 1. Lanzar aparte una consulta `SELECT COUNT(*) FROM tabla` para saber si hay filas (esta es la forma más segura de saberlo, aunque supone una consulta adicional... si la tabla está bien indexada tiene poco coste en recursos); 2. a) Crear un array vacío antes del bucle, b)Llenar el array dentro de un bucle, c)Comprobar el array fuera del bucle ... – A. Cedano Feb 01 '19 at 21:16
  • ... cabe decir que **previo** a todo eso hay que verificar otras cosas: 1. fallos en los datos que usará la consulta (nulos, vacíos, etc por ejemplo vienen por POST, GET...); 2. fallos en la conexión (que no sea nula); 3. fallos en la preparación de la consulta (en caso de consultas preparadas); 4. fallos en la ejecución de la consulta (con `execute` o con `query` según el caso). – A. Cedano Feb 01 '19 at 21:17
  • si he leido del rowCoun() pero no funciona con todos los gestores de base de datos y eso es lo que quiero evitar necesito que mi aplicacion sea compatible con todas, y con respecto al SELECT COUNT(*) FROM tabla no me convence por lo que tendria que generar otra consulta. Con respecto a los fallos los tengo controlados solo quiero ver en el tema de la validacion si retorna vacios o con datos, por eso era ver si mi consulta tenia alguna factibilidad positiva para continuar con mis desarrollos – HRCody Feb 01 '19 at 21:51
  • `SELECT COUNT(*)` es siempre lo más seguro. Si no quieres eso, como te dije, puedes declarar un array vacío, luego meter los resultados en la rueda con `fetch` para llenar el array y al final comprobar el array. O, usar `fetchAll`, el cual no se recomienda cuando se esperan muchas filas. Y no creas que lanzar un `COUNT(*)` sea más costoso que usar `fetchAll` por ejemplo si la consulta devuelve varias decenas o cientos de miles de datos. – A. Cedano Feb 01 '19 at 21:54
  • Dado que veo que te interesan las buenas prácticas, te sugiero que leas la guía publicada en `phpdelusions` sobre PDO. Para el tema que nos ocupa aquí, puedes leer [la parte donde el autor trata el conteo de datos](https://phpdelusions.net/pdo#count). El [autor de `phpdelusions`](https://stackoverflow.com/users/285587/your-common-sense) es de los pocos que por ahora tienen [medalla de oro](https://stackoverflow.com/help/badges/4220/pdo) (desde 2014) en la etiqueta `pdo` de Stackoverflow en inglés. – A. Cedano Feb 01 '19 at 21:57
  • muchas gracias mi estimado por tu tiempo, leere esa guia antes de seguir continuando con mis desarrollos – HRCody Feb 01 '19 at 21:59

0 Answers0