Entendiendo el config de Laravel parte 1: app.php

Publicado por Andrés López

Entendiendo el config de Laravel parte 1: app.php

Cuando inicias una nueva aplicación de Laravel bastante sencilla (simplificada cada vez más con cada nueva versión). Mucha de la magia con la que cuenta Laravel se encuentra en el código fuente: enrutamiento, bases de datos, encriptación, patrones de diseño, etc. Y sabemos que, cuando hablamos de código en muchas ocasiones es necesario personalizar para ajustar las herramientas conforme a los requerimientos de tu aplicación.

Laravel ofrece 2 maneras de hacerlo:

  1. Mediante el service container (en un futuro haré un post acerca de esto)
  2. Mediante archivos de configuración globales

En este artículo veremos a detalle el archivo de configuración app.php:

return [
    'name' => env('APP_NAME', 'Laravel'),
    'env' => env('APP_ENV', 'production'),
    'debug' => (bool) env('APP_DEBUG', false),
    'url' => env('APP_URL', 'http://localhost'),
    'timezone' => 'UTC',
    'locale' => env('APP_LOCALE', 'en'),
    'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
    'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
    'cipher' => 'AES-256-CBC',
    'key' => env('APP_KEY'),
    'previous_keys' => [
        ...array_filter(
            explode(',', env('APP_PREVIOUS_KEYS', ''))
        ),
    ],
    'maintenance' => [
        'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
        'store' => env('APP_MAINTENANCE_STORE', 'database'),
    ],
];

name

'name' => env('APP_NAME', 'Laravel'),

Este es el nombre de tu aplicación, generalmente sirve como identificador y no tiene más uso, te muestro algunos ejemplos de donde se suele usar:

HTML

Recomiendo agregarlo a tu etiqueta title, muchos devs (incluido yo) suelen crear sus layouts de esta manera:

// components/layout/app.blade.php
<!DOCTYPE html>
<html>
    <head>
        <title>
            {{ config('app.name') }} | {{ $title  ?? 'Laravel' }}
    </head>
</html>

Correos electrónicos

Cuando solemos enviar correos electrónicos usamos el nombre de la aplicación como el nombre del remitente del correo, esto nos facilita identificar para filtrarlos o dar más confianza a los visitantes de nuestra app. En teoría Laravel ya hace eso por nosotros, pero siempre podemos hacerlo manualmente, la referencia de la documentación la puedes encontrar aquí:

use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;

/**
 * Get the message envelope.
 */
public function envelope(): Envelope
{
    return new Envelope(
        from: new Address('contacto@andreslopez.com.mx', config('app.name')),
        subject: 'Order Shipped',
    );
}

env

'env' => env('APP_ENV', 'production'),

El entorno (environment) es útil para saber el contexto de tu aplicación, a veces queremos que solo los correos se manden a la dirección adecuada cuando es producción y cuando es local o pruebas enviarlo a algún correo de desarrollo, para esto sirve esta configuración, típicamente se suele usar:

  • local
  • production
  • staging

y ya en código puedes realizar validaciones como estás:

$isProduction = config('app.env') == 'production';

if($isProduction) {
    // do something
}

Claro que si quieres una manera más elegante puedes usar las funciones de la clase App de Laravel, referencia de documentación aquí:

use Illuminate\Support\Facades\App;
 
$environment = App::environment();

if (App::environment('local')) {
    // The environment is local
}
 
if (App::environment(['local', 'staging'])) {
    // The environment is either local OR staging...
}

if(App::isLocal()) {
    // The environment is local
}

if(App::isProduction()) {
    // The environment is production
}

O mediante el helper app:

app()->environment();

app()->environment('local');

app()->environment(['local', 'staging']);

app()->isLocal();

app()->isProduction();

Un buen truco para usar esto, es si estamos enviando correos y no queremos que se envien al destinatario original podemos colocar este código en cualquier service provider:

use Illuminate\Support\Facades\Mail;
 
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot(): void
{
    if (! $this->app->isProduction()) {
        Mail::alwaysTo('contacto@redplug.com.mx');
    }
}

debug

'debug' => (bool) env('APP_DEBUG', false),

Esta configuración define cuanta información se le muestra a los usuarios acerca de los errores que ocurren en tu aplicación, lo ideal es que para entornos locales o pruebas este contenga el valor true y para entornos de producción se encuentre en false.

Error 500 con debugError 500 con debug

Error 500 sin debugError 500 sin debug

Este valor también es tomado por paquetes de debug famosos como:

url

'url' => env('APP_URL', 'http://localhost'),

Este valor pareciera no importante, porque cuando estas navegando por tu aplicación, te das cuenta que todo funciona bien aunque este valor no sea el adecuado, pero hay truco, y para ello necesitamos entender como funciona la generación de rutas en Laravel. Todos conocemos el helper route, muy útil, todos lo queremos, pero que es lo que hace,

Bueno, en la mayoría de los casos genera una url absoluta con el nombre de la ruta que le pases por ejemplo:

route('brands.index'); // https://myapp.com/brands

Si es una petición active obtendrá el dominio desde donde se hizo la petición, que es la mayoría de los casos:

use Illuminate\Http\Request;

public function index(Request $request)
{
    $request->getHost(); // myapp.com
}

Sin embargo, cuando estamos trabajando en comandos o procesos de queues, este valor no esta disponible, es decir, no hay una petición como tal, y aquí es donde Laravel recurre al uso de tu configuración app.url

public function handle(): int
{
    $host = config('app.url'); // myapp.com
}

**Este es un ejemplo burdo, la implementación interna de Laravel es mucho más avanzada e involucra varias clases y uso de código de PHP $_SERVER si tienes curiosidad aquí esta el código original

timezone

'timezone' => 'UTC',

Este es la zona horaria en la que necesitas que tu aplicación funcione, por defecto este valor es UTC, que se podría decir que es la zona horaria estandar universal, es decir a partir de esta hora, las demás zonas horarias son calculadas.

Este valor es útil al trabajar con las herramientas de fechas en Laravel como:

  • Carbon
  • El schedule de comandos
  • Las colas de trabajos (queues)
  • Timestamps de tus modelos

Aunque la lógica nos dice que lo obvio sería cambiar este valor por el adecuado a tu ubicación, en mi caso America/Mexico_City, la realidad es que no es la mejor práctica, sobre todo si tienes visitantes/usuarios de tu aplicación con distintas ubicaciones alrededor del mundo. Cada uno de ellos tendrá su propia zona horaria y distinta a la que configures, por eso, es mejor quedarte con UTC y de ahí hacer las operaciones adecuadas:

use Illuminate\Http\Request;
use App\Models\User;

public function index(Request $request)
{
    $user = User::first();

    $localDate = $user->created_at
                        ->format('Y-m-d H:i:s'); // "2025-03-12 01:35:56"

    $clientDate = $user->created_at
                        ->setTimezone('America/Mexico_City')
                        ->format('Y-m-d H:i:s'); // "2025-03-11 19:35:56"

    return response()->json([
        'message' => "The user was created at {$clientDate}"
    ]);
}

locale

'locale' => env('APP_LOCALE', 'en'),

Este valor es de uso exclusivo de Laravel, se utiliza para manejar la configuración global y ajustar las traducciones de tu aplicación, puedes cambiar este valor en cualquier parte de tu aplicación solo tienes que conocer los métodos adecuados:

app()->getLocale(); // 'en'

app()->getLocale(); // 'en'

app()->isLocale('en'); // true

app()->setLocale('es'); // configura a español

además es útil para configurar tu HTML para que los crawlers sepan en que idioma esta tu aplicación:

// components/layout/app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    ...
</html>

fallback_locale

'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),

En caso de que tu aplicación no cuente con una traducción adecuada para el locale, intentará volver a buscar una traducción pero esta vez de esa configuración.

faker_locale

'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),

Este valor mayormente se utliza para sembrar base de datos con valores falsos, se utiliza por faker el cuál es el generador de esta información:

// en
fake()->name(); // 'Mr. Dejuan Reynolds PhD'

// es
fake()->name(); // 'Jessyca Parisian'

cipher

'cipher' => 'AES-256-CBC',

Este el el algoritmo que tu aplicación utilizará para cifrar datos, habitualmente con el uso de la clase Illuminate\Support\Facades\Crypt, por defecto utlizará el algoritmo AES-256-CBC el cuál es el más seguro a la fecha, sin embargo puedes cambiarlo en cualquier momento, solo toma en cuenta que si tienes valores cifrados en base de datos estos dejaran de funcionar, los algoritmos de cifrado disponibles son:

  • aes-128-cbc
  • aes-256-cbc
  • aes-128-gcm
  • aes-256-gcm

key

'key' => env('APP_KEY'),

Esta configuración esta ligada a la anterior, es decir la llave/contraseña con la que se generarán los cifrados mediante el algoritmo seleccionado, además Laravel también utlizá esta configuración para generar tokens de reinicio de contraseña y urls cifradas (signed).

habitualmente para facilitar y asegurar esta llave la puedes generar mediante el siguiente comando:

php artisan key:generate

Toma en cuenta que cambiar esta llave hará obsoletos los registros que hayas generado con la llave anterior.

previous_keys

'previous_keys' => [
    ...array_filter(
        explode(',', env('APP_PREVIOUS_KEYS', ''))
    ),
],

En caso de que quieras cambiar la llave de encriptación, ya se por prevención o porque directamente se filtro al público, puedes hacer una migración paso a paso, aqui puedes colocar tus llaves previas separadas por comas, entonces Laravel intentará usarlas hasta encontrar la adecuada, aquí lo ideal es solicitar a tus usuarios que cambien sus contraseñas y otros datos cifrados para que sean encriptados con la nueva llave.

Ejemplo de como Laravel prueba los cifrados

use lluminate\Encryption\Encrypter;
use Exception;

$key = config('app.key');
$previousKeys = config('app.previous_keys');

$keys = [
    $key,
    ...$previousKeys
];

foreach($keys as $key) {
    try {
        $value = new Encrypter()->decryptString($value);

        return $value;
    }
    catch(Exception $e) {
        continue;
    }
}

throw new Exception('Value can not be decoded');

**Este es un ejemplo burdo, la implementación interna de Laravel es mucho más avanzada, si tienes curiosidad aquí esta el código original

maintenance

'maintenance' => [
    'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
    'store' => env('APP_MAINTENANCE_STORE', 'database'),
],

Está es la configuración de modo mantenimiento, para colocar tu aplicación en modo mantenimiento puedes correr este comando:

php artisan down

Y para volver a colocarlo en línea puedes correr este comando:

php artisan up

Para mayor información y otras opciones lee la documentación de Laravel

Cuando corres este comando se colocará un archivo maintenance.php en storage/framework, este se encargará de manejar las respuestas 503 y notiifcar al usuario sobre el modo mantenimiento.

En caso de que tengas múltiple servidores corriendo tendrás que correr este comando en cada uno de ellos, aunque si cambias el driver a cache, esto podrá compartirse y slo habrá necesidad de correrlo en un solo servidor.

Hay otras opciones que se pueden personalizar del app.php que en previas versiones si que aparecian pero ahora se guardan de manera interna con posiblidad a sobreescribirse si se colocan en tu app.php, algunas de ellas que puedes cambiar:

  • frontend_url
  • asset_url
  • providers
  • aliases

Futuramente hablaré de estos puntos, por el momento es todo lo que tengo que compartir, espero hayas podido aprender algo como yo mientras investigaba el framework internamente.

Hasta luego :)

Andrés López

Andrés López

Gran fan de Laravel, entusiasta de Vue y escritor de cualquier cosa que suene interesante