Carbon 3 en Laravel 11: diffInHours devuelve decimales y no cuadra con el tipo int
Hola, bienvenido. En esta lección vamos a resolver el último error de la actualización: el de Carbon 3. En Carbon 3, diffInHours() y el resto de métodos diffIn* devuelven un float en vez de un int, así que un método tipado como int que devuelve su resultado lanza un TypeError en cuanto el archivo declara strict_types.
Es el error que tenemos pendiente desde la lección 5, y el más fácil de corregir: una línea. Pero antes de cambiarla vamos a ver bien qué ha cambiado, porque la solución que parece obvia no funciona con los valores negativos.
El TypeError de Sla::hoursLeft()
Es el único error que queda en los tests. Vamos a lanzar SlaTest, que es donde se ve más limpio:
Los 3 tests que llaman a hoursLeft() fallan, y son los mismos 3 de la lección 5. Los otros 6 tests de Feature que siguen en rojo, en TicketApiTest y ShowTicketTest, fallan por lo mismo, a través del accesor hours_left del modelo Ticket que vimos en la lección 6.
La causa está en 2 piezas que encajaban con Carbon 2 y ya no encajan con Carbon 3. La guía oficial lo resume en su apartado de Carbon 3 (se abre en una pestaña nueva): Laravel 11 admite Carbon 2 y Carbon 3, y en Carbon 3 los métodos diffIn* devuelven números decimales y pueden devolver valores negativos para indicar la dirección del tiempo. Composer instaló Carbon 3 en la lección 5 (nesbot/carbon (2.73.0 => 3.15.0) en la salida del update), porque nada en el proyecto exigía la versión 2.
La otra pieza es app/Support/Sla.php, que declara strict_types en su primera línea y tipa hoursLeft() como int. Con strict_types, PHP no convierte un float en int al devolverlo, ni siquiera cuando el valor no tiene decimales. Fíjate en los 3 tests que fallan: el primero espera 1 hora entre las 10:00 y las 11:30, que con Carbon 3 son 1.5, pero los otros 2 calculan diferencias exactas, de 3 horas hacia atrás y de 5 hacia delante, y fallan igual, porque -3.0 y 5.0 siguen siendo float. Sin strict_types, PHP habría convertido el 5.0 en 5 sin decir nada, y el 1.5 en 1 con un aviso de obsolescencia, y el cambio habría pasado desapercibido.
Larastan nos lo dijo desde la lección 5, sin ejecutar nada: Method App\Support\Sla::hoursLeft() should return int but returns float. Lo sabe porque Carbon 3 declara float como tipo de retorno de diffInHours().
- 02Carbon 2 frente a Carbon 3 en diffInHours
- 03Truncar como Carbon 2
- 04composer qa en verde