Resultado del conteo de colecciones de Laravel

4 minutos de lectura

Avatar de usuario de Klaaz
Klaaz

En un modelo de usuario (tabla con 4 registros), cuando hago:

$coll = User::all();
echo $coll->count();

Obtengo la cantidad de registros encontrados (4).

Pero cuando lo hago:

$coll = User::find(2);
echo $coll->count();

No obtengo 1 (como esperaba) sino la cantidad de atributos en la colección resultante (23 en este caso).

¿Cómo puedo verificar si se encuentran más de un registro?


ACTUALIZAR:

OK, gracias a todos ustedes, ahora veo la diferencia en el resultado entre la colección y el modelo.

Pero mi verdadero problema es que tengo que detectar si estoy teniendo como resultado un modelo o una colección. Dependiendo de este resultado, realizo algunos cambios en el contenido de los campos en los elementos (con mapa ()) o modelo. ¿Cómo puedo detectar si el resultado es un modelo o una colección?

if(count($coll) > 1)

Funciona, pero ¿es este el enfoque correcto?

  • no creo ::find() devuelve una colección, en realidad.

    – No entrar en pánico

    11 mayo 2015 a las 22:56

  • @Don’tPanic En realidad, puede, si le pasa una serie de identificaciones. Pero en este caso si la entrada con un id = 2 se encuentra, devolverá un modelo elocuente.

    – Bogdán

    11 mayo 2015 a las 22:57


  • @Bogdan, Buen punto. Supongo que debería haber dicho más específicamente ::find(2) no devuelve una colección.

    – No entrar en pánico

    11 mayo 2015 a las 22:59

Avatar de usuario de Bogdan
Bogdán

Esto es lo que está pasando con el código que tienes allí:

1. al llamar User::all() obtendrás un Illuminate\Database\Eloquent\Collection en el que puedes llamar count que cuenta los elementos de la colección así:

public function count()
{
    return count($this->items);
}

Esto devolverá la cantidad de elementos en la colección como esperaba correctamente.

2. al llamar User::find(2) sin embargo, Eloquent Query Builder no devolverá un Collectionporque comprobará a ver cuantos resultados hay, y ya que pasaste una identificación obtendrás como máximo un resultado, por lo que devolverá un Modelo Elocuente en su lugar. El modelo no tiene count() método, por lo que cuando intenta llamar $coll->count(); irá a la magia __call método que la clase ha implementado que se ve así:

public function __call($method, $parameters)
{
    if (in_array($method, array('increment', 'decrement')))
    {
        return call_user_func_array(array($this, $method), $parameters);
    }

    $query = $this->newQuery();

    return call_user_func_array(array($query, $method), $parameters);
}

Como puede ver, el método intenta ver si debe llamar a un par de métodos codificados (increment y decrement), que por supuesto no coinciden en este caso porque $method = 'count'por lo que continúa creando una nueva consulta en la que llamará al count método.

La conclusión es que tanto la primera como la segunda muestra de código terminan haciendo lo mismo: contando todas las entradas en el users mesa.

Y dado que, como señalé anteriormente, una identificación no puede coincidir con más de una fila (dado que las identificaciones son únicas), el respuesta a tu pregunta es que no hay necesidad ni forma de contar los resultados de find(2)ya que solo puede ser 0 (si null se devuelve) o 1 (si se Model es regresado).


ACTUALIZAR

En primer lugar, para futuras referencias, puede utilizar PHP get_class para determinar el nombre de clase de un objeto o get_parent_class para determinar la clase que se está extendiendo. En tu caso la segunda función get_parent_class podría ser útil para determinar la clase del modelo ya que el User class extiende una clase de modelo abstracto de Laravel.

Así que si tienes un modelo get_class($coll) reportará Userpero get_parent_class($coll) reportará \Illuminate\Database\Eloquent\Model.

Ahora para verificar si el resultado es una Colección o un Modelo que puede usar instanceof:

instanceof se utiliza para determinar si una variable de PHP es un objeto instanciado de una determinada clase

Sus cheques deberían verse así:

// Check if it's a Collection
if ($coll instanceof \Illuminate\Support\Collection)

// Check if it's a Model
if ($coll instanceof \Illuminate\Database\Eloquent\Model)

También es posible que desee comprobar si el resultado es nulldesde find regresará null si no se encuentra ninguna entrada con el ID dado:

if (is_null($coll))

  • ¡Por supuesto! No hice la diferencia entre una colección y un modelo. ¡Gracias por aclararme esto! Consulte la pregunta actualizada para conocer la solución real que estoy buscando.

    – Klaaz

    12 de mayo de 2015 a las 7:49


  • @Klaaz Actualicé la respuesta con la solución a su pregunta actualizada.

    – Bogdán

    12 de mayo de 2015 a las 9:12


  • ¡Excelente! Esto deja las cosas muy claras, gracias por explicar 🙂

    – Klaaz

    12 mayo 2015 a las 10:36

  • El Collection tiene su propio método $collection->count()

    – Código para la vida

    28/09/2022 a las 15:41

Parece que estás esperando la método find() comportarse de manera diferente. Desde el documentos

Find a model by its primary key.

  • Laravel rompió muchos enlaces de documentación durante un rediseño en algún momento, por lo que estos enlaces API antiguos están muertos.

    – kjones

    21 de julio de 2021 a las 20:10

Si su problema es comprobando si es de colección. ¿Por qué no lo compruebas si es de Illuminate\Database\Eloquent\Collection?

if (get_class($coll) == 'Illuminate\Database\Eloquent\Collection') {
   your code...
}

o

if ($coll instanceof \Illuminate\Database\Eloquent\Collection) {
   your code...
}

¿Ha sido útil esta solución?