Helpers

Helpers

Introduction

Laravel includes a variety of global “helper” PHP functions. Many of these functions are used by the framework itself; however, you are free to use them in your own applications if you find them convenient.

Laravel incluye una variedad de funciones helper globales. Muchas de estas funciones son usadas por el framework mismo; Sin embargo, puedes usarlas en tu aplicación como consideres.

Available Methods

Aquí puedes encontrar los metodos disponibles

Other Utilities

Benchmarking

A veces es posible que desees probar rápidamente el rendimiento de ciertas partes de tu aplicación. En esas ocasiones, puedes utilizar la clase de soporte Benchmark para medir la cantidad de milisegundos que tardan en completarse los callbacks dados:

<?php
 
use App\Models\User;
use Illuminate\Support\Benchmark;
 
Benchmark::dd(fn () => User::find(1)); // 0.1 ms
 
Benchmark::dd([
    'Scenario 1' => fn () => User::count(), // 0.5 ms
    'Scenario 2' => fn () => User::all()->count(), // 20.0 ms
]);

Por defecto, los callbacks dados se ejecutarán una vez (una iteración), y su duración se mostrará en el navegador / consola. Para invocar un callback más de una vez, puedes especificar el número de iteraciones que se debe invocar el callback como el segundo argumento al método. Al ejecutar un callback más de una vez, la clase Benchmark devolverá la cantidad media de milisegundos que tomó ejecutar el callback a través de todas las iteraciones:

Benchmark::dd(fn () => User::count(), iterations: 10); // 0.5 ms

A veces, es posible que desees medir el rendimiento de una callback mientras aún obtienes el valor devuelto por la callback. El método value devolverá una tupla que contiene el valor devuelto por la callback y la cantidad de milisegundos que tardó en ejecutarse la callback:

[$count, $duration] = Benchmark::value(fn () => User::count());

Dates

Laravel incluye Carbon, una poderosa biblioteca de manipulación de fechas y horas. Para crear una nueva instancia de Carbon, puedes invocar la función now. Esta función está disponible globalmente en tu aplicación Laravel:

$now = now();

O también puedes crear una nueva instancia de Carbon utilizando la clase Illuminate\Support\Carbon:

use Illuminate\Support\Carbon;
 
$now = Carbon::now();

Para una discusión exhaustiva sobre Carbon y sus características, consulta la documentación oficial de Carbon.

Deferred Functions

❗ Las funciones diferidas están actualmente en fase beta mientras recopilamos comentarios de la comunidad.

Mientras que los trabajos en cola de Laravel te permiten poner tareas en cola para procesamiento en segundo plano, a veces puedes tener tareas simples que te gustaría diferir sin configurar o mantener un proceso de cola de larga duración.

Las funciones diferidas te permiten posponer la ejecución de un closure hasta después de que la respuesta HTTP haya sido enviada al usuario, manteniendo tu aplicación rápida y receptiva. Para diferir la ejecución de un closure, simplemente pasa el closure a la función Illuminate\Support\defer:

use App\Services\Metrics;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use function Illuminate\Support\defer;
 
Route::post('/orders', function (Request $request) {
    // Create order...
 
    defer(fn () => Metrics::reportOrder($order));
 
    return $order;
});

Por defecto, las funciones diferidas solo se ejecutarán si la respuesta HTTP, el comando Artisan o el trabajo en cola desde el que se invoca Illuminate\Support\defer se completa con éxito. Esto significa que las funciones diferidas no se ejecutarán si una solicitud resulta en una respuesta HTTP 4xx o 5xx. Si deseas que una función diferida se ejecute siempre, puedes encadenar el método always a tu función diferida:

defer(fn () => Metrics::reportOrder($order))->always();

Cancelling Deferred Functions

Si necesitas cancelar una función diferida antes de que se ejecute, puedes usar el método forget para cancelar la función por su nombre. Para nombrar una función diferida, proporciona un segundo argumento a la función Illuminate\Support\defer:

defer(fn () => Metrics::report(), 'reportMetrics');
 
defer()->forget('reportMetrics');

Deferred Function Compatibility

Si actualizaste a Laravel 11.x desde una aplicación Laravel 10.x y el esqueleto de tu aplicación todavía contiene un archivo app/Http/Kernel.php, debes agregar el middleware InvokeDeferredCallbacks al inicio de la propiedad $middleware del kernel:

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\InvokeDeferredCallbacks::class, 
    \App\Http\Middleware\TrustProxies::class,
    // ...
];

Disabling Deferred Functions in Tests

Al escribir pruebas, puede ser útil desactivar las funciones diferidas. Puedes llamar a withoutDefer en tu prueba para indicar a Laravel que ejecute todas las funciones diferidas inmediatamente:

PestPHPUnit

test('without defer', function () {
    $this->withoutDefer();
 
    // ...
});

Si deseas desactivar las funciones diferidas para todas las pruebas dentro de un caso de prueba, puedes llamar al método withoutDefer desde el método setUp en tu clase base TestCase:

<?php
 
namespace Tests;
 
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 
abstract class TestCase extends BaseTestCase
{
    protected function setUp(): void
    {
        parent::setUp();
 
        $this->withoutDefer();
    }
}

Lottery

La clase de lotería de Laravel se puede usar para ejecutar callbacks basados en un conjunto de probabilidades dadas. Esto puede ser especialmente útil cuando solo deseas ejecutar código para un porcentaje de tus solicitudes entrantes:

use Illuminate\Support\Lottery;
 
Lottery::odds(1, 20)
    ->winner(fn () => $user->won())
    ->loser(fn () => $user->lost())
    ->choose();

Puedes combinar la clase de lotería de Laravel con otras características de Laravel. Por ejemplo, es posible que desees informar solo un pequeño porcentaje de las consultas lentas a tu manejador de excepciones. Y, dado que la clase de lotería es callable, podemos pasar una instancia de la clase a cualquier método que acepte callables:

use Carbon\CarbonInterval;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Lottery;
 
DB::whenQueryingForLongerThan(
    CarbonInterval::seconds(2),
    Lottery::odds(1, 100)->winner(fn () => report('Querying > 2 seconds.')),
);

Testing Lotteries

Laravel ofrece algunos métodos simples que te permiten probar fácilmente las invocaciones de lotería de tu aplicación:

// Lottery will always win...
Lottery::alwaysWin();
 
// Lottery will always lose...
Lottery::alwaysLose();
 
// Lottery will win then lose, and finally return to normal behavior...
Lottery::fix([true, false]);
 
// Lottery will return to normal behavior...
Lottery::determineResultsNormally();

Pipeline

La fachada Pipeline de Laravel proporciona una forma conveniente de “enviar” una entrada dada a través de una serie de clases invocables, funciones anónimas o llamados, dando a cada clase la oportunidad de inspeccionar o modificar la entrada e invocar el siguiente callable en el pipeline:

use Closure;
use App\Models\User;
use Illuminate\Support\Facades\Pipeline;
 
$user = Pipeline::send($user)
            ->through([
                function (User $user, Closure $next) {
                    // ...
 
                    return $next($user);
                },
                function (User $user, Closure $next) {
                    // ...
 
                    return $next($user);
                },
            ])
            ->then(fn (User $user) => $user);

Como puedes ver, a cada clase invocable o función anónima en la tubería se le proporcionan la entrada y una función anónima $next. Invocar la función anónima $next invocará el siguiente callable en la tubería. Como habrás notado, esto es muy similar a middleware.

Cuando el último callable en el pipeline invoca la función anónima $next, el callable proporcionado al método then será invocado. Típicamente, este callable simplemente devolverá la entrada dada.

Por supuesto, como se discutió anteriormente, no estás limitado a proporcionar funciones anónimas a tu pipeline. También puedes proporcionar clases invocables. Si se proporciona un nombre de clase, la clase se instanciará a través del contenedor de servicios de Laravel, lo que permite que las dependencias se inyecten en la clase invocable:

$user = Pipeline::send($user)
            ->through([
                GenerateProfilePhoto::class,
                ActivateSubscription::class,
                SendWelcomeEmail::class,
            ])
            ->then(fn (User $user) => $user);

Sleep

La clase Sleep de Laravel es un contenedor ligero alrededor de las funciones sleep y usleep nativas de PHP, ofreciendo una mayor facilidad de prueba mientras expone una API amigable para desarrolladores para trabajar con tiempo:

use Illuminate\Support\Sleep;
 
$waiting = true;
 
while ($waiting) {
    Sleep::for(1)->second();
 
    $waiting = /* ... */;
}

La clase Sleep ofrece una variedad de métodos que te permiten trabajar con diferentes unidades de tiempo:

// Return a value after sleeping...
$result = Sleep::for(1)->second()->then(fn () => 1 + 1);
 
// Sleep while a given value is true...
Sleep::for(1)->second()->while(fn () => shouldKeepSleeping());
 
// Pause execution for 90 seconds...
Sleep::for(1.5)->minutes();
 
// Pause execution for 2 seconds...
Sleep::for(2)->seconds();
 
// Pause execution for 500 milliseconds...
Sleep::for(500)->milliseconds();
 
// Pause execution for 5,000 microseconds...
Sleep::for(5000)->microseconds();
 
// Pause execution until a given time...
Sleep::until(now()->addMinute());
 
// Alias of PHP's native "sleep" function...
Sleep::sleep(2);
 
// Alias of PHP's native "usleep" function...
Sleep::usleep(5000);

Para combinar unidades de tiempo de manera sencilla, puedes usar el método and:

Sleep::for(1)->second()->and(10)->milliseconds();

Testing Sleep

Al probar código que utiliza la clase Sleep o las funciones de suspensión nativas de PHP, tu prueba pausará la ejecución. Como puedes imaginar, esto hace que tu suite de pruebas sea significativamente más lenta. Por ejemplo, imagina que estás probando el siguiente código:

$waiting = /* ... */;
 
$seconds = 1;
 
while ($waiting) {
    Sleep::for($seconds++)->seconds();
 
    $waiting = /* ... */;
}

Típicamente, probar este código llevaría al menos un segundo. Afortunadamente, la clase Sleep nos permite “simular” el sueño para que nuestra suite de pruebas se mantenga rápida:

it('waits until ready', function () {
    Sleep::fake();
 
    // ...
});

Al simular la clase Sleep, se evita la pausa de ejecución real, lo que conduce a una prueba sustancialmente más rápida.

Una vez que la clase Sleep ha sido simulada, es posible hacer afirmaciones contra los “sueños” esperados que deberían haber ocurrido. Para ilustrar esto, imaginemos que estamos probando un código que pausa la ejecución tres veces, con cada pausa aumentando en un segundo. Usando el método assertSequence, podemos afirmar que nuestro código “durmió” por la cantidad de tiempo adecuada mientras mantenemos nuestra prueba rápida:

it('checks if ready three times', function () {
    Sleep::fake();
 
    // ...
 
    Sleep::assertSequence([
        Sleep::for(1)->second(),
        Sleep::for(2)->seconds(),
        Sleep::for(3)->seconds(),
    ]);
}

Por supuesto, la clase Sleep ofrece una variedad de otras afirmaciones que puedes usar al realizar pruebas:

use Carbon\CarbonInterval as Duration;
use Illuminate\Support\Sleep;
 
// Assert that sleep was called 3 times...
Sleep::assertSleptTimes(3);
 
// Assert against the duration of sleep...
Sleep::assertSlept(function (Duration $duration): bool {
    return /* ... */;
}, times: 1);
 
// Assert that the Sleep class was never invoked...
Sleep::assertNeverSlept();
 
// Assert that, even if Sleep was called, no execution paused occurred...
Sleep::assertInsomniac();

A veces puede ser útil realizar una acción siempre que ocurra un sueño simulado en el código de tu aplicación. Para lograr esto, puedes proporcionar un callback al método whenFakingSleep. En el siguiente ejemplo, usamos los ayudantes de manipulación de tiempo de Laravel para avanzar el tiempo instantáneamente por la duración de cada sueño:

use Carbon\CarbonInterval as Duration;
 
$this->freezeTime();
 
Sleep::fake();
 
Sleep::whenFakingSleep(function (Duration $duration) {
    // Progress time when faking sleep...
    $this->travel($duration->totalMilliseconds)->milliseconds();
});

A medida que el tiempo de progreso es un requisito común, el método fake acepta un argumento syncWithCarbon para mantener Carbon en sincronía cuando se hace una pausa dentro de una prueba:

Sleep::fake(syncWithCarbon: true);
 
$start = now();
 
Sleep::for(1)->second();
 
$start->diffForHumans(); // 1 second ago

Laravel utiliza la clase Sleep internamente siempre que pausa la ejecución. Por ejemplo, el helper retry utiliza la clase Sleep al hacer una pausa, lo que permite una mejor capacidad de prueba al usar ese helper.