Registro (Logging) – Documentación de Laravel 6

Introducción

Para ayudarte a aprender más acerca de lo que está sucediendo dentro de tu aplicación, Laravel proporciona un robusto servicio de registro que te permite registrar mensajes en archivos, en el registro de errores del sistema e incluso en Slack para notificar a todo tu equipo.

De forma interna, Laravel usa la biblioteca Monolog, que proporciona soporte para una variedad de poderosos manejadores de registros. Laravel hace que sea pan comido configurar dichos manejadores, permitiéndote mezclarlos y juntarlos para personalizar el manejo de registros en tu aplicación.

Configuración

Toda la configuración para el sistema de registros de tu aplicación se encuentra en el archivo de configuración config/logging.php. Este archivo te permite configurar los canales de registros de tu aplicación, así que asegúrate de revisar cada uno de los canales disponibles y sus opciones. Revisaremos algunas opciones comunes a continuación.

Por defecto, Laravel usará el canal stack al registrar mensajes. El canal stack es usado para agregar múltiples canales de registros en un solo canal. Para más información sobre la construcción de stacks, revisa la documentación debajo.

Configurando el nombre del canal

Por defecto, Monolog es instanciado con un «nombre de canal» que concuerda con el entorno actual, como production o local. Para cambiar este valor, agrega una opción name a la configuración de tu canal:

'stack' => [
    'driver' => 'stack',
    'name' => 'channel-name',
    'channels' => ['single', 'slack'],
],

Drivers de canales disponibles

Nombre Descripción
stack Wrapper para facilitar la creación de canales «multi-canales»
single Canal de registro de un sólo archivo o ubicación (StreamHandler)
daily Driver de Monolog basado en RotatingFileHandler que rota diariamente
slack Driver de Monolog basado en SlackWebhookHandler
papertrail Driver de Monolog basado en SyslogUdpHandler
syslog Driver de Monolog basado en SyslogHandler
errorlog Driver de Monolog basado en ErrorLogHandler
monolog Driver factory de Monolog que puede usar cualquier manejador de Monolog soportado
custom Driver que llama a un factory especificado para crear un canal

Consulta la documentación sobre personalización avanzada de canales para aprender más sobre monolog y drivers personalizados.

Configuración de los canales single y daily

Los canales single y daily tienen tres opciones de configuración opcionales: bubble, permission y locking.

Nombre Descripción Default
bubble Indica si los mensajes deberían llegar a otros canales después de ser manejados true
permission Los permisos del archivo de registro 0644
locking Intenta bloquear el archivo de registro antes de escribirlo false

Configurando el canal de papertrail

El canal papertrail requiere de las opciones de configuración url y port. Puedes obtener estos valores desde Papertrail.

Configurando el canal de Slack

El canal slack requiere una opción de configuración url. Esta URL debe coincidir con una URL de un webhook entrante que hayas configurado para tu equipo de Slack. Por defecto, Slack sólo recibirá registros en el nivel critical y superior; sin embargo, puedes ajustar esto en tu archivo de configuración logging.

Ver post

Manejo de Errores – Documentación de Laravel 6

Introducción

Cuando comienzas un nuevo proyecto de Laravel, el manejo de excepciones y errores ya está configurado para ti. La clase App\Exceptions\Handler es donde todas las excepciones disparadas por tu aplicación son registradas y después renderizadas de vuelta al usuario. Revisaremos más profundamente dentro de esta clase a través de esta documentación.

Configuración

La opción debug en tu archivo de configuración config/app.php determina cuanta información sobre un error se muestra realmente al usuario. Por defecto, esta opción es establecida para respetar el valor de la variable de entorno APP_DEBUG, la cual es almacenada en tu archivo .env.

Para desarrollo local, deberías establecer la variable de entorno APP_DEBUG a true. En tu entorno de producción, este valor debería estar siempre false. Si el valor es establecido a true en producción, te arriesgas a exponer valores de configuración sensibles a los usuarios finales de tu aplicación.

Manejador de excepciones

Ver post

Validación – Documentación de Laravel 6

Introducción

Laravel proporciona varios enfoques diferentes para validar los datos entrantes de tu aplicación. De forma predeterminada, la clase base del controlador de Laravel usa el trait ValidatesRequests el cual proporciona un método conveniente para validar las solicitudes HTTP entrantes con una variedad de poderosas reglas de validación.

Inicio rápido de validación

Para aprender sobre las poderosas características de validación de Laravel, vamos a observar un ejemplo completo validando un formulario y mostrando los mensajes de error devueltos al usuario.

Ver post

Sesión HTTP – Documentación de Laravel 6

Introducción

Ya que las aplicaciones manejadas por HTTP son sin estado, las sesiones proporcionan una forma de almacenar información sobre el usuario a través de múltiples solicitudes. Laravel viene con una variedad de backends de sesión que son accedidos a través de una expresiva API unificada. El soporte para los backends populares tales como Memcached, Redis y bases de datos es incluido de forma predeterminada.

Ver post

Generación de URLs – Documentación de Laravel 6

Introducción

Laravel proporciona varios helpers para asistirte en la generación de URLs para tu aplicación. Éstos son útiles principalmente al momento de construir enlaces en tus plantillas y respuestas de API, o al momento de generar respuestas redireccionadas a otra parte de tu aplicación.

Fundamentos

Generando URLs básicas

El helper url puede ser usado para generar URLs arbitrarias en tu aplicación. La URL generada utilizará automáticamente el esquema (HTTP o HTTPS) y el host de la solicitud actual:

$post = App\Post::find(1);

echo url("/posts/{$post->id}");

// http://example.com/posts/1

Ver post

Vistas – Documentación de Laravel 6

Creando vistas

Para buscar más información sobre ¿Cómo escribir plantillas de Blade? Revisa la documentación de Blade completa para comenzar.

Las vistas contienen el HTML servido por tu aplicación y separan la lógica de tu controlador/aplicación de la lógica de presentación. Las vistas son almacenadas en el directorio resources/views. Una vista sencilla podría lucir de esta forma:

<!-- View stored in resources/views/greeting.blade.php -->

<html>
    <body>
        <h1>Hello, {{ $name }}</h1>
    </body>
</html>

Ya que esta vista es almacenada en resources/views/greeting.blade.php, podemos devolverla usando el helper global view, de la siguiente forma:

Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});

Como puedes ver, el primer argumento pasado al helper view corresponde al nombre del archivo de la vista en el directorio resources/views. El segundo argumento es un arreglo de datos que debería estar disponible para la vista. En este caso, estamos pasando la variable name, la cual es mostrada en la vista usando la sintaxis de Blade.

Las vistas también pueden estar anidadas dentro de sub-directorios del directorio resources/views. La notación de «punto» puede ser usada para referenciar vistas anidadas. Por ejemplo, si tu vista está almacenada en resources/views/admin/profile.blade.php, puedes hacer referencia a ella de la siguiente forma:

return view('admin.profile', $data);

Los nombres de directorio de vista no deberían contener el carácter ..

Determinando si una vista existe

Si necesitas determinar si una vista existe, puedes usar la clase facade View. El método exists devolverá true si la vista existe:

use Illuminate\Support\Facades\View;

if (View::exists('emails.customer')) {
    //
}

Creando la primera vista disponible

Usando el método first, puedes crear la primera vista que existe en un arreglo de vistas dado. Esto es útil si tu aplicación o paquete permite que las vistas sean personalizadas o sobrescritas:

return view()->first(['custom.admin', 'admin'], $data);

También puedes ejecutar este método por medio de la clase facade View:

use Illuminate\Support\Facades\View;

return View::first(['custom.admin', 'admin'], $data);

Pasando datos a las vistas

Como viste en los ejemplos previos, puedes pasar un arreglo de datos a las vistas:

return view('greetings', ['name' => 'Victoria']);

Al momento de pasar información de esta manera, los datos deberían ser un arreglo con pares clave / valor. Dentro de tu vista, entonces puedes acceder a cada valor usando su clave correspondiente, tal como <?php echo $key; ?>. Como una alternativa a pasar un arreglo completo de datos a la función helper view, puedes usar el método with para agregar partes individuales de datos a la vista:

return view('greeting')->with('name', 'Victoria');

Compartiendo datos con todas las vistas

Ocasionalmente, puedes necesitar compartir una parte de los datos con todas las vistas que son renderizadas por tu aplicación. Puedes hacer eso usando el método share de la clase facade View. Típicamente, deberías colocar las ejecuciones a share dentro del método boot de un proveedor de servicio. Eres libre de agregarlos al AppServiceProvider o generar un proveedor de servicio diferente para alojarlos:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;

class AppServiceProvider extends ServiceProvider
{
    /**
    * Register any application services.
    *
    * @return void
    */
    public function register()
    {
        //
    }

    /**
    * Bootstrap any application services.
    *
    * @return void
    */
    public function boot()
    {
        View::share('key', 'value');
    }
}

View Composers

Los view composers son funciones de retorno (callbacks) o métodos de clase que son ejecutados cuando una vista es renderizada. Si tienes datos que quieres que estén enlazados a una vista cada vez que la vista es renderizada, un view composer puede ayudarte a organizar esa lógica dentro de una sola ubicación.

Para este ejemplo, vamos a registrar los View Composers dentro de un proveedor de servicio. Usaremos la clase facade View para acceder a la implementación de la interfaz Illuminate\Contracts\View\Factory subyacente. Recuerda, Laravel no incluye un directorio predeterminado para los View Composers. Eres libre de organizarlos del modo que desees. Por ejemplo, podrías crear un directorio app/Http/View/Composers:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
    /**
    * Register any application services.
    *
    * @return void
    */
    public function register()
    {
        //
    }

    /**
    * Bootstrap any application services.
    *
    * @return void
    */
    public function boot()
    {
        // Using class based composers...
        View::composer(
            'profile', 'App\Http\View\Composers\ProfileComposer'
        );

        // Using Closure based composers...
        View::composer('dashboard', function ($view) {
            //
        });
    }
}

Recuerda, si creas un nuevo proveedor de servicio para contener tus registros de View Composers, necesitarás agregar el proveedor de servicio al arreglo providers en el archivo de configuración config/app.php.

Ahora que hemos registrado el composer, el método ProfileComposer@compose será ejecutado cada vez que la vista profile esté siendo renderizada. Así que, vamos a definir la clase composer:

<?php

namespace App\Http\View\Composers;

use App\Repositories\UserRepository;
use Illuminate\View\View;

class ProfileComposer
{
    /**
    * The user repository implementation.
    *
    * @var UserRepository
    */
    protected $users;

    /**
    * Create a new profile composer.
    *
    * @param  UserRepository  $users
    * @return void
    */
    public function __construct(UserRepository $users)
    {
        // Dependencies automatically resolved by service container...
        $this->users = $users;
    }

    /**
    * Bind data to the view.
    *
    * @param  View  $view
    * @return void
    */
    public function compose(View $view)
    {
        $view->with('count', $this->users->count());
    }
}

Justo antes de que la vista sea renderizada, el método compose del composer es ejecutado con la instancia Illuminate\View\View. Puedes usar el método with para enlazar datos a la vista.

Todos los View Composers son resueltos por medio del contenedor de servicio, de modo que puedas colocar la referencia a cualquier dependencia que necesites dentro del constructor de un composer.

Adjuntando un composer a múltiples vistas

Puedes adjuntar un View Composer a múltiples vistas de una vez al pasar un arreglo de vistas como primer argumento del método composer:

View::composer(
    ['profile', 'dashboard'],
    'App\Http\View\Composers\MyViewComposer'
);

El método composer también acepta el carácter * como un comodín, permitiendo que adjuntes un composer a todas las vistas:

View::composer('*', function ($view) {
    //
});

View Creators

Los View Creators (creadores de vistas) son muy similares a los View Composers; sin embargo, son ejecutados inmediatamente después de que la vista sea instanciada en lugar de esperar hasta que la vista sea renderizada. Para registrar un View Creator, usa el método creator:

View::creator('profile', 'App\Http\View\Creators\ProfileCreator');

Respuestas HTTP – Documentación de Laravel 6

Creando respuestas

Cadenas y arreglos

Todas las rutas y controladores deberían devolver una respuesta para ser enviada de regreso al navegador del usuario. Laravel proporciona diferentes formas de devolver respuestas. La respuesta más básica es devolver una cadena desde una ruta o controlador. El framework convertirá la cadena en una respuesta HTTP completa:

Route::get('/', function () {
    return 'Hello World';
});

Además de devolver cadenas desde tus rutas y controladores, también puedes devolver arreglos. El framework convertirá automáticamente el arreglo en una respuesta JSON:

Route::get('/', function () {
    return [1, 2, 3];
});

¿Sabías que también puedes devolver colecciones de Eloquent desde tus rutas o controladores? Estas serán convertidas automáticamente a JSON. ¡Inténtalo!

Objetos de respuesta

Típicamente, no sólo estarás devolviendo cadenas básicas o arreglos desde tus acciones de ruta. Además, estarás devolviendo instancias Illuminate\Http\Response completas o vistas.

Devolver una instancia Response completa te permite personalizar el código de estado y los encabezados HTTP de la respuesta. Una instancia Response hereda desde la clase Symfony\Component\HttpFoundation\Response, la cual proporciona una variedad de métodos para construir respuestas HTTP:

Route::get('home', function () {
    return response('Hello World', 200)
                  ->header('Content-Type', 'text/plain');
});

Adjuntando encabezados a las respuestas

Ten en cuenta que la mayoría de los métodos de respuestas son encadenables, permitiendo la construcción fluida de instancias de respuesta. Por ejemplo, puedes usar el método header para agregar una serie de encabezados para la respuesta antes de enviarla de regreso al usuario:

return response($content)
            ->header('Content-Type', $type)
            ->header('X-Header-One', 'Header Value')
            ->header('X-Header-Two', 'Header Value');

O, puedes usar el método withHeaders para especificar un arreglo de encabezados para que sean agregados a la respuesta:

return response($content)
            ->withHeaders([
                'Content-Type' => $type,
                'X-Header-One' => 'Header Value',
                'X-Header-Two' => 'Header Value',
            ]);
Middleware para control de caché

Laravel incluye un middleware cache.headers, el cual puede ser usado para rápidamente establecer el encabezado Cache-Control para un grupo de rutas. Si etag está especificado en la lista de directivas, un hash MD5 del contenido de la respuesta será automáticamente establecido como identificador del ETag:

Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
    Route::get('privacy', function () {
        // ...
    });

    Route::get('terms', function () {
        // ...
    });
});

Adjuntando cookies a las respuestas

El método cookie en las instancias de respuesta permite que adjuntes fácilmente cookies a la respuesta. Por ejemplo, puedes usar el método cookie para generar una cookie y adjuntarla fluidamente a la instancia de respuesta, de la siguiente manera:

return response($content)
                ->header('Content-Type', $type)
                ->cookie('name', 'value', $minutes);

El método cookie también acepta unos cuantos argumentos los cuales son usados con menos frecuencia. Generalmente, estos argumentos tienen el mismo propósito y significado que los argumentos que serán dados al método nativo de PHP setcookie:

->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly)

Alternativamente, puedes usar la clase facade Cookie para agregar cookies a la cola y adjuntarlas a la respuesta saliente de tu aplicación. El método queue acepta una instancia Cookie o los argumentos que se necesitan para crear una instancia Cookie. Estas cookies serán adjuntadas a la respuesta saliente antes de que sea enviada al navegador:

Cookie::queue(Cookie::make('name', 'value', $minutes));

Cookie::queue('name', 'value', $minutes);

Cookies y Encriptación

De forma predeterminada, todos los cookies generados por Laravel son encriptados y firmados de modo que no puedan ser modificados o leídos por el cliente. Si prefieres deshabilitar la encriptación para un subconjunto de cookies generados por tu aplicación, puedes usar la propiedad $except del middleware App\Http\Middleware\EncryptCookies, el cual es localizado en el directorio app/Http/Middleware:

/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
    'cookie_name',
];

Redirecciones

Las respuestas redireccionadas son instancias de la clase Illuminate\Http\RedirectResponse y contienen los encabezados apropiados que se necesitan para redireccionar al usuario a otra URL. Hay varias formas de generar una instancia RedirectResponse. El método más simple es usar el helper global redirect:

Route::get('dashboard', function () {
    return redirect('home/dashboard');
});

Algunas veces podrás querer redireccionar al usuario a su página previa, tal como cuando un formulario enviado no es válido. Puedes hacer eso usando la función helper global back. Ya que esta característica utiliza la sesión, asegúrate de que la ruta llamando a la función back está usando el grupo de middleware web o tiene todos los middleware de sesión aplicados:

Route::post('user/profile', function () {
    // Validate the request...

    return back()->withInput();
});

Ver post

Solicitudes HTTP – Documentación de Laravel 6

Accediendo a la solicitud

Para obtener una instancia de la solicitud HTTP actual por medio de una inyección de dependencia, deberías poner la referencia de la clase Illuminate\Http\Request en tu método de controlador. La instancia de la solicitud entrante automáticamente será inyectada por el contenedor de servicio:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
    * Store a new user.
    *
    * @param  Request  $request
    * @return Response
    */
    public function store(Request $request)
    {
        $name = $request->input('name');

        //
    }
}

Inyección de dependencias y parámetros de rutas

Si tu método de controlador también está esperando la entrada de un parámetro de ruta deberías listar tus parámetros de ruta después de tus otras dependencias. Por ejemplo, si tu ruta es definida como sigue:

Route::put('user/{id}', 'UserController@update');

Todavía puedes poner la referencia de la clase Illuminate\Http\Request y acceder a tu parámetro de ruta id al definir tu método de controlador como sigue:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    /**
    * Update the specified user.
    *
    * @param  Request  $request
    * @param  string  $id
    * @return Response
    */
    public function update(Request $request, $id)
    {
        //
    }
}

Accediendo la solicitud a través de closures de rutas

También puedes poner la referencia de la clase Illuminate\Http\Request en una Closure de ruta. El contenedor de servicio automáticamente inyectará la solicitud entrante dentro de la Closure que es ejecutada:

use Illuminate\Http\Request;

Route::get('/', function (Request $request) {
    //
});

Ver post

Controladores – Documentación de Laravel 6

Introducción

En lugar de definir toda la lógica de manejo de solicitud como Closure en archivos de ruta, puedes desear organizar este comportamiento usando clases Controller. Los controladores pueden agrupar la lógica de manejo de solicitud relacionada dentro de una sola clase. Los controladores son almacenados en el directorio app/Http/Controllers.

Controladores básicos

Ver post

Protección CSRF – Documentación de Laravel 6

Introducción

Laravel hace que sea fácil proteger tu aplicación de ataques de tipo cross-site request forgery (CSRF). Los ataques de tipo CSRF son un tipo de explotación de vulnerabilidad malicioso por el cual comandos no autorizados son ejecutados en nombre de un usuario autenticado.

Laravel genera automáticamente un «token» CSRF para cada sesión de usuario activa manejada por la aplicación. Este token es usado para verificar que el usuario autenticado es quien en realidad está haciendo la petición a la aplicación.

En cualquier momento que definas un formulario HTML en tu aplicación, debes incluir un campo de token CSRF oculto en el formulario para que el middleware de protección CSRF pueda validar la solicitud. Puedes usar la directiva de Blade @csrf para generar el campo de token:

<form method="POST" action="/profile">
    @csrf
    ...
</form>

El middleware VerifyCsrfToken, el cual es incluido en el grupo de middleware web, verificará automáticamente que el token en el campo de la solicitud coincida con el almacenado en la sesión.

Tokens CSRF & JavaScript

Cuando se crean aplicaciones controladas por JavaScript, es conveniente hacer que tu librería HTTP de JavaScript agregue automáticamente el token CSRF a cada petición saliente. Por defecto, la librería HTTP Axios proporcionada en el archivo resources/js/bootstrap.js automáticamente envía un header X-XSRF-TOKEN usando el valor de la cookie encriptada XSRF-TOKEN. Si no estás usando esta librería, necesitarás configurar de forma manual este comportamiento en tus aplicaciones.

Excluyendo las URIs de la protección CSRF

Algunas veces puedes desear excluir un conjunto de URIs de la protección CSRF. Por ejemplo, si estás usando Stripe para procesar pagos y estás utilizando su sistema webhook, necesitarás excluir tu ruta de manejador webhook de Stripe de la protección CSRF ya que Stripe no sabrá que token CSRF enviar a sus rutas.

Típicamente, deberías colocar este tipo de rutas fuera del grupo de middleware web que el RouteServiceProvider aplica a todas las rutas en el archivo routes/web.php. Sin embargo, también puedes excluir las rutas al añadir sus URIs a la propiedad except del middleware VerifyCsrfToken:

<?php

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
    * The URIs that should be excluded from CSRF verification.
    *
    * @var array
    */
    protected $except = [
        'stripe/*',
        'http://example.com/foo/bar',
        'http://example.com/foo/*',
    ];
}

El middleware CSRF está deshabilitado automáticamente al ejecutar pruebas.

X-CSRF-TOKEN

Además de comprobar el token CSRF como parámetro POST, el middleware VerifyCsrfToken también comprobará el encabezado de solicitud X-CSRF-TOKEN. Podrías, por ejemplo, almacenar el token en una etiqueta meta de HTML:

<meta name="csrf-token" content="{{ csrf_token() }}">

Entonces, una vez que has creado la etiqueta meta, puedes instruir una biblioteca como jQuery para añadir automáticamente el token a todos los encabezados de las peticiones. Esto proporciona protección CSRF fácil y conveniente para tus aplicaciones basadas en AJAX.

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

X-XSRF-TOKEN

Laravel almacena el token CSRF actual en una cookie XSRF-TOKEN encriptada que es incluida con cada respuesta generada por el framework. Puedes usar el valor del cookie para establecer el encabezado de la solicitud X-XSRF-TOKEN.

Esta cookie primeramente es enviada por conveniencia ya que algunos frameworks JavaScript y librerías, como Angular y Axios, colocan automáticamente su valor en el encabezado X-XSRF-TOKEN en las solicitudes de mismo origen.

Por defecto, el archivo resources/js/bootstrap.js incluye la librería HTTP Axios que enviará automáticamente esto por ti.

Suscríbete a nuestro boletín

Te enviaremos publicaciones con consejos útiles y múltiples recursos para que sigas aprendiendo.

Suscríbete a nuestro boletín

Recibe consejos útiles, promos y múltiples recursos directamente en tu correo.

Tu nombre y correo serán enviados directamente a MailChimp. No compartiremos tus datos con otras empresas.