🎃 12 meses por 75 €

El plan anual a mitad de precio hasta el 31 de octubre.

Aprovechar la oferta

🎃 Halloween: 12 meses por 75 €

Plan anual a mitad de precio, para altas y renovaciones. Solo hasta el 31 de octubre.
Aprovechar la oferta
Saltar al contenido
Curso Actualizar un proyecto de Laravel 10 a Laravel 11
09/13 La actualización a Laravel 11 Carbon 3 en Laravel 11: diffInHours devuelve decimales y no cuadra con el tipo int
Tu lectura Quedan 8 min
Lección 9 de 13 · La actualización a Laravel 11

Carbon 3 en Laravel 11: diffInHours devuelve decimales y no cuadra con el tipo int

8 min de lectura Laravel 11

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:

Terminal
sail test tests/Unit/SlaTest.php
Salida
FAIL Tests\Unit\SlaTest ✓ the due date depends on the priority with dataset "high" 0.01s ✓ the due date depends on the priority with dataset "normal" ✓ the due date depends on the priority with dataset "low" ✓ the due date depends on the priority with dataset "unclassified" ⨯ hours left only count whole hours ⨯ hours left are negative once the due date has passed ✓ the sla is breached after the due date ⨯ it uses the current time when no date is given ──────────────────────────────────────────────────────────────────────────── FAILED Tests\Unit\SlaTest > hours left only count whole hours TypeError App\Support\Sla::hoursLeft(): Return value must be of type int, float returned at app/Support/Sla.php:22 18▕ } 19▕ 20▕ public function hoursLeft(CarbonInterface $dueAt): int 21▕ { ➜ 22▕ return $this->now()->diffInHours($dueAt, false); 23▕ } 24▕ 25▕ public function isBreached(CarbonInterface $dueAt): bool 26▕ { 1 app/Support/Sla.php:22 2 tests/Unit/SlaTest.php:25 ... Tests: 3 failed, 5 passed (6 assertions)

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().

Lo que queda de esta lección
  1. 02Carbon 2 frente a Carbon 3 en diffInHours
  2. 03Truncar como Carbon 2
  3. 04composer qa en verde
Sigue leyendo con tu suscripción El curso completo, con el certificado y el foro, está incluido en la suscripción. Ver los planes