<![CDATA[Café de por medio]]>https://blog.coffeedevs.com/https://blog.coffeedevs.com/favicon.pngCafé de por mediohttps://blog.coffeedevs.com/Ghost 5.18Mon, 10 Oct 2022 16:09:23 GMT60<![CDATA[Laravel 9 - Cambios en español]]>

Laravel 9

Como ya sabrán, Laravel hizo la transición a lanzamientos anuales con el lanzamiento de Laravel 8. Anteriormente, las versiones principales se lanzaban cada 6 meses. Esta transición tiene como objetivo aliviar la carga de mantenimiento de la comunidad y desafiar al equipo

]]>
https://blog.coffeedevs.com/laravel-9-cambios-en-espanol/620cdf8963cdf352b1b8206dSat, 19 Mar 2022 13:10:33 GMT

Laravel 9

Laravel 9 - Cambios en español

Como ya sabrán, Laravel hizo la transición a lanzamientos anuales con el lanzamiento de Laravel 8. Anteriormente, las versiones principales se lanzaban cada 6 meses. Esta transición tiene como objetivo aliviar la carga de mantenimiento de la comunidad y desafiar al equipo de Laravel a ofrecer nuevas funciones sorprendentes y potentes sin introducir cambios importantes.

Laravel 9 sigue las mejoras realizadas en Laravel 8.x introduciendo soporte para los componentes 6.0 de Symfony, Symfomny Mailer, Flysystem 3.0, mejoras de salida en route:list, un driver de Laravel Scout para la base de datos, una sintáxis nueva para accesors/mutators, la posibilidad de usar Enums en las rutas implicitas, y una variedad de otras correcciones y mejoras de usabilidad.

PHP 8.0

Laravel 9.x requiere mínimo PHP 8.0.

Symfony Mailer

Versiones anteriores de Laravel usaban la librería Swift Mailer para enviar email. Esa librería no tiene más mantenimiento y ahora fue reemplazada por Symfony Mailer.

Flysystem 3.x

Laravel 9.x actualiza la dependencia de Flysystem a la 3.x.
Flysystem se encarga de todas las interacciones con el sistema de archivos ofrecidos por la fachada Storage.

Mejoras en los Accessors / Mutators de Eloquent

Laravel 9.x ofrece una nueva forma de definir accesors y mutators en Eloquent. En versiones previas de Laravel, la única forma de definirlos era mediante métodos prefixeados en tu modelo:

public function getNameAttribute($value)
{
    return strtoupper($value);
}
 
public function setNameAttribute($value)
{
    $this->attributes['name'] = $value;
}

Sin embargo, en Laravel 9.x puedes definir accessors y mutators usando un método único, sin prefixes, usando Attribute como type-hint.

use Illuminate\Database\Eloquent\Casts\Attribute;
 
public function name(): Attribute
{
    return new Attribute(
        get: fn ($value) => strtoupper($value),
        set: fn ($value) => $value,
    );
}

Además, este nuevo enfoque permite definir accesors que se pueden cachear, mejorando el rendimiento:

use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;
 
public function address(): Attribute
{
    return new Attribute(
        get: fn ($value, $attributes) => new Address(
            $attributes['address_line_one'],
            $attributes['address_line_two'],
        ),
        set: fn (Address $value) => [
            'address_line_one' => $value->lineOne,
            'address_line_two' => $value->lineTwo,
        ],
    );
}

Casting de atributos a Enums

Solo disponible para PHP 8.1+.

Eloquent ahora te permite castear tus atributos a Enums definidos en PHP.
Para lograr esto, puedes especificar un atributo y un Enum al que quieres transformarlo en el array $casts de tu modelo:

use App\Enums\ServerStatus;
 
/**
 * The attributes that should be cast.
 *
 * @var array
 */
protected $casts = [
    'status' => ServerStatus::class,
];

Una vez que definiste el cast para tu modelo, el atributo especificado será automaticamente transformado desde y hacia el Enum elegido:

if ($server->status == ServerStatus::provisioned) {
    $server->status = ServerStatus::ready;
 
    $server->save();
}

Parámetros en rutas implicitas con Enums

PHP 8.1 introduce soporte para Enums. Laravel 9 agrega la habilidad de usar un Enum como type-hint en la definición de tu ruta y Laravel solo invocara la ruta si ese segmento corresponde a un Enum valido. De otra forma, devuelve un 404.
Por ejemplo, dado el siguiente Enum:

enum Category: string
{
    case Fruits = 'fruits';
    case People = 'people';
}

Puedes definir una ruta que solo será invocada si el segmento {category} de la ruta es "fruits" o "people". De otra manera, se devolverá una respuesta 404:

Route::get('/categories/{category}', function (Category $category) {
    return $category->value;
});

Limitación forzada de Route Bindings (uniones de ruta)

En versiones anteriores de Laravel, podías limitar el segundo modelo de Eloquent en la definición de una ruta como el hijo del modelo anterior.
Por ejemplo, considera la siguiente definición de una ruta que recibe un blog post por slug de un usuario específico:

use App\Models\Post;
use App\Models\User;
 
Route::get('/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

Cuando se usa una clave implicita para hacer la unión como un parámetro anidado, Laravel automáticamente limita la consulta para recuperar el modelo anidado usando convenciones para adivinar la relación entre el hijo y el padre.
Sin embargo, este comportamiento estaba soportado previamente por Laravel solo cuando se usaba una clave personalizada para limitar la ruta hijo (slug en este caso).

Ahora, en Laravel 9, puedes indicar a Laravel que limite el "hijo" incluso cuando no hay una clave personalizada definida. Para hacer esto, puedes invocar el método scopeBindings cuando defines la ruta:

use App\Models\Post;
use App\Models\User;
 
Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
    return $post;
})->scopeBindings();

O, puedes indicar a un grupo entero de definiciones de ruta a usar uniones limitadas:

Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', function (User $user, Post $post) {
        return $post;
    });
});

Controladores para grupos de rutas

Ahora puede usar el método controller para definir un controlador común para todas las rutas dentro del grupo. Luego, al definir las rutas, solo necesitas proporcionar el Controller que invocan:

use App\Http\Controllers\OrderController;
 
Route::controller(OrderController::class)->group(function () {
    Route::get('/orders/{id}', 'show');
    Route::post('/orders', 'store');
});

Búsquedas de texto completo para índices y consultas where

Al usar MySQL o PostgreSQL, ahora se puede agregar el método fullText a las definiciones de columna para generar índices de texto completo:

$table->text('bio')->fullText();

Además, los métodos whereFullText y orWhereFullText se pueden usar para agregar cláusulas "where" de texto completo a una consulta de columnas que tienen índices de texto completo. Laravel transformará estos métodos en el SQL apropiado para el sistema de base de datos subyacente. Por ejemplo, se generará una cláusula MATCH AGAINST para aplicaciones que utilicen MySQL:

$users = DB::table('users')
           ->whereFullText('bio', 'web developer')
           ->get();

Motor de base de datos de Laravel Scout

Si su aplicación interactúa con bases de datos pequeñas o medianas o tiene una carga de trabajo liviana, ahora puede usar el motor de "base de datos" de Scout en lugar de un servicio de búsqueda dedicado como Algolia o MeiliSearch. El motor de la base de datos utilizará cláusulas whereLike e índices de texto completo cuando filtre los resultados de su base de datos existente para determinar los resultados de búsqueda aplicables para su consulta.

Para aprender más sobre el motor de base de datos Scout, consulte la documentación de Scout.

Renderizar plantillas Blade en línea

A veces, es posible que deba transformar una cadena de plantilla Blade sin procesar en HTML válido. Puede lograr esto utilizando el método de renderizado proporcionado por la fachada de Blade. El método de representación acepta la cadena de plantilla Blade y una matriz opcional de datos para proporcionar a la plantilla:

use Illuminate\Support\Facades\Blade;
 
return Blade::render('Hello, {{ $name }}', ['name' => 'Julian Bashir']);

De manera similar, el método renderComponent se puede usar para representar un componente de clase dado pasando la instancia del componente al método:

use App\View\Components\HelloComponent;
 
return Blade::renderComponent(new HelloComponent('Julian Bashir'));

Método corto para nombres de Slots

En versiones anteriores de Laravel, los nombres de los slots se proporcionaban mediante un atributo de nombre en la etiqueta x-slot:

<x-alert>
    <x-slot name="title">
        Server Error
    </x-slot>
 
    <strong>Whoops!</strong> Something went wrong!
</x-alert>

Sin embargo, a partir de Laravel 9.x, puede especificar el nombre de la ranura usando una sintaxis conveniente y más corta:

<x-slot:title>
    Server Error
</x-slot>

Directivas Blade para Selected y Checked

Para mayor comodidad, ahora puede usar la directiva @checked para indicar fácilmente si una entrada de casilla de verificación HTML determinada está "marcada". Esta directiva se repetirá si la condición proporcionada se evalúa como verdadera:

<input type="checkbox"
        name="active"
        value="active"
        @checked(old('active', $user->active)) />

Del mismo modo, la directiva @selected se puede usar para indicar si una determinada opción de selección debe ser "seleccionada":

<select name="version">
    @foreach ($product->versions as $version)
        <option value="{{ $version }}" @selected(old('version') == $version)>
            {{ $version }}
        </option>
    @endforeach
</select>

Bootstrap 5 Pagination Views

Laravel ahora incluye vistas de paginación creadas con Bootstrap 5. Para usar estas vistas en lugar de las vistas predeterminadas de Tailwind, puede llamar al método useBootstrapFive del paginador dentro del método boot de su clase App\Providers\AppServiceProvider:

use Illuminate\Pagination\Paginator;
 
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Paginator::useBootstrapFive();
}

Mejoras de validación para datos en matrices anidadas

A veces, es posible que necesite acceder al valor de un elemento de matriz anidado determinado al asignar reglas de validación al atributo. Ahora puede lograr esto usando el método Rule::forEach. El método forEach acepta una función de clausura que se invocará para cada iteración del atributo de matriz siendo validado, y recibirá el valor del atributo y el nombre de atributo explícito y completamente expandido. La función de clausura debe devolver una matriz de reglas para asignar al elemento de la matriz:

use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
 
$validator = Validator::make($request->all(), [
    'companies.*.id' => Rule::forEach(function ($value, $attribute) {
        return [
            Rule::exists(Company::class, 'id'),
            new HasPermission('manage-company', $value),
        ];
    }),
]);

API de Laravel Breeze y Next.js

El kit de inicio de Laravel Breeze ha recibido un modo "API" de scaffolding/andamiaje y una implementación de frontend complementaria de Next.js. Este kit inicial se puede usar para poner en marcha sus aplicaciones Laravel que sirven como backend a través de una API autenticada de Laravel Sanctum para una interfaz de JavaScript.

Página de excepción Ignition mejorada

Ignition, la página de depuración de excepciones de código abierto creada por Spatie, se ha rediseñado desde cero. El nuevo y mejorado Ignition viene con Laravel 9.x e incluye temas claro/oscuro, funcionalidad personalizable de "abrir en el editor" y más.

Mejoras en la salida del comando de CLI `route:list``

La salida de CLI de route:list se ha mejorado significativamente para la versión Laravel 9.x, lo que ofrece una hermosa experiencia nueva al explorar las definiciones de ruta.

Cobertura de pruebas con el comando test de Artisan

El comando test de Artisan recibió una nueva opción --coverage que puede usar para explorar la cantidad de cobertura de código que sus pruebas brindan a su aplicación:

php artisan test --coverage

Los resultados de la cobertura de la prueba se mostrarán directamente en la salida de la CLI.

Además, si desea especificar un umbral mínimo que debe cumplir el porcentaje de cobertura de su prueba, puede usar la opción --min. La suite de pruebas fallará si no se alcanza el umbral mínimo dado:

php artisan test --coverage --min=80.3

Servidor de Echo: Soketi

Aunque no es exclusivo de Laravel 9.x, Laravel ha ayudado recientemente con la documentación de Soketi, un servidor Web Socket compatible con Laravel Echo escrito para Node.js. Soketi ofrece una excelente alternativa de código abierto a Pusher y Ably para aquellas aplicaciones que prefieren administrar su propio servidor Web Socket.

Para obtener más información sobre el uso de Soketi, consulte la documentación de transmisión y la documentación de Soketi.

Mejor soporte del IDE para Colecciones

Laravel 9.x agrega definiciones "genéricas" mejoradas al componente de colecciones, mejorando el soporte de análisis estático y IDE. Los IDE como PHPStorm o las herramientas de análisis estático como PHPStan ahora comprenderán mejor las colecciones de Laravel de forma nativa.

Nuevos helpers

Laravel 9.x presenta dos funciones helpers nuevas y convenientes que puede usar en su propia aplicación.

str

La función str devuelve una nueva instancia de Illuminate\Support\Stringable para el string dado.
Esta función es equivalente al método Str::of:

$string = str('Taylor')->append(' Otwell');
 
// 'Taylor Otwell'

Si no se proporciona ningún argumento a la función str, la función devuelve una instancia de Illuminate\Support\Str:

$snake = str()->snake('LaravelFramework');
 
// 'laravel_framework'

to_route

La función to_route genera una respuesta HTTP de redirección para una ruta con nombre determinada, lo que proporciona una forma expresiva de redirigir a rutas con nombre desde sus rutas y controladores:

return to_route('users.show', ['user' => 1]);

Si es necesario, puede pasar el código HTTP que debe asignarse a la redirección y cualquier encabezado de respuesta adicional como el tercer y cuarto argumento del método to_route:

return to_route('users.show', ['user' => 1], 302, ['X-Framework' => 'Laravel']);
]]>
<![CDATA[Laravel 8 - Cambios en español]]>

Laravel 8

Laravel 8 continua las mejoras introducidas por Laravel 7.x, incorporando Laravel Jetstream, clases para las model factories, consolidación de migraciones, trabajos por lotes, mejoras en el manejo de limitación de peticiones, mejoras en el manejo de las colas, componentes dinámicos en

]]>
https://blog.coffeedevs.com/laravel-8-cambios-en-espanol/5f8082d9ed74f1085316d3deSat, 10 Oct 2020 13:22:33 GMT

Laravel 8

Laravel 8 - Cambios en español

Laravel 8 continua las mejoras introducidas por Laravel 7.x, incorporando Laravel Jetstream, clases para las model factories, consolidación de migraciones, trabajos por lotes, mejoras en el manejo de limitación de peticiones, mejoras en el manejo de las colas, componentes dinámicos en Blade, paginación con Tailwind, helpers para testear casos que involucren tiempo, mejoras al comando artisan serve, mejoras en los event listener, y una variedad de otras correcciones y mejoras de usabilidad.

Laravel Jetstream

Laravel Jetstream fue escrito por Taylor Otwell.

Laravel Jetstream es un esqueleto de aplicación bellamente diseñado para Laravel. Jetstream proporciona el punto de partida perfecto para tu próximo proyecto e incluye inicio de sesión, registro, verificación de correo electrónico, autenticación de dos factores, administración de sesiones, soporte de API a través de Laravel Sanctum y administración de equipo opcional. Laravel Jetstream reemplaza y mejora el esqueleto de autenticación que existía en versiones anteriores de Laravel.

Jetstream está diseñado con Tailwind CSS y ofrece su elección de Livewire o Inertia como esqueletos.

Directorio para los modelos

Debido a la abrumadora demanda de la comunidad, el esqueleto predeterminado de la aplicación Laravel ahora contiene un directorio app/Models. ¡Esperamos que disfrutes de este nuevo hogar para tus modelos Eloquent! Todos los comandos relevantes del generador se han actualizado para asumir que los modelos existen dentro del directorio app/Models, si existe. Si el directorio no existe, Laravel asumirá que tus modelos deben colocarse dentro del directorio app.

Clases para Model Factories

Las clases para Model Factories fueron escritas por Taylor Otwell.

Las model factories de Eloquent fueron re-escritas completamente como clases y mejorado el soporte para las relaciones como ciudadanos de primera.
Por ejemplo, la UserFactory incluída por defecto en Laravel queda así:

<?php

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    /**
     * The name of the factory's corresponding model.
     *
     * @var string
     */
    protected $model = User::class;

    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'email' => $this->faker->unique()->safeEmail,
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}

Gracias al nuevo trait HasFactory disponible en los modelos generados, puede utilizarse de la siguiente forma:

use App\Models\User;

User::factory()->count(50)->create();

Como las model factories ahora son simples clases de PHP, las transformaciones de estado pueden escribirse como métodos de clase. Además, puedes agregar otras clases de ayuda, tantas como necesites.

Por ejemplo, tu modelo Userpuede tener un estado suspended que modifica el valor por defecto de uno de los atributos. Puedes definir las transformaciones de estado usando el método state de la clase base. Puedes nombrar este método como quieras. Después de todo, es un método típico de PHP:

/**
 * Indicate that the user is suspended.
 *
 * @return \Illuminate\Database\Eloquent\Factories\Factory
 */
public function suspended()
{
    return $this->state([
        'account_status' => 'suspended',
    ]);
}

Después de definir el método de transformación de estado, podemos usarlo así:

use App\Models\User;

User::factory()->count(5)->suspended()->create();

Como se mencionó, las model factories de Laravel 8 contienen soporte de primera clase para las relaciones. Entonces, asumiendo que nuestro modelo User tiene un método de relación posts, podemos simplemente ejecutar el siguiente código para generar un usuario con tres publicaciones:

$users = User::factory()
            ->hasPosts(3, [
                'published' => false,
            ])
            ->create();

Para facilitar el proceso de actualización, se lanzó el paquete laravel/legacy-factories para brindar soporte a la iteración anterior de model factories en Laravel 8.x.

Las model factories reescritas de Laravel contienen muchas más características que pensamos que te encantarán. Para obtener más información sobre las model factories, consulte la documentación de prueba de la base de datos.

Consolidación de migraciones

Consolidación de migraciones fue contribuido por Taylor Otwell.

A medida que crece su aplicación, puede acumular más y más migraciones a lo largo del tiempo. Esto puede hacer que su carpeta de migraciones crezca con potencialmente cientos de migraciones. Si está utilizando MySQL o PostgreSQL, ahora puede "aplastar" sus migraciones en un solo archivo SQL. Para comenzar, ejecute el comando schema: dump:

php artisan schema:dump

// Volcar el esquema de la base de datos actual y eliminar todas las migraciones existentes...
php artisan schema:dump --prune

Cuando ejecutas este comando, Laravel escribirá un archivo "esquema" en tu directorio database/schema. Ahora, cuando intente migrar su base de datos y no se hayan ejecutado otras migraciones, Laravel ejecutará primero el SQL del archivo de esquema. Después de ejecutar los comandos del archivo de esquema, Laravel ejecutará las migraciones restantes que no formaban parte del esquema volcado.

Trabajos por lotes

Trabajos por lotes fue contribuido por Taylor Otwell & Mohamed Said.

La función de procesamiento de trabajos por lotes de Laravel le permite ejecutar fácilmente un lote de trabajos y luego realizar alguna acción cuando el lote de trabajos se haya completado.

El nuevo método batch de la fachada Bus se puede utilizar para despachar un lote de trabajos. Por supuesto, el procesamiento por lotes es principalmente útil cuando se combina con callbacks. Por lo tanto, puede usar los métodos then, catch y finally para definir callbacks para todo el lote. Cada una de estas callbacks recibirá una instancia Illuminate\Bus\Batch cuando se invoquen:

use App\Jobs\ProcessPodcast;
use App\Podcast;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
use Throwable;

$batch = Bus::batch([
    new ProcessPodcast(Podcast::find(1)),
    new ProcessPodcast(Podcast::find(2)),
    new ProcessPodcast(Podcast::find(3)),
    new ProcessPodcast(Podcast::find(4)),
    new ProcessPodcast(Podcast::find(5)),
])->then(function (Batch $batch) {
    // Todos los trabajos se completaron con éxito...
})->catch(function (Batch $batch, Throwable $e) {
    // Se detectó el primer error del lote...
})->finally(function (Batch $batch) {
    // El lote se terminó de ejecutar...
})->dispatch();

return $batch->id;

Para obtener más información sobre el procesamiento de trabajos por lotes, consulte la documentación de colas.

Mejoras en limitación de peticiones

Las mejoras en limitación de peticiones fue contribuido por Taylor Otwell.

La función de limitación de peticiones de Laravel se ha mejorado con más flexibilidad y potencia, al tiempo que mantiene la compatibilidad hacia atrás con la API de middleware "throttle" de la versión anterior.

Los limitadores de peticiones se definen utilizando el método for de la fachada RateLimiter. El método for acepta un nombre de limitador de peticiones y un closure que devuelve la configuración de límite que debe aplicarse a las rutas a las que se les asigna este limitador de peticiones:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('global', function (Request $request) {
    return Limit::perMinute(1000);
});

Dado que los callbacks del limitador de peticiones reciben una instancia de la solicitud HTTP entrante, puede crear el límite de peticiones apropiado de forma dinámica en función de la solicitud entrante o del usuario autenticado:

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100);
});

A veces, es posible que desee segmentar los límites por algún valor arbitrario. Por ejemplo, es posible que desee permitir que los usuarios accedan a una ruta determinada 100 veces por minuto por dirección IP. Para lograr esto, puede usar el método by cuando construya su límite de solicitudes:

RateLimiter::for('uploads', function (Request $request) {
    return $request->user()->vipCustomer()
                ? Limit::none()
                : Limit::perMinute(100)->by($request->ip());
});

Se pueden adjuntar limitadores de peticiones a rutas o grupos de rutas usando el middleware throttle. El middleware throttle acepta el nombre del limitador que desea asignar a la ruta:

Route::middleware(['throttle:uploads'])->group(function () {
    Route::post('/audio', function () {
        //
    });

    Route::post('/video', function () {
        //
    });
});

Para aprender más acerca de esta función, por favor consulta la documentación de enrutamiento.

Mejoras en el Modo Mantenimiento

Las mejoras en el Modo Mantenimiento fueron contribuidas por Taylor Otwell inspirado por Spatie.

En versiones anteriores de Laravel, la función del modo mantenimiento php artisan down se puede omitir usando una "lista de permitidos" de direcciones IP que tenían permiso para acceder a la aplicación. Esta característica se ha eliminado en favor de una solución de "clave secreta"/token más simple.

Mientras está en modo mantenimiento, puede usar la opción secret para especificar un token de omisión del modo de mantenimiento:

php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"

Después de colocar la aplicación en modo mantenimiento, puede navegar a la URL de la aplicación que coincide con este token y Laravel emitirá una cookie de omisión del modo de mantenimiento a su navegador:

https://example.com/1630542a-246b-4b66-afa1-dd72a4c43515

Cuando acceda a esta ruta oculta, será redirigido a la ruta / de la aplicación. Una vez que la cookie haya sido enviada a su navegador, podrá navegar por la aplicación normalmente como si no estuviera en modo de mantenimiento.

Pre-Rendering The Maintenance Mode View

Si utilizas el comando php artisan down durante el deployment, tus usuarios pueden encontrar errores ocasionalmente al acceder a la aplicación mientras se actualizan las dependencias de Composer u otros componentes de la infraestructura. Esto ocurre porque una parte importante de Laravel debe iniciarse para determinar que su aplicación está en modo mantenimiento y presentar la vista del modo mantenimiento utilizando Blade.

Por esta razón, Laravel ahora permite pre-renderizar una vista en modo de mantenimiento que se devolverá al comienzo del ciclo de la solicitud. Esta vista se presenta antes de que se haya cargado cualquiera de las dependencias de la aplicación. Puede pre-renderizar una plantilla de su elección usando la opción render del comando down:

php artisan down --render="errors::503"

Funcion catch para trabajos anónimos

Las función catch fue contribuida por Mohamed Said.

Con el nuevo método catch, ahora puede proporcionar un closure que debe ejecutarse si no se completa correctamente un trabajo encolado anónimo después de agotar todos los reintentos configurados de la cola:

use Throwable;

dispatch(function () use ($podcast) {
    $podcast->publish();
})->catch(function (Throwable $e) {
    // Este trabajo falló...
});

Componentes dinámicos en Blade

Componentes dinámicos en Blade fue contribuido por Taylor Otwell.

A veces es posible que necesite renderizar un componente pero no saber qué componente debe renderizarse hasta el tiempo de ejecución. En esta situación, ahora puede usar el componente dynamic-component incorporado en Laravel para renderizar el componente basado en un valor de tiempo de ejecución o variable:

<x-dynamic-component :component="$componentName" class="mt-4" />

Para obtener más información sobre los componentes de Blade, consulte la documentación de Blade.

Mejoras en Event Listener

Las mejoras en Event Listener fueron contribuidas por Taylor Otwell.

Los event listeners basados en closures ahora pueden registrarse solamente pasando un closure al método Event::listen. Laravel inspeccionará el closure para determinar qué tipo de evento maneja el event listener:

use App\Events\PodcastProcessed;
use Illuminate\Support\Facades\Event;

Event::listen(function (PodcastProcessed $event) {
    //
});

Además, los event listeners basados en closures ahora se pueden marcar como encolables usando la función Illuminate\Events\queueable:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;

Event::listen(queueable(function (PodcastProcessed $event) {
    //
}));

Al igual que los trabajos en cola, puedes utilizar los métodos onConnection, onQueue y delay para personalizar la ejecución del event listener:

Event::listen(queueable(function (PodcastProcessed $event) {
    //
})->onConnection('redis')->onQueue('podcasts')->delay(now()->addSeconds(10)));

Si deseas manejar fallas en event listeners anónimos, puedes proporcionar un closure al método catch mientras defines el event listener queueable:

use App\Events\PodcastProcessed;
use function Illuminate\Events\queueable;
use Illuminate\Support\Facades\Event;
use Throwable;

Event::listen(queueable(function (PodcastProcessed $event) {
    //
})->catch(function (PodcastProcessed $event, Throwable $e) {
    // El listener falló...
}));

Funciones helper para pruebas con tiempos

Funciones helper para pruebas con tiempos fueron contribuidos por Taylor Otwell inspirado en Ruby on Rails.

Cuando se hace pruebas, puede necesitarse modificar la hora devuelta por funciones helper como now o Illuminate\Support\Carbon::now(). La clase base de Laravel ahora incluye helpers que permiten manipular la hora actual:

public function testTimeCanBeManipulated()
{
    // Viajar al futuro...
    $this->travel(5)->milliseconds();
    $this->travel(5)->seconds();
    $this->travel(5)->minutes();
    $this->travel(5)->hours();
    $this->travel(5)->days();
    $this->travel(5)->weeks();
    $this->travel(5)->years();

    // Viajar al pasado...
    $this->travel(-5)->hours();

    // Viajar a un momento en particular...
    $this->travelTo(now()->subHours(6));

    // Volver al presente...
    $this->travelBack();
}

Mejoras en artisan serve

Las mejoras en artisan serve fueron contribuidas por Taylor Otwell.

El comando Artisan serve se ha mejorado con la recarga automática cuando se detectan cambios en las variables de entorno dentro de su archivo local .env. Anteriormente, el comando tenía que detenerse y reiniciarse manualmente.

Vistas de paginación con Tailwind

El paginador de Laravel se ha actualizado para utilizar Tailwind CSS de forma predeterminada. Tailwind CSS es un framework CSS de bajo nivel altamente personalizable que brinda todos los componentes básicos que se necesitan para crear diseños a medida sin ningún diseño específico que tengas que luchar para anular. Por supuesto, las vistas Bootstrap 3 y 4 también permanecen disponibles.

Actualizaciones en los namespace para el archivo de enrutamiento.

En versiones anteriores de Laravel, RouteServiceProvider contenía una propiedad $namespace. El valor de esta propiedad era automáticamente prefijado en las definiciones de ruta del controlador y las llamadas al método action o URL::action. En Laravel 8.x, esta propiedad es null por defecto. Esto significa que Laravel no realizará ningún prefijado automático para los namespaces. Por lo tanto, en las nuevas aplicaciones de Laravel 8.x, las definiciones de ruta de los controladores deben definirse utilizando la sintaxis estándar de PHP:

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

Las llamadas a los métodos relacionados con action deben usar la misma sintaxis:

action([UserController::class, 'index']);

return Redirect::action([UserController::class, 'index']);

Si prefieres el estilo Laravel 7.x para prefijos de controladores en el archivo de rutas, puedes simplemente completar la propiedad $namespace en el RouteServiceProvider de la aplicación.

]]>
<![CDATA[Laravel 7 - Lista de cambios en español]]>

Laravel 7 continua con las mejoras realizadas en Laravel 6.x, introduciendo Laravel Airlock, mejoras en la velocidad de enrutamiento, conversiones personalizadas de atributos en Eloquent, etiquetas para componentes de Blade, operaciones fluidas con strings, un cliente HTTP enfocado en desarrolladores, soporte para CORS de base, mejoras en el scope

]]>
https://blog.coffeedevs.com/laravel-7-lista-de-cambios-en-espanol/5e68d3cf24a63c71fd7275aaWed, 11 Mar 2020 12:05:51 GMTLaravel 7 - Lista de cambios en español

Laravel 7 continua con las mejoras realizadas en Laravel 6.x, introduciendo Laravel Airlock, mejoras en la velocidad de enrutamiento, conversiones personalizadas de atributos en Eloquent, etiquetas para componentes de Blade, operaciones fluidas con strings, un cliente HTTP enfocado en desarrolladores, soporte para CORS de base, mejoras en el scope de los modelos obtenidos por Routes, personalización de Stubs para tests, mejoras en las colas con base de datos, múltiples drivers para email, un nuevo comando artisan test, y una variedad de otras correcciones y mejoras de usabilidad.

Laravel Airlock

Laravel Airlock provee un sistema de autenticación ligero para SPAs, aplicaciones móviles, y APIs simples basadas en tokens. Airlock permite a cada usuario de tu aplicación generar múltiples tokens de API para su cuenta. Estos tokens pueden ser otorgados habilidades y alcances que especifican que acciones pueden realizar esos tokens.

Para más información, revisar la documentación de Airlock.

Conversiones personalizadas para Eloquent

Laravel tiene una variedad de tipos preconstruidos para hacer conversiones; sin embargo, ocasionalmente puedes necesitar definir tus propios tipos de conversión. Puedes lograr esto definiendo una clase que implementa la interfaz CastsAttributes.

Clases que implementen esta interfaz deben definir métodos get y set. El método get es el responsable de transformar el valor crudo de la base de datos al valor convertido, mientras que el método set debe transformar el valor convertido al valor crudo para guardar en la base de datos. A modo de ejemplo, vamos a re-implementar el tipo de conversión json que viene en el framework:

<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Json implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return array
     */
    public function get($model, $key, $value, $attributes)
    {
        return json_decode($value, true);
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  array  $value
     * @param  array  $attributes
     * @return string
     */
    public function set($model, $key, $value, $attributes)
    {
        return json_encode($value);
    }
}

Una vez que definimos estos tipos, puedes asignarlo al atributo de un modelo usando el nombre de la clase:

<?php

namespace App;

use App\Casts\Json;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => Json::class,
    ];
}

Para aprender cómo escribir tipos personalizdos de conversión, incluyendo como convertir a Value Objects, por favor consulta la documentación de Eloquent.

Etiquetas y mejoras para componentes Blade

Los componentes de Blade fueron reformados para permitir su renderizado basado en etiquetas, manejo de atributos, clases y más. Dado que la reforma de los componentes de Blade es tan extensa, por favor consulta la documentación completa para aprender más sobre sus características.

En resumen, un componente ahora puede asociarse a una clase que especifica la información que acepta. Todas las propiedades y métodos públicos definidos en la clase del componente estarán disponibles automáticamente a la vista del componente. Cualquier atributo extra agregado por HTML puede ser manipulado automáticamente a través de la variable $attribute.

En este ejemplo, asumimos que App\View\Components\Alert es un componente definido de la siguiente forma:


<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    /**
     * The alert type.
     *
     * @var string
     */
    public $type;

    /**
     * Create the component instance.
     *
     * @param  string  $type
     * @return void
     */
    public function __construct($type)
    {
        $this->type = $type;
    }

    /**
     * Get the class for the given alert type.
     *
     * @return string
     */
    public function classForType()
    {
        return $this->type == 'danger' ? 'alert-danger' : 'alert-warning';
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.alert');
    }
}

Y, asumiendo que el template del componente está definido de la siguiente forma:


<!-- /resources/views/components/alert.blade.php -->

<div class="alert {{ $classForType }}" {{ $attributes }}>
    {{ $heading }}

    {{ $slot }}
</div>

El componente puede renderizarse en otra vista de Blade usando su etiqueta:

<x-alert type="error" class="mb-4">
    <x-slot name="heading">
        Alert content...
    </x-slot>

    Default slot content...
</x-alert>

Como mencionamos, esto es solo un pequeño ejemplo de la reforma de funcionalidad a los componentes de Blade en Laravel 6 y no llega a demostrar componentes anónimos, en línea, y otras características. Por favor consulta la documentación completa de Blade para aprender más.

La sintáxis @component para componentes Blade no se removió ni se removerá.

Cliente HTTP

Laravel ahora provee un API mínima y expresiva alrededor del cliente HTTP Guzzle, permitiendo hacer peticiones HTTP rápidamente para comunicarse con otras aplicaciones web. El wrapper de Laravel alrededor de Guzzle está enfocado en los casos más comunes y es una excelente experiencia para el desarrollador. Por ejemplo, el cliente hace muy fácil hacer un POST a una interfaz con datos en json:

use Illuminate\Support\Facades\Http;

$response = Http::withHeaders([
    'X-First' => 'foo',
    'X-Second' => 'bar'
])->post('http://test.com/users', [
    'name' => 'Taylor',
]);

return $response['id'];

Además, el cliente HTTP provee simplicidad a la hora de testear:

Http::fake([
    // Stub a JSON response for GitHub endpoints...
    'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),

    // Stub a string response for Google endpoints...
    'google.com/*' => Http::response('Hello World', 200, ['Headers']),

    // Stub a series of responses for Facebook endpoints...
    'facebook.com/*' => Http::sequence()
                            ->push('Hello World', 200)
                            ->push(['foo' => 'bar'], 200)
                            ->pushStatus(404),
]);

Para aprender más sobre todas las características del cliente HTTP, por favor consultar la documentación.

Operaciones fluidas con Strings

Seguramente estes familiarizado con la clase Illuminate\Support\Str, que provee una variedad de operaciones de manipulación de strings. Laravel 7 ahora ofrece un enfoque más orientado a objetos, con manipulaciones de strings declaradas de forma fluida. Puedes crear tu objeto Illuminate\Support\Stringable de forma fluida con el método Str::of. Una variedad de métodos pueden ser encadenados al objeto para manipular el string:

return (string) Str::of('  Laravel Framework 6.x ')
                    ->trim()
                    ->replace('6.x', '7.x')
                    ->slug();

Para más información en los métodos disponibles a través de manipulación de strings de forma fluida, por favor consulte la documentación completa.

Mejoras en Route Model Binding

Personalización de clave

Algunas veces puedes querer resolver modelos de Eloquent usando otra columna que la de id. Para hacer eso, Laravel 7 permite specificar la columna directamente en el parámetro de la ruta:

Route::get('api/posts/{post:slug}', function (App\Post $post) {
    return $post;
});

Alcance automático

A veces, cuando se enlazan múltiples modelos Eloquent en una misma definición de ruta, puedes querer limitar el alcance del segundo modelo Eloquent de tal forma que sea un hijo del primer modelo Eloquent. Por ejemplo, consideremos la situación en la que obtienes un post por slug de un usuario específico:

use App\Post;
use App\User;

Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

Laravel 7 automáticamente limita el alcance de la consulta para obtener el modelo anidado, usando convenciones para adivinar la relación con el padre. En este caso, asume que el modelo User tiene una relación posts (el plural del parametro de ruta) que puede usarse para obtener el modelo Post.

Para más información en Route Model Binding, por favor consulte la documentación.

Múltiples drivers para mails

Laravel 7 permite la configuración de múltiples "mailers" para una misma aplicación.
Cada "mailer" se puede configurar por separado y pueden tener su propio "transporte", permitiendo a tu aplicación utilizar diferentes servicios para distintos tipos de mensajes. Por ejemplo, tu aplicación puede usar Postmark para mandar mails transaccionales, mientras usa Amazon SES para enviar mails masivos.

Por defecto, Laravel utiliza el mailer configurado como default en tu configuración de mail. Sin embargo, puedes usar el método mailer para enviar un mensaje usando un mailer en particular:

Mail::mailer('postmark')
        ->to($request->user())
        ->send(new OrderShipped($order));

Mejoras en la velocidad de enrutamiento

Laravel 7 incluye un método para matchear rutas compiladas a través del comando route:cache. En aplicaciones grandes (por ejemplo, con 800 rutas o más), estas mejoras pueden duplicar las peticiones por segundo de una aplicación "Hello World" de prueba. No es necesario aplicar cambios a tus aplicaciones.

Soporte para CORS

Laravel 7 incluye soporte de primera mano para configurar respuestas a peticiones Cross-Origin Resource Sharing (CORS) OPTIONS integrando el popular paquete Laravel CORS de Barry vd. Heuvel. Un nuevo archivo de configuración para cors está incluido por defecto en las aplicaciones de Laravel.

Para más información, por favor consulta la documentación de CORS.

Query Time Casts

A veces se necesita aplicar conversiones mientras ejecutamos una query, como cuando seleccionamos un valor crudo de una tabla. Por ejemplo, consideremos la siguiente query:

use App\Post;
use App\User;

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
            ->whereColumn('user_id', 'users.id')
])->get();

El atributo last_posted_at en los resultados de la query será un string crudo. Puede ser conveniente se pudieramos aplicar una conversión a date al atributo mientras ejecutamos la query. Para lograr esto, podemos usar el método withCasts provisto por Laravel 7:

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
            ->whereColumn('user_id', 'users.id')
])->withCasts([
    'last_posted_at' => 'date'
])->get();

Mejoras en el driver Database para queues

En versiones anteriores de Laravel, el driver database para queues no era considerado robusto para usar en producción, debido a los deadlocks. Sin embargo, Laravel 7 provee mejoras a aplicaciones usando queues con bases de datos MySQL 8+ como driver. Utilizando la clausula FOR UPDATE SKIP LOCKED y otras mejoras de SQL, el driver database ahora puede usarse de forma segura en aplicaciones de producción con alto volumen.

Comando test de Artisan

Además del comando phpunit, ahora puedes usar el comando test de Artisan para correr tus tests. Este comando provee una hermosa experiencia de usuario en la consola, y más información correspondiente al test que se está corriendo. Adicionalmente, el comando frena automáticamente en la primer falla:

php artisan test

Laravel 7 - Lista de cambios en español

Todo argumento que puede pasarse a phpunit puede también pasarse al comando test de Artisan:

php artisan test --group=feature

Personalización de Stubs

El comando make de Artisan permiten crear una variedad de clases, como Controllers, Jobs, Migrations y Tests. Estas clases son generadas usando archivos "stub" que son pre-cargados con los valores que se ingresan. Sin embargo, a veces es necesario realizar pequeños cambios en los archivos generados por Artisan. Para lograr esto, Laravel 7 provee un comando stub:publish para publicar los stubs más comunes para su personalización:

php artisan stub:publish

Los stubs publicados se encuentran en el directorio stubs en la raíz de la aplicación. Cualquier cambio que se hagan a esos stubs será reflejado cuando generes la clase correspondiente usando el comando make de Artisan.

Queue maxExceptions Configuration

A veces puedes necesitar que un job específico se ejecute muchas veces, pero que debería fallar si los reintentos son activados por un número dado de excepciones. En Laravel 7, puedes definir maxExceptions como propiedad en la clase de tu job:

<?php

namespace App\Jobs;

class ProcessPodcast implements ShouldQueue
{
    /**
     * The number of times the job may be attempted.
     *
     * @var int
     */
    public $tries = 25;

    /**
     * The maximum number of exceptions to allow before failing.
     *
     * @var int
     */
    public $maxExceptions = 3;

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Redis::throttle('key')->allow(10)->every(60)->then(function () {
            // Lock obtained, process the podcast...
        }, function () {
            // Unable to obtain lock...
            return $this->release(10);
        });
    }
}

En este ejemplo, el job es liberado por diez segundos si la aplicación es incapaz de obtener un cerrojo de Redis y continuará hasta que se haya reintentado 25 veces. Sin embargo, el job fallará si tres excepciones no manejadas son arrojadas por el mismo.

]]>
<![CDATA[Laravel 6.0 - Cambios en español!]]>Laravel sacó una nueva versión de su framework, y esta vez promete seguir el sistema de Versionado Semántico, es decir, que sigue el siguiente formato: major.minor.patch, por lo que a partir de ahora, vamos a ver los saltos de versiones de Laravel como

]]>
https://blog.coffeedevs.com/laravel-6-0-cambios-en-espanol/5d70e8ce24a63c71fd727558Tue, 10 Sep 2019 17:37:23 GMT

Laravel sacó una nueva versión de su framework, y esta vez promete seguir el sistema de Versionado Semántico, es decir, que sigue el siguiente formato: major.minor.patch, por lo que a partir de ahora, vamos a ver los saltos de versiones de Laravel como Laravel 7.0, Laravel 8.0 mucho más rápido.

También es una versión LTS (long-term support), que viene acompañado de 2 años de soporte para bugs y 3 años para parches de seguridad. Esto puede ser de utilidad para empresas que no tienen la dinámica de estar actualizando el framework de su producto cada 6 meses, y prefieren estirar los tiempos (aunque saltar de un LTS a otro, implica un upgrade más brusco).

A continuación, los cambios de la nueva versión de Laravel

Laravel 6.0

Laravel 6.0 (LTS) continúa las mejoras realizadas en Laravel 5.8 mediante la introducción de versiones semánticas, compatibilidad con Laravel Vapor, respuestas de autorización mejoradas, middleware para Jobs, Collections diferidas, mejoras en sub-queries, la extracción del scaffolding frontend al paquete de Composer laravel/ui , y una variedad de otras correcciones de errores y mejoras de usabilidad.

Versiones Semánticas

El paquete Laravel (laravel/framework) ahora sigue el estándar de versiones semántico. Esto hace que el marco sea coherente con los otros paquetes Laravel de origen que ya siguieron este estándar de versiones. El ciclo de lanzamiento de Laravel permanecerá sin cambios.

Compatibilidad de vapor Laravel

Laravel 6.0 proporciona compatibilidad con Laravel Vapor, una plataforma de implementación serverless y autoescalable para Laravel. Vapor resume la complejidad de administrar las aplicaciones de Laravel en AWS Lambda, así como la interfaz de esas aplicaciones con colas SQS, bases de datos, clústeres Redis, networking, CloudFront CDN y más.

Excepciones mejoradas a través de Ignition

Laravel 6.0 viene con Ignition, una nueva página de excepciones de código abierto creada por Freek Van der Herten y Marcel Pociot. Ignition ofrece muchos beneficios con respecto a versiones anteriores, como un archivo mejorado de errores de Blade y manejo de números de línea, soluciones ejecutables para problemas comunes, edición de código, uso compartido de excepciones y una experiencia de usuario mejorada.

Respuestas de autorización mejoradas

En versiones anteriores de Laravel, era difícil recuperar y exponer mensajes de autorización personalizados a los usuarios finales. Esto dificultaba explicar a los usuarios finales exactamente por qué se denegó una solicitud en particular. En Laravel 6.0, ahora es mucho más fácil usar mensajes de respuesta de autorización y el nuevo método Gate::inspect. Por ejemplo, dado el siguiente método de política:

/**
* Determine si el usuario puede ver el vuelo dado. *
* 
* @param \App\User $user 
* @param \App\Flight $flight 
* @return mixed
*/
public function view(Usuario $usuario, Vuelo $vuelo) {
    return $this->deny('Explicación de la negación');
}

La respuesta y el mensaje de la política de autorización se pueden recuperar fácilmente utilizando el método Gate::inspect:

$respuesta = Gate::inspect('view', $vuelo);

if ($respuesta->allowed()) {    
    // El usuario está autorizado para ver el vuelo ...
}
if ($respuesta->denied()) {
    echo $respuesta->message();
}

Además, estos mensajes personalizados se devolverán automáticamente a su interfaz cuando use métodos auxiliares como $this->authorize o Gate::authorize de sus rutas o controladores.

Job Middleware

El Job Middleware te permite envolver lógica personalizada sobre la ejecución de los Jobs encolados, reduciendo el código repetido en los Jobs. Por ejemplo, en versiones anteriores de Laravel, podrías envolver la lógica de un Job en un callback para limitar el acceso:

/**
 * Ejecutar el trabajo.
 *
 * @return void
 */
public function handle()
{
    Redis::throttle('key')->block(0)->allow(1)->every(5)->then(function () {
        info('Se obtuvo el lock...');

        // Manejar el Job...
    }, function () {
        // No se pudo obtener el lock...

        return $this->release(5);
    });
}

En Laravel 6.0, esta lógica se puede aplicar en un middleware de trabajo, lo que le permite mantener su trabajo libre.

<?php

namespace App\Jobs\Middleware;

use Illuminate\Support\Facades\Redis;

class RateLimited
{
    /**
     * Procesar el Job encolado.
     *
     * @param  mixed  $job
     * @param  callable  $next
     * @return mixed
     */
    public function handle($job, $next)
    {
        Redis::throttle('key')
                ->block(0)->allow(1)->every(5)
                ->then(function () use ($job, $next) {
                    // Se obtuvo el lock...

                    $next($job);
                }, function () use ($job) {
                    // No se pudo obtener el lock...

                    $job->release(5);
                });
    }
}

Luego de crear un middleware, pueden adjuntarse a un Job retornandolo directamente desde el método middleware.

use App\Jobs\Middleware\RateLimited;

/**
 * Elegir que middleware aplica a este Job
 *
 * @return array
 */
public function middleware()
{
    return [new RateLimited];
}

Lazy Collections

Muchos desarrolladores ya disfrutan de los poderosos métodos de colección de Laravel. Para complementar la ya poderosa clase Collection, Laravel 6.0 presenta una colección LazyCollection, que aprovecha los generadores de PHP para permitirte trabajar con grandes sets de datos mantienendo un uso bajo de memoria.

Por ejemplo, imagine que su aplicación necesita procesar un log de varios gigabytes mientras aprovecha los métodos de Collection de Laravel para analizar los registros. En lugar de leer todo el archivo en memoria a la vez, se pueden usar LazyCollections para mantener solo una pequeña parte del archivo en la memoria en un momento dado:

use App\LogEntry;
use Illuminate\Support\LazyCollection;

LazyCollection::make(function () {
    $handle = fopen('log.txt', 'r');

    while (($line = fgets($handle)) !== false) {
        yield $line;
    }
})
->chunk(4)
->map(function ($lines) {
    return LogEntry::fromLines($lines);
})
->each(function (LogEntry $logEntry) {
    // Procesar el log...
});

O imagine que necesita recorrer 10.000 modelos Eloquent. Cuando se usan colecciones tradicionales de Laravel, todos los 10,000 modelos Eloquent deben cargarse en la memoria al mismo tiempo:

$users = App\User::all()->filter(function ($user) {
    return $user->id > 500;
});

Sin embargo, a partir de Laravel 6.0, el método cursor del QueryBuilder se ha actualizado para devolver una instancia de LazyCollection. Un modelo Eloquent cargado en la memoria a la vez. En este ejemplo, la devolución de filter no se ejecuta hasta que iteramos sobre cada usuario individualmente, lo que permite una reducción drástica en el uso de la memoria:

$users = App\User::cursor()->filter(function ($user) {
    return $user->id > 500;
});

foreach ($users as $user) {
    echo $user->id;
}

Mejoras en sub-queries de Eloquent

Laravel 6.0 presenta varias correcciones y mejoras nuevas para el soporte de subconsultas de bases de datos. Por ejemplo, imaginemos que tenemos una tabla destinations (destinos) y una tabla de flights (vuelos).

Usando la nueva funcionalidad de selección de subconsulta en Laravel 6.0, podemos seleccionar todos los destinos y el vuelo más reciente que ha llegado a ese destino utilizando una sola consulta:

return Destination::addSelect(['last_flight' => Flight::select('name')
    ->whereColumn('destination_id', 'destinations.id')
    ->orderBy('arrived_at', 'desc')
    ->limit(1)
])->get();

Además, podemos usar nuevas características de subconsulta agregadas a la función orderBy del generador de consultas. Nuevamente, esto se puede hacer mientras se ejecuta una única consulta en la base de datos:

return Destino::orderByDesc(
    Vuelo::select('arrived_at')
        ->whereColumn('destination_id', 'destinations.id')
        ->orderBy('arrived_at', 'desc')
        ->limit(1)
)->get();

Laravel UI

El scaffolding frontend que normalmente se proporciona con versiones anteriores de Laravel se ha extraído en un paquete de laravel/ui. Esto permite que el scaffolding de interfaz de usuario se desarrolle y versione por separado del framework. Como resultado de este cambio, no hay código Bootstrap o Vue presente en el scaffolding predeterminado del framework, y el comando make:auth también se ha extraído del framework.

Para restaurar el scaffolding Vue/Bootstrap tradicional presente en versiones anteriores de Laravel, hay que instalar el paquete laravel/ui y usar el comando artisan ui para instalar el scaffolding frontend:

composer require laravel/ui

php artisan ui vue --auth
]]>
<![CDATA[Telescope: debugging al estilo Laravel]]>
La pantalla inicial de Telescope

Laravel Telescope es un nuevo asistente de depuración para Laravel, escrito por Mohamed Said y Taylor Otwell. Es de código abierto, gratuito, disponible en Github. Puedes agregarlo a tus aplicaciones como una dependencia a travès de Composer. Una vez

]]>
https://blog.coffeedevs.com/telescope-debugging-al-estilo-laravel/5bd4573c24a63c71fd72750aWed, 31 Oct 2018 11:30:00 GMTTelescope: debugging al estilo Laravel
La pantalla inicial de Telescope
Telescope: debugging al estilo Laravel

Laravel Telescope es un nuevo asistente de depuración para Laravel, escrito por Mohamed Said y Taylor Otwell. Es de código abierto, gratuito, disponible en Github. Puedes agregarlo a tus aplicaciones como una dependencia a travès de Composer. Una vez instalado, puedes accederlo a través de la url /telescope.

¿Para qué sirve Telescope?

Si alguna vez usaste Clockwork o Laravel Debugbar, imaginatelos pero como una interfaz independiente, con superpoderes. Telescope está compuesto de una serie de guardianes que "observan" cada request que entra a tu aplicación, sean por HTTP, desde la línea de comandos, desde el Scheduler, o desde una queue. Estos "watchers" capturan todo tipo de información sobre los requests y la información que tienen asociada: consultas a la base de datos y su tiempo de ejecución, golpes al caché, eventos disparados, emails enviados, y mucho más. Hay distintas pestañas para cada uno de ellos.

Veamos para qué sirve cada una de las pestañas y qué nos dejan revisar. Todas muestran una lista y además permiten adentrarnos al detalle de cada uno de los ítems.

Requests

Telescope: debugging al estilo Laravel
Lista de todos los Requests entrantes

Esta pestaña nos permite ver todas las peticiones HTTP que lleguen a nuestra aplicación. Puedes inspeccionarlos y ver mucha información útil asociada.

Telescope: debugging al estilo Laravel

Cada página individual también muestra datos de otros "watchers" que están relacionados con la petición; por ejemplo, todas las bases de datos asociadas y cuanto tardaron; cual es el usuario autenticado para cada request, y mucho más.

Commands

Telescope: debugging al estilo Laravel

La pestaña de comandos muestra una lista de los comandos que se ejecutaron y sus códigos de salida. Cuando los inspeccionamos, también podemos ver los argumentos, opciones y elementos relacionados con la ejecución del mismo.

Telescope: debugging al estilo Laravel

Schedule

Telescope: debugging al estilo Laravel

Schedule muestra la lista de tareas programadas  que se han ejecutado. En la lista detallada, podemos ver la expresión cron utilizada, cuando se ejecutó, etc.

Jobs

La pestaña de Jobs nos muestra todos los trabajos que se ejecutaron o se están ejecutando. Es similar a Horizon, pero Horizon es exclusivo de Redis, y no es solo una interfaz gráfica sino que también te permite interactuar y configurar tus "queue workers". Telescope, por otro lado, simplemente te muestra información, pero funciona con todos los drivers disponibles de colas.

Telescope: debugging al estilo Laravel

En el detalle, podrás ver el nombre del trabajo, la cola en la que se ejecutó, la conexión a la base de datos que uso, el estado y cuando se disparó.

También vas a ver información como el host, el nombre completo de la clase, el número de intentos, si falló por timeout, etc.

Telescope: debugging al estilo Laravel

Los trabajos son automáticamente etiquetados con cualquier modelo de Eloquent que estén trabajando, así como el usuario si es que hay un usuario involucrado. Ítems como requests, comandos, etc. son asignados automáticamente como etiquetas al trabajo para que puedas filtrarlos en la búsqueda.

Así como con las peticiones HTTP, puedes ver toda la información relacionada con el trabajo como las consultas a base de datos ejecutadas, trabajos que se generaron  a partir de este, y cualquier log que se haya generador del mismo.

Exceptions

Telescope: debugging al estilo Laravel

Esta pestaña muestra todas las excepciones que se han generado en tu aplicación y te permite inspeccionarlas. Verás información similar a la de otras pestañas, como host, tipo, request que la generó, etiquetas, usuario autenticado, etc.

Telescope: debugging al estilo Laravel

También puedes ver la ubicación exacta en el código, resaltada, con un par de líneas por arriba y por debajo para tener un mejor contexto. Lógicamente, está el stack trace completo para que puedas revisar si es necesario.

Telescope: debugging al estilo Laravel
Telescope: debugging al estilo Laravel

También puedes conseguir un enlace al detalle de la excepción desde la petición que la generó. Esto también puede hacerse desde los detalles de otros elementos, lo que hace a Telescope muy fácil de navegar.

Si una excepción es disparada más de una vez, se empezarán a agrupar, pero igualmente puedes acceder a una en particular si necesitas más información. Esto evita que la página se inunde de una sola excepción que se dispare muy frecuentemente.

Logs

Telescope: debugging al estilo Laravel

La pestaña de logs permite ver los mensajes loggeados, su nivel de severidad, y cuando fueron generados.

Cuando entras a ver el detalle de cada ítem, puedes ver más información, incluyendo el contexto que pasaste a tus ítems como array. Esto te permite una mejor inspección del error que entrar a revisar el archivo de texto de forma manual.

Telescope: debugging al estilo Laravel

Dump screen

Telescope: debugging al estilo Laravel

Esta pestaña es el servidor de Dump que agregó la versión 5.7 de Laravel, que permite separar los llamados a dump() del flujo de nuestra aplicación. Cuando estemos en esta pestaña, todos los llamados a dump() se enviarán aquí, y cuando dejemos la pestaña volverán al flujo normal de nuestra aplicación.

Queries

Telescope: debugging al estilo Laravel

Muestra una lista de todas las consultas a base de datos, justo como lo hace Laravel Debug Bar. Cuánto tardaron, cuándo ocurrieron y si entramos al detalle, podemos ver la información asociada, la consulta completa, quién la disparó, todo correctamente formateado.

Telescope: debugging al estilo Laravel
Las consultas lentas mostrarán su duración en rojo

Puedes configurar en tu Service Provider que consultas quieres que sean marcadas como "lentas" y marcarlas de rojo en la lista. Esto permite también filtrarlas por el campo de búsqueda.

Models

Telescope: debugging al estilo Laravel

Puedes ver eventos disparados de tus modelos como creación, actualización, eliminación, los cambios realizados, etc.

Telescope: debugging al estilo Laravel

Obviamente, como en todas las pestañas, puedes ver quién generó los cambios.

Events

Telescope: debugging al estilo Laravel

Muestra una lista de todos tus eventos. Puedes ver cuantos listeners están asociados, filtrarlos por etiqueta, y ver cuando ocurrieron. Si entras al detalle también puedes ver quién lo disparó y cuáles son los listeners exactos.

Telescope: debugging al estilo Laravel

Mail

Telescope: debugging al estilo Laravel

La pestaña Mail te muestra una lista de todos los emails que enviaste, quienes los recibieron, cuando se dispararon, si están encolados o no, el asunto, y hasta puedes descargarlo como un archivo .eml y abrirlo con tu cliente de email preferido y ver como se muestra. También puedes ver una previsualización del mismo.

Telescope: debugging al estilo Laravel
Telescope: debugging al estilo Laravel

Notifications

Telescope: debugging al estilo Laravel

Muestra todas las notificaciones, de qué tipo son, cuando se enviaron, etc. Las notificaciones que sean por email se mostrarán también previsualizadas, pero no para el resto.

Telescope: debugging al estilo Laravel

Si una notificación fue encolada, puedes verla en la parte de Jobs.

Cache

Telescope: debugging al estilo Laravel

Esta pestaña muestra las interacciones con el caché, si se acertó o falló, si fue guardada en cache o eliminada del mismo, etc. También puedes ver quién lo originó.

Redis

Esta pestaña es similar a Cache, mostrando cuando se agregaron, modificaron o borraron claves de Redis.

Authenticated user

Telescope: debugging al estilo Laravel

Esto no es una pestaña pero puede aparecer en Telescope cuando alguno de sus elementos esté asociado con un usuario autenticado.

Authorization

Puedes usar una lista de emails en el Service Provider de Telescope para definir qué usuarios pueden accederlo en producción. O puedes usar el gate viewTelescope para definir si un usuario puede o no accederlo.

Filtering

En producción, puedes no querer guardar todo lo que sucede, por lo que puedes definir filtros en el Service Provider de la siguiente forma: Telescope::filter(function ($entry){})

Filtro por defecto:

function ($entry) {
    if (local) { return true; }

    return $entry->isReportableException ||
        $entry->isfailedJob() ||
        $entry->isScheduledTask() ||
        $entry->hasMonitoredTag();
}

Puedes modificar esto como tú quieras.

Monitored tags

Ve al botón de Radar y agrega una etiqueta para monitorear. Esto sirve para filtrar por etiquetas en producción.

Prune

Puedes  programar que Telescope limpie entradas antiguas, configurar una hora al día en la que se ejecute la limpieza y determinar hasta cuantas horas quieres guardar de información. También puedes activar o desactivar algunos watchers desde la configuración de Telescope (config/telescope). Incluso puedes definir un límite con la clave TELESCOPE_LIMIT (100 por defecto) que es el número máximo de entradas que Telescope guarda para cada watcher. Muchos de estos cambios son configurables por .env.

Miscellaneous

Telescope puede ser ejecutado de forma local y en producción, y viene integrado con autorización y herramientas para mantener de forma privada tus datos. Provee un acceso similar a la información desde distintos ángulos, es super configurable, y permite una búsqueda fácil y rápida a través de las etiquetas.

Es recomendable instalarlo en una base de datos separada, y también hay formas de filtrar el logging para que los datos sensibles no sean guardados.

También puedes activar el modo Oscuro utilizando Telescope::night() en tu Service Provider.

Telescope: debugging al estilo Laravel
Todo lo que tenga Dark Mode tiene mi aprobación 😍

Toda la información es almacenada en una base de datos, detrás de una interface StorageRepository, y funcionando con Redis. Pero puedes implementarlo como quieras.

Con respecto a la cantidad de información que se guarda, no es pesada ya que en producción se descartan la mayoría de los eventos, y con la limpieza programada y el límite de 100 ítems, el espacio utilizado es poco significativo.

No tiene un mayor impacto en el tiempo de arranque de Laravel, y en producción mantiene las escrituras a un mínimo. También puedes deshabilitar watchers que no requieras para reducir aún más el consumo.

]]>
<![CDATA[Laravel 5.7 - Lista de cambios en español]]>

Laravel 5.7 continua las mejoras realizadas en Laravel 5.6 introduciendo Laravel Nova, verificación opcional por email a la generación automática de autenticación, soporte para usuarios invitados en políticas y puertas de acceso, mejoras en pruebas para comandos de

]]>
https://blog.coffeedevs.com/laravel-5-7-lista-de-cambios-espanol/5b8ef66235391963c51c886cTue, 04 Sep 2018 22:17:52 GMTLaravel 5.7 - Lista de cambios en español

Laravel 5.7 continua las mejoras realizadas en Laravel 5.6 introduciendo Laravel Nova, verificación opcional por email a la generación automática de autenticación, soporte para usuarios invitados en políticas y puertas de acceso, mejoras en pruebas para comandos de consola, integración del servidor de prueba de Symfony, notificaciones localizables, y una variedad de correcciones y mejoras de usabilidad.

Laravel Nova

Laravel Nova es un panel de administración para aplicaciones Laravel. Por supuesto, la principal característica de Nova es la habilidad de administrar tus registros de base de datos a través de Eloquent. Adicionalmente, Nova ofrece soporte para filtros, lentes, acciones, acciones encoladas, métricas, autorización, herramientas personalizadas, tarjetas personalizadas, campos personzalidos y más.

Para aprender más acerca de Laravel Nova, revisa el sitio en el siguiente enlace: Laravel Nova

Email Verification

Laravel 5.7 introduce verificación por email opcional a la generación automática de autenticación incluída en el framework. Para permitir esta funcionalidad, se agregó una columna email_verified del tipo timestamp a la tabla de usuarios incluída por defecto.

Para requerir que los usuarios recién registrados validen su email, el modelo User debería marcarse con la interfaz MustVerifyEmail:

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    // ...
}

Una vez que el usuario User es marcada con la interfaz, los usuarios registrados recibirán un email que contiene un enlace de verificación firmado.
Una vez que se hace clic en el enlace, Laravel automáticamente va a guardar el tiempo actual en la base de datos y va a redirigir al usuario a una ubicación de tu elección.

Un middleware verified se agregó al Kernel HTTP de la aplicación por defecto.
Este middleware puede agregarse a las rutas que solo puedan ser accedidos por usuarios verificados.

'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

Para aprender más sobre verificación por email, revisa la documentación completa en el siguiente enlace: Verificación por email

Politicas y puertas para usuarios invitados

En versiones previas de Laravel, las puertas y políticas automaticamente retornaban falso para los usuarios no-autenticados en tu aplicación. Sin embargo, ahora puedes permitir que tus usuarios invitados pasen las validaciones de autorización declarando un "type-hint" opcional o utilizando un valor nulo por defecto en la definición del argumento del usuario:

Gate::define('update-post', function (?User $user, Post $post) {
    // ...
});

Servidor de prueba de Symfony

Laravel 5.7 ofrece integración con el servidor de prueba de Symfony, a través del paquete de Marcel Pociot. Para comenzar, utiliza el comando de Artisan:

php artisan dump-server

Una vez que el servidor está corriendo, todos los pedidos de "dump" serán mostrados en el servidor en la ventana de la consola en lugar de en tu navegador, permitiendote inspeccionar los valores sin tener que luchar con el resultado de la respuesta HTTP.

Localización de las notificaciones

Laravel ahora permite enviar notificaciones en otra localización que la actual, y permite recordar la localización cuando la notificación es encolada.

Para conseguir esto, la clase Illuminate\Notifications\Notification ahora ofrece un método locale para setear el lenguaje deseado. La aplicación cambia a este locale cuando la notificación está siendo formateada, y vuelve al locale anterior una vez que termina de formatearlo:

$user->notify((new InvoicePaid($invoice))->locale('es'));

La localización de múltiples notificaciones puede realizarse mediante la fachada Notification:

Notification::locale('es')->send($users, new InvoicePaid($invoice));

Pruebas de comandos de consola

Laravel 5.7 te permite fácilmente "mockear" información suministrada por el usuario para tus comandos de consola usando el método expectsQuestion. Además, puedes especificar un código de salida y un texto esperado como resultado del comando para validar con los métodos assertExitCode y expectsOutput. Por ejemplo, considera el siguiente comando de consola:

Artisan::command('question', function () {
    $name = $this->ask('What is your name?');

    $language = $this->choice('Which language do you program in?', [
        'PHP',
        'Ruby',
        'Python',
    ]);

    $this->line('Your name is '.$name.' and you program in '.$language.'.');
});

Puedes probar este comando con la siguiente prueba que utiliza los métodos mencionados anteriormente:

/**
 * Test a console command.
 *
 * @return void
 */
public function test_console_command()
{
    $this->artisan('laracon')
         ->expectsQuestion('What is your name?', 'Taylor Otwell')
         ->expectsQuestion('Which language do you program in?', 'PHP')
         ->expectsOutput('Your name is Taylor Otwell and you program in PHP.')
         ->assertExitCode(0);
}

Sintáxis de Callables en el generador de URLs

En lugar de aceptar solamente strings, el generador de URLs de Laravel ahora acepta sintáxis callable cuando genera URLs en sus acciones de controlador:

action([UserController::class, 'index']);

Laravel 5.7 te permite controlar cuantos enlaces adicionales mostrar a cada lado de la botonera de tu paginador. Por defecto, tres enlaces se mostraran a cada lado. Sin embargo, puedes controlar este número usando el método onEachSide:

{{ $paginator->onEachSide(5)->links() }}

Streams de lectura y escritura para el Filesystem

La integración Flysystem de Laravel ahora ofrece los métodos readStream y writeStream:

Storage::disk('s3')->writeStream(
    'remote-file.zip',
    Storage::disk('local')->readStream('local-file.zip')
);
]]>
<![CDATA[Como mejorar tu API con Resources en Laravel 5.5+]]>

Cuando construimos un API, nuestro objetivo es devolver la información de nuestra base de datos de forma fácil de interpretar por el cliente.
Hoy en día la forma más común de hacerlo es mediante un objeto o array JSON que

]]>
https://blog.coffeedevs.com/laravel-resources/5b22f07407d650425d6a52b5Wed, 20 Jun 2018 00:26:53 GMTComo mejorar tu API con Resources en Laravel 5.5+

Cuando construimos un API, nuestro objetivo es devolver la información de nuestra base de datos de forma fácil de interpretar por el cliente.
Hoy en día la forma más común de hacerlo es mediante un objeto o array JSON que representa nuestro modelo de datos de la siguiente forma:

Modelo Order:

  • id
  • buyer_id
  • seller_id
  • order_status_id,
// OrdersController

public function show(Order $order)
{
    return $order;
}
// Respuesta
{
    id: 1,
    buyer_id: 5,
    seller_id: 14,
    order_status_id: 1,
}

Esto es correcto y funciona, bien, pero podemos observar claramente como nuestra respuesta y su estructura están ligadas a la estructura de nuestra base de datos.

¿Qué pasa si realizamos un cambio en nuestro esquema de datos y, por ejemplo, queremos cambiar el nombre de algún campo? ¿O decidimos mostrar los nombres de nuestras relaciones en lugar de un ID? ¿O agregar información especial al momento de devolver el resultado, como una suma, un total o un enlace?

Este problema se debe a que nuestros clientes están interactuando directamente con nuestro esquema de datos, en lugar de con capa intermedia.

El mismo principio que rige para los Getters y Setters de Programación Orientada a Objetos rige para las respuestas de un API: separar el resultado de la implementación concreta.

Resources al rescate

Aquí es donde entran en acción los Resources, que funcionarán como intermediario entre nuestros clientes y nuestro esquema de datos.

Veamos un ejemplo:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class OrderResource extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'buyer_id' => $this->buyer->id,
            'seller_id' => $this->seller->id,
            'order_status_id' => $this->order_status->id,
        ];
    }
}

Así se ve un Resource que reemplaza al resultado actual de nuestro API.
El concepto de los Resources es simple, agregar una capa entre nuestra base de datos y nuestros clientes, ganando la flexibilidad de cambiar nuestra implementación sin que el usuario final se entere. Esto se logra con un simple array donde indicamos cómo y qué campos se van a mostrar al transformar nuestros modelos a JSON.

Para generar un recurso, Laravel nos provee el siguiente comando de Artisan:

php artisan make:resource Order

Para que nuestras respuestas pasen a través de nuestros Resource, tenemos que cambiar nuestros controladores de la siguiente manera:

// OrdersController

public function show(Order $order)
{
    return  new OrderResource($order);
}

Flexibilidad en el esquema de datos

Supongamos por un momento que decidimos cambiar el nombre de la relación seller por el de owner. Modificamos nuestra base de datos a través de una migración de la siguiente forma:

    public function up()
    {
        Schema::table('orders', function (Blueprint $table) {
            $table->renameColumn('seller_id', 'owner_id');
        });
    }

Ahora, nuestros clientes ya están programados para interactuar con la relación seller, pero gracias a nuestro Resource, ya nuestra respuesta está desacoplada de nuestras tablas:

...
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'buyer_id' => $this->buyer->id,
            'seller_id' => $this->owner->id,
            'order_status_id' => $this->order_status->id,
        ];
    }
...

Vean como incluso al cambiar una relación, la respuesta se mantiene igual, solo tuvimos que actualizar nuestro Resource para que tome los datos del modelo de la nueva relación.

Atributos extra

También podemos agregar información a nuestras respuestas que no siempre queremos que esté disponible, por ejemplo, si la información nos llega desde un usuario dueño del recurso, podemos incluir más información que no la tendría si no lo fuera utilizando el método when, que recibe una condición y un valor si la condición se cumple.

...
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'buyer_id' => $this->buyer->id,
            'seller_id' => $this->owner->id,
            'order_status_id' => $this->order_status->id,
            'total' => $this->when(auth()->user()->id == $this->owner_id, $this->order_details->sum('price')),
        ];
    }
...

También podemos pasarle un Closure como segundo argumento:

...
        'total' => $this->when(auth()->user()->id == $this->owner_id, function(){
            return $this->order_details->sum('price'));
        }
...

O agregar información que esté relacionada con el recurso pero no esté persistida en base de datos, como un enlace:

...
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'buyer_id' => $this->buyer->id,
            'seller_id' => $this->owner->id,
            'order_status_id' => $this->order_status->id,
            'link' => route('api.orders.show', $this->id),
        ];
    }
...

Resources para más de un elemento

Por ahora vimos solamente como transformar un solo objeto, pero qué pasa cuando queremos hacerlo con un conjunto, como en un index?

Con Laravel Resources necesitamos crear una collection, y para hacerlo tenemos dos formas, mediante la opción --collection o incluyendo Collection en el nombre del recurso.

php artisan make:resource Orders --collection

php artisan make:resource OrderCollection

En cualquier caso, Laravel generará un recurso nuevo que será el encargado de transformar nuestra colección de objetos al formato que nosotros querramos:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class OrderCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
        ];
    }
}

Para utilizarlo en nuestra aplicación, es igual que el Resource individual:

Route::get('/orders', function () {
    return new OrderCollection(Order::all());
});

Hay que tener en cuenta también que al trabajar con API's, es necesario paginar los resultados, por lo que podemos pasarle un Paginator al ResourceCollection en lugar de una Collection:

Route::get('/orders', function () {
    return new OrderCollection(Order::paginate());
});

El resultado se verá de la siguiente forma:

{
    "data": [
        {
            "id": 1,
            "buyer_id": 12,
            "seller_id": 3,
            "order_status_id": 1,
            "link": "http://resouces.local/orders/1
        },
        {
            "id": 2,
            "buyer_id": 15,
            "seller_id": 6,
            "order_status_id": 2,
            "link": "http://resouces.local/orders/2
        },
    ],
    "links":{
        "first": "http://resouces.local/orders/pagination?page=1",
        "last": "http://resouces.local/orders/pagination?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://resouces.local/orders/pagination",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

De esta forma podemos ver como a través de los Resources podemos transformar el resultado de nuestra API y las ventajas que esto tiene.

La opción de Laravel es una excelente forma de resolver este problema, pero también hay otras soluciones, que veremos en otros posts, con algunas ventajas sobre Resources, como por ejemplo, utiliza una misma clase tanto para un solo objeto, como para una colección, o un Paginator.

Espero que este tutorial les haya servido, dejen su opinión en sus comentarios!

]]>
<![CDATA[Cómo instalar Laravel en Windows desde cero]]>

En este tutorial veremos cómo instalar PHP, Composer y Laravel desde cero, algo que para muchos resulta ser un gran obstáculo a la hora de iniciarse en este excelente framework.

Instalando PHP

Para instalar PHP en Windows tenemos varias herramientas, cada una con distintos beneficios.
En

]]>
https://blog.coffeedevs.com/como-instalar-laravel-en-windows-desde-cero/5ae33e2526ada43e672b6a36Sun, 30 Jul 2017 21:59:24 GMTCómo instalar Laravel en Windows desde cero

En este tutorial veremos cómo instalar PHP, Composer y Laravel desde cero, algo que para muchos resulta ser un gran obstáculo a la hora de iniciarse en este excelente framework.

Instalando PHP

Para instalar PHP en Windows tenemos varias herramientas, cada una con distintos beneficios.
En una oportunidad anterior, les explicamos como instalar una de ellos: Laragon.
Es tan simple como entrar a su página, descargar el paquete WAMP (Windows, Apache, MySQL, PHP) y ejecutar el instalador.

Elegimos la ruta donde se instalará Laragon, y luego el instalador asociará PHP a nuestras variables de entorno (PATH) para que podamos usarlo desde consola.
Una de las ventajas de Laragon vs Xampp o Wamp es que instalar proyectos Laravel es muy sencillo, ya que tiene una opción específica para eso, que genera un nuevo proyecto Laravel con todos los paquetes instalados, el archivo .env creado, un Virtual Host para Apache o nginx configurado con el nombre del proyecto para que podamos acceder rápidamente en nuestro navegador (http://ejemplo.dev) y hasta puede generar una base de datos para el proyecto, todo desde un fácil acceso rápido en la barra de tareas.

Una vez instalado alguno de estos entornos, ya sea Laragon, Xampp, Wamp o cualquier otro, podremos comprobar que PHP se instaló correctamente comprobando por consola su versión:

php -v

Si PHP se instaló con éxito, debería mostrarnos algo similar a esto:

PHP 7.0.11 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.11, Copyright (c) 1999-2016, by Zend Technologies

Es importante instalar las versiones de PHP 7+, ya que las versiones 5 de PHP han quedado discontinuadas y muchos paquetes requieren de la última versión para ejecutarse.

Instalando Composer

Composer es el manejador de dependencias de PHP, es decir, se encarga de instalar las librerias que nuestros proyectos necesitan y de mantenerlas actualizadas, por lo que podemos reutilizar código de otros programadores en nuestras aplicaciones y ahorrarnos reescribir siempre las mismas funcionalidades.

PHP tuvo un antes y un después de la aparición de Composer, ya que permitió que la comunidad desarrollara paquetes especializados y que estos fueran probados por miles de aplicaciones, ahorrando tiempo a futuros programadores y mejorando la estabilidad de nuestros sistemas.

Para instalar Composer en Windows, debemos descargarlo desde su página:
https://getcomposer.org/Composer-Setup.exe
Luego, ejecutamos el instalador y seguimos sus pasos:

Cómo instalar Laravel en Windows desde cero

Una vez terminado, podemos abrir una consola de Windows y ejecutar composer. Si todo salió bien, nos mostrará una lista de comandos para ejecutar.

Cómo instalar Laravel en Windows desde cero

Más adelante veremos cómo utilizar Composer para manejar las dependencias de nuestras aplicaciones.

Ahora ya podemos pasar a crear nuestro primer proyecto!

Creando nuestro primer proyecto

Para crear un nuevo proyecto en Laravel, tenemos dos formas (tres con Laragon):

  • Utilizando composer
composer create-project --prefer-dist laravel/laravel nuevo-proyecto "5.4.*"
  • Utilizando el instalador de Laravel (más rápido)
composer global require "laravel/installer" 
laravel new nuevo-proyecto
  • Utilizando el acceso rápido de Laragon

Cómo instalar Laravel en Windows desde cero

Estos comandos generarán una carpeta nuevo-proyecto que tendrá la instalación básica del framework.

Si lo creamos con composer, tendremos que copiar el archivo .env.example a .env y generar una clave nueva para el proyecto:

copy .env.example .env
php artisan key:generate

Si lo creamos con el instalador de Laravel o de Laragon, esto se hará automáticamente.

Ahora sí, ya podemos abrir la ventana de nuestro navegador y ver el inicio de nuestra nueva app.

Entremos a http://nuevo-proyecto.dev y veremos esto:

Cómo instalar Laravel en Windows desde cero

Eso fue todo, espero que les haya servido!

]]>
<![CDATA[Crea tus propios helpers en Laravel]]>

Muchos de ustedes conocen los helpers o funciones globales de Laravel que nos permiten realizar operaciones muy comunes en nuestra aplicación de forma más sencilla, como por ejemplo el helper app para instanciar objetos desde el Service Container, request para obtener un objeto con todos los

]]>
https://blog.coffeedevs.com/crea-tus-propios-helpers-en-laravel/5ae33e2526ada43e672b6a35Sun, 23 Jul 2017 17:29:06 GMTCrea tus propios helpers en Laravel

Muchos de ustedes conocen los helpers o funciones globales de Laravel que nos permiten realizar operaciones muy comunes en nuestra aplicación de forma más sencilla, como por ejemplo el helper app para instanciar objetos desde el Service Container, request para obtener un objeto con todos los datos del request actual o route para generar links a rutas nombradas.

Si bien los helpers de Laravel son muy útiles, muchas veces vamos a necesitar crear los nuestros.
Vamos a ver cómo crearlos, dónde declararlos y de qué forma usarlos.

El archivo helpers

Declarar funciones globales en PHP es muy sencillo, es cuestión de escribirlas dentro de un archivo PHP e incluir ese archivo en cualquier lugar donde quisieramos hacer uso de ellas.

Idealmente, seguiremos la convención de usar el nombre helpers.php para el archivo, con el fin de que otros desarrolladores puedan ubicarlo fácilmente.

No hay una convención sobre la ubicación física del archivo en nuestro proyecto, pero por lo general, se agrega en la raíz del proyecto, junto a otros archivos como artisan.

Para evitar que nuestros helpers no generen conflictos con otros ya declarados, PHP nos permite hacer un chequeo de existencia de otras funciones con el mismo nombre, algo que nosotros vamos a utilizar en cada declaración:

<?php

if (!function_exists('artisan')) {
    function artisan()
    {
        return app()->make('Illuminate\Contracts\Console\Kernel');
    }
}

Una vez declaramos nuestro archivo, para que podamos utilizarlo en el resto del proyecto necesitaremos agregarlo al autoloader de Composer en nuestro composer.json:

...
    "autoload": {
        "classmap": [
            "database"
        ],
        "psr-4": {
            "App\\": "app/"
        },
        "files": [
            "helpers.php"
        ]
    },
...

Una vez hecho esto, tenemos que generar nuevamente nuestro archivo autoload.php, para esto llamamos al comando dump-autoload de composer:

composer dump-autoload

O más corto aún:

composer du

Ahora ya puedes usar tus funciones helpers en el resto de tu proyecto!

Helpers que usamos con frecuencia

Cada proyecto tiene sus propias funcionalidades que se repiten a lo largo del mismo, pero en todos los proyectos terminamos necesitando siempre estas funciones para tareas generales:

  • active_route determina si estamos en la ruta nombrada que estamos comparando, y emite un output si es así, generalmente active. Esto sirve para marcar barras de navegación con el framework Bootstrap cuando navegamos un sitio en Laravel. Podemos cambiar el output si queremos como segundo parámetro, para adaptarlo a otro framework CSS.
if (!function_exists('active_route')) {
    function active_route($route, $output = 'active')
    {
        if (Route::current()->getName() == $route)
            return $output;
    }
}
  • user es un atajo a la muy común combinación de auth()->user(). Usado en todos los proyectos.
if (!function_exists('user')) {
    /**
     * @return \Illuminate\Contracts\Auth\Authenticatable|null|App\User
     */
    function user()
    {
        return auth()->user();
    }
}
  • Algunas fachadas pueden reemplazarse por helpers si es una sintaxis que preferimos más, como Storage por storage() y DB por db():
if (!function_exists('db')) {
    function db($connection = null)
    {
        return app()->make('db')->connection($connection);
    }
}

if (!function_exists('storage')) {
    /**
     * @param null $disk
     * @return \Illuminate\Filesystem\Filesystem
     */
    function storage($disk = null)
    {
        return app()->make('filesystem')->disk($disk);
    }
}

Estas funciones son muy útiles para evitar repetir lógica en distintos lugares de nuestro código, y a la vez mantener la sintaxis sencilla y sobre todo corta y entendible, una gran ventaja de las funciones por sobre las clases utilitarias, y con soporte del IDE, ventaja frente a las fachadas.

Espero que les haya sido de utilidad!

]]>
<![CDATA[Optimizando la entrega de imágenes con Intervention (Laravel)]]>

Un problema muy común en el desarrollo de aplicaciones web es el de las imágenes generadas por el usuario. Cómo mostrarlas, en que tamaño, donde guardarlas, etc.

Hoy vamos a mostrarles una de las opciones, la que usamos nosotros en Coffeedevs, que

]]>
https://blog.coffeedevs.com/optimizando-la-entrega-de-imagenes-con-intervention-laravel/5ae33e2526ada43e672b6a33Sat, 11 Mar 2017 19:35:10 GMTOptimizando la entrega de imágenes con Intervention (Laravel)

Un problema muy común en el desarrollo de aplicaciones web es el de las imágenes generadas por el usuario. Cómo mostrarlas, en que tamaño, donde guardarlas, etc.

Hoy vamos a mostrarles una de las opciones, la que usamos nosotros en Coffeedevs, que tiene al paquete Intervention como principal actor.

Que es Intervention?

Intervention es un paquete de Composer que permite manipular imágenes: podes cambiarles el tamaño, cropearlas, aplicarles filtros, agregar marcas de agua, etc.

Está preparado para funcionar con Laravel por defecto, pero es fácil de integrar en el resto de los frameworks.

Sin embargo, lo que a nosotros nos interesa en este momento es un pequeño paquete utilitario que hace de compañero de Intervention y que se llama ImageCache.

ImageCache lo que permite es generar transformaciones para las imágenes "on the fly", es decir, a medida que son pedidas, y guardarlas en cache, lo que nos permite mostrar versiones específicas para cada una de nuestras vistas de Laravel, con sólo tener la imagen original guardada, sin necesidad de generarlas al momento de subirlas.

Guardando las imágenes en nuestra aplicación

Primero que nada, para manipular imágenes, necesitamos que nuestros usuarios suban algunas.

Lo más común, y lo que menos esfuerzo requiere, es guardarlas en la carpeta public y mostralas con asset() en nuestro template Blade.

Sin embargo, esto presenta algunos problemas de seguridad ya que los usuarios pueden subir archivos a un directorio público, por lo que la opción recomendada es guardarlas en storage/app, donde sólo la aplicación puede acceder.

Para guardarlas en storage, basta con utilizar el siguiente código:

$request->file('uploaded_file')->store('app/uploads');

Puedes leer más sobre como guardar archivos en nuestro anterior tutorial

Pero para mostrar los archivos guardados en storage, es un poco más complicado que simplemente llamar a asset():

Necesitamos una ruta dedicada en nuestra aplicación que busque las imágenes y las retorne.

Utilizando Intervention e Imagecache

Intervention va a permitirnos realizar transformaciones a nuestra imágenes a medida que nuestra aplicación las demande, a través de una URL que indique la transformación que queremos aplicar y el nombre de la imagen original:

http://intervention.dev/{ruta}/{template}/{imagen}

Ruta podría ser images, template puede ser small, medium o large, e imagen es el nombre de la imagen: p. e. avatar.png

Para poder utilizar su función de cache, necesitamos instalar ambos paquetes:

composer require intervention/image intervention/imagecache

Luego, tenemos que registrar el Service Provider en app.php:

$providers = [
...
    Intervention\Image\ImageServiceProvider::class,
...
]

Y por último, es muy importante publicar la configuración de ambos paquetes:

php artisan vendor:publish

Esto nos creará dos archivos de configuración nuevos en nuestra carpeta config:
image.php e imagecache.php.

Configurando Intervention

Intervention genera una nueva imagen a partir de la original, le aplica el filtro, la guarda en el cache, y nos la devuelve

Para que podamos mostrar las imágenes subidas por nuestros usuarios en la aplicación, Intervention necesita definir una ruta donde le pediremos las imágenes transformadas.

La misma la podemos definir en su archivo de configuración imagecache.php en la carpeta config:

<?php

return array(

    /*
    |--------------------------------------------------------------------------
    | Name of route
    |--------------------------------------------------------------------------
    |
    | Enter the routes name to enable dynamic imagecache manipulation.
    | This handle will define the first part of the URI:
    | 
    | {route}/{template}/{filename}
    | 
    | Examples: "images", "img/cache"
    |
    */
   
    'route' => 'images',

    /*
    |--------------------------------------------------------------------------
    | Storage paths
    |--------------------------------------------------------------------------
    |
    | The following paths will be searched for the image filename, submited 
    | by URI. 
    | 
    | Define as many directories as you like.
    |
    */
    
    'paths' => array(
        storage_path('app/uploads'),
    ),

    /*
    |--------------------------------------------------------------------------
    | Manipulation templates
    |--------------------------------------------------------------------------
    |
    | Here you may specify your own manipulation filter templates.
    | The keys of this array will define which templates 
    | are available in the URI:
    |
    | {route}/{template}/{filename}
    |
    | The values of this array will define which filter class
    | will be applied, by its fully qualified name.
    |
    */
   
    'templates' => array(
        'small' => 'Intervention\Image\Templates\Small',
        'medium' => 'Intervention\Image\Templates\Medium',
        'large' => 'Intervention\Image\Templates\Large',
    ),

    /*
    |--------------------------------------------------------------------------
    | Image Cache Lifetime
    |--------------------------------------------------------------------------
    |
    | Lifetime in minutes of the images handled by the imagecache route.
    |
    */
   
    'lifetime' => 43200,

);

Como podemos ver, la ruta quedó definida como images y también configuramos los directorios donde Intervention va a buscar la imagen: storage_path('app/uploads')

Ahora que ya tenemos configurado la ruta y el directorio, podemos llamar a las imágenes desde nuestro template de la siguiente forma:

<img src="{{ url('images/medium/avatar.png') }}">

Esto realiza una llamada a la ruta que definimos y el filtro que elegimos, e Intervention genera una nueva imagen a partir de la original, le aplica el filtro, la guarda en el cache, y nos la devuelve.

Realizando nuestros propios templates

El template medium, por ejemplo, resizea la imagen a 240x180, pero así como podemos usar los 3 templates base de Intervention, también podemos definir los nuestros, utilizando toda la gama de transformaciones que nos permite el paquete, como sean fit, crop, greyscale, etc.

Para definir nuestros propios templates, tenemos que crear una clase que implemente la interfaz Intervention\Image\Filters\FilterInterface.

Esto nos obliga a implementar el método applyFilter(Image $image) donde recibimos la imagen original y le aplicamos las transformaciones que querramos antes de devolverla:

class Avatar implements FilterInterface
{

    public function applyFilter(Image $image)
    {
        return $image->fit(40, 40);
    }
}

Luego, en el archivo de configuración imagecache.php agregamos al mapa de templates la entrada con nuestra nueva clase:

    'templates' => array(
        'small' => 'Intervention\Image\Templates\Small',
        'medium' => 'Intervention\Image\Templates\Medium',
        'large' => 'Intervention\Image\Templates\Large',
        'avatar' => App\Intervention\Templates\Avatar::class,
    ),

Y para utilizarlo en nuestra aplicación hacemos lo siguiente:

<img src="{{ url('images/avatar/' . $user->avatar) }}">

De esta forma podremos entregar imágenes a la medida de los requerimientos, sin necesidad de generarlas cuando se cargan, pudiendo adaptarnos fácilmente a requerimientos nuevos de tamaño, color, o proporción.

Espero que les haya sido útil!

]]>
<![CDATA[Lista de cambios en español para Laravel 5.4]]>

Lista de cambios en español para Laravel 5.4

Laravel 5.4 continua con las mejoras realizadas en Laravel 5.3, agregando soporte para Markdown en emails y notificaciones, el framework para testing Laravel Dusk, la nueva versión de Laravel Elixir, Laravel Mix, components y slots

]]>
https://blog.coffeedevs.com/lista-de-cambios-en-espanol-para-laravel-5-4/5ae33e2526ada43e672b6a34Sun, 12 Feb 2017 13:27:54 GMT

Lista de cambios en español para Laravel 5.4

Lista de cambios en español para Laravel 5.4

Laravel 5.4 continua con las mejoras realizadas en Laravel 5.3, agregando soporte para Markdown en emails y notificaciones, el framework para testing Laravel Dusk, la nueva versión de Laravel Elixir, Laravel Mix, components y slots para Blade, route model binding en los canales de broadcast, mensajes de orden superior en colecciones, eventos de Eloquent como objetos/clases, configuraciones individuales para los intentos y el tiempo de espera de los Jobs, fachadas en tiempo real, soporte mejorado para Redis Cluster, modelos personalizados para tablas pivot, middlewares para limpiar y recortar input del usuario, y más. Además, el código fuente del framework fue revisado y refactorizado para ordenarlo y mantenerlo limpio.

Esta documentación resume las más notables mejoras al framework; sin embargo, para listas de cambios más completas, se pueden encontrar en Github.

Markdown en mails y notificaciones

Los emails en Markdown nos permiten tomar ventaja de las plantillas pre-construidas y componentes de notificaciones por email en tus mailables. Ya que los mensajes están escritos en Markdown, Laravel es capaz de renderizar hermosos, responsivos templates HTML para los mensajes a la vez que automáticamente genera su contraparte en texto plano. Por ejemplo, un email Markdown puede parecerse al siguiente:


@component('mail::message')
# Pedido enviado

Su pedido ha sido enviado!

@component('mail::button', ['url' => $url])
Ver pedido
@endcomponent

Próximos pasos:

- Seguir el estado de su pedido en la web
- Pre-firmar para la entrega

Gracias,<br>
{{ config('app.name') }}
@endcomponent

Usando esta simple plantilla de Markdown, Laravel es capaz de generar un email HTML responsive y su contra-parte en texto plano:
Lista de cambios en español para Laravel 5.4

Para leer más acerca de Markdown email y notificaciones, revise la documentación completa sobre email y notificaciones.

Puedes exportar todos tus componentes de email en Markdown a tu aplicación para personalizarlos. Para exportar los componentes, utiliza el comando Artisan vendor:publish --tag=laravel-mail.

Laravel Dusk

Laravel Dusk provee una API para testing automatizados expresiva y fácil de utilizar, que interactua con el navegador. Por defecto, Dusk no requiere que instales un JDK o Selenium en tu computadora. En lugar de eso, Dusk utiliza una instalación independiente de ChromeDriver. Sin embargo, eres libre de utilizar el driver compatible con Selenium que desees.

Ya que Dusk trabaja usando un navegador real, podes fácilmente testear e interactuar con tu aplicación aunque use JavaScript.

/**
 * A basic browser test example.
 *
 * @return void
 */
public function testBasicExample()
{
    $user = factory(User::class)->create([
        'email' => '[email protected]',
    ]);

    $this->browse(function ($browser) use ($user) {
        $browser->loginAs($user)
                ->visit('/home')
                ->press('Create Playlist')
                ->whenAvailable('.playlist-modal', function ($modal) {
                    $modal->type('name', 'My Playlist')
                          ->press('Create');
                });

        $browser->waitForText('Playlist Created');
    });
}

Para más información sobre Dusk, consulta la documentación completa.

Laravel Mix

Laravel Mix es el sucesor espiritual de Elixir, y está completamente basado en Webpack en lugar de Gulp. Laravel Mix provee una API fluida para definir los pasos de Webpack para tu aplicación Laravel, utilizando varios pre-procesadores comunes de CSS y JavaScript. A través de la encadenación de métodos, puedes definir de forma fluida tu tubería de tus activos. Por ejemplo:

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css');

Componentes y slots de Blade

Componentes y slots de Blade ofrecen beneficios similares a las secciones y diseños; sin embargo, algunos pueden encontrar el modelo mental de componentes y slots más fácil de entender. Primero, imaginemos un componente "alerta" re-utilizable que queramos utilizar en el resto de nuestra aplicación:

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    {{ $slot }}
</div>

La variable {{ $slot }} va a contener lo que quieras inyectarle al componente. Ahora, para construir este componente, podemos usar la directiva de Blade @component:

@component('alert')
    <strong>Whoops!</strong> Algo salió mal!
@endcomponent

Slots nombrado te permiten proveer multiples puntos de inyección en un sólo comoponente:

<!-- /resources/views/alert.blade.php -->

<div class="alert alert-danger">
    <div class="alert-title">{{ $title }}</div>

    {{ $slot }}
</div>

Slots nombrados pueden inyectarse usando la directiva @slot. Cualquier contenido que no esté en una directiva @slot será pasada al componente en la variable $slot:

@component('alert')
    @slot('title')
        Acceso denegado
    @endslot

    No tienes permitido acceder a este recurso!
@endcomponent

Para leer más acerca de componentes y slots, consulta la documentación completa de Blade.

Model Binding para broadcasts

Al igual que las rutas HTTP, las rutas de los canales ahora toman ventaja del route model binding implícito y explícito. Por ejemplo, en lugar de recibir un string o un o un ID numérico, puedes pedir una instancia del modelo Order enviado:

use App\Order;

Broadcast::channel('order.{order}', function ($user, Order $order) {
    return $user->id === $order->user_id;
});

Para leer más acerca de route model binding en los canales de broadcast, consulta la documentación completa sobre broadcasting de eventos.

Mensajes de orden superior para colecciones

Las colecciones ahora proveen soporte para mensajes de orden superior, los cuales son atajos para realizar acciones comúnes sobre colecciones.
Los métodos de colecciones que proveen mensajes de orden superior son: contains, each, every, filter, first, map, partition, reject, sortBy, sortByDesc, and sum.

Cada función de orden superior puede ser accedida como una propiedad dinámica sobre una instancia de colección. Por ejemplo, vamos a utilizar la función de orden superior each para llamar a cada método dentro de una colección:

$users = User::where('votes', '>', 500)->get();

$users->each->markAsVip();

Así mismo, podemos utilizar la suma como mensaje de orden superior para conseguir el total del número de votos para una colección de usuarios:

$users = User::where('group', 'Development')->get();

return $users->sum->votes;

Eventos de Eloquent basados en objetos

Los manejadores de eventos de Eloquent ahora pueden ser mapeados a eventos de objetos. Esto provee una forma más intuitiva de manejar eventos de Eloquent y hace más fácil el testeo de eventos. Para empezar, definamos una propiedad $events en tu modelo Eloquent que mapea varios puntos del ciclo de vida de un modelo Eloquent a tus propias clases de eventos:


<?php

namespace App;

use App\Events\UserSaved;
use App\Events\UserDeleted;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The event map for the model.
     *
     * @var array
     */
    protected $events = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}

Tiempo de espera y número de intentos para Jobs

Previamente, las configuraciones de tiempo de espera e intentos para los trabajos eran configurados globalmente desde la consola. Sin embargo, en Laravel 5.4, estas configuraciones pueden hacerse de manera individualizada para cada trabajo, directamente en la clase del trabajo:

<?php

namespace App\Jobs;

class ProcessPodcast implements ShouldQueue
{
    /**
     * La cantidad de veces que un trabajo puede intentar de ejecutarse.
     *
     * @var int
     */
    public $tries = 5;

    /**
     * La cantidad de segundos que dura un trabajo antes de darse por fallado.
     *
     * @var int
     */
    public $timeout = 120;
}

Para más información acerca de esta configuración, revisa la documentación completa de colas.

Middleware para sanitizar las peticiones

Laravel 5.4 incluye dos nuevos middleware por defecto: TrimStrings y ConvertEmptyStringsToNull:

/**
 * The application's global HTTP middleware stack.
 *
 * These middleware are run during every request to your application.
 *
 * @var array
 */
protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

Estos middleware automáticamente van a aplicar trim() a los valores enviados por input en las peticiones y convertir cualquier string vacío '' a null. Esto ayuda a normalizar el input de cada petición entrante y no tener que preocuparnos continuamente llamando la función trim en cada ruta y controlador.

Fachadas "en tiempo real"

Previamente, sólo los servicios que vienen incluidos en Laravel exponían fachadas, que proveen un acceso rápido y breve a los sus métodos a través del contenedor de servicios. Sin embargo, en Laravel 5.4, puedes fácilmente convertir cualquier clase de tu aplicación en una fachada en tiempo real simplemente agregando como prefijo Facades a la clase importada. Por ejemplo, imagina que tu aplicación contiene una clase como la siguiente:

<?php

namespace App\Services;

class PaymentGateway
{
    protected $tax;

    /**
     * Crear una nueva instancia de PaymentGateway.
     *
     * @param  TaxCalculator  $tax
     * @return void
     */
    public function __construct(TaxCalculator $tax)
    {
        $this->tax = $tax;
    }

    /**
     * Pagar la cantidad acordada.
     *
     * @param  int  $amount
     * @return void
     */
    public function pay($amount)
    {
        // Pagar la cantidad acordada...
    }
}

Puedes también utilizar la clase como fachada de esta forma:

use Facades\ {
    App\Services\PaymentGateway
};

Route::get('/pay/{amount}', function ($amount) {
    PaymentGateway::pay($amount);
});

Obviamente, si utilizas fachadas en tiempo real de esta forma, puedes fácilmente testearlo utilizando las capacidades de mocking de fachadas de Laravel:

PaymentGateway::shouldReceive('pay')->with('100');

Modelos personalizados para las tablas pivot

En Laravel 5.3, todos los modelos de tablas pivot (o intermedias) para las relaciones belongsToMany usaban la misma instancia de modelo Pivot que viene por defecto.
En Laravel 5.4, puedes definir modelos para tus tablas pivot de forma personalizada.
Si deseas definir un modelo personalizado que representa la tabla intermedia de tu relación, usa el siguiente método mientras describes la relación:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
    /**
     * El usuario que pertenece al rol
     */
    public function users()
    {
        return $this->belongsToMany('App\User')->using('App\UserRole');
    }
}

Soporte mejorado para Redis Cluster

Anteriormente, no era posible definir conexiones Redis a hosts individuales y a clusters a la vez en la misma aplicación. En Laravel 5.4, puedes definir conexiones a múltiples hosts individuales y a múltiples clusters dentro de la misma aplicación. Para más información sobre Redis en Laravel, puedes consultar la documentación completa de Redis.

Longitud de caracteres por defecto en los String de migraciones.

Laravel 5.4 usa el set de caracteres utf8mb4 por defecto, que incluye soporte para almacenar emojis en la base de datos. Si estás actualizando tu aplicación de Laravel 5.3, no es requerido cambiar el set de caracteres.
Si elijes cambiar el set de caracteres de forma manual y estás corriendo una versión de MySQL anterior a la 5.7.7, puedes necesitar configurar manualmente la longitud por defecto de los strings generados por migraciones. Puedes configurarlo llamando al método Schema::defaultStringLength dentro de tu AppServiceProvider:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}
]]>
<![CDATA[Creando un API RESTful con Laravel 5.2 parte 2]]>

Luego de un tiempo sin escribir, voy a continuar con el tutorial acerca de REST API's con laravel.

En la primer parte pudimos llegar a listar proyectos y tareas, pero todavía no creamos el código para poder insertar, actualizar y eliminar estos recursos. Antes

]]>
https://blog.coffeedevs.com/creando-un-api-restful-con-laravel-5-2-parte-2/5ae33e2526ada43e672b6a31Sat, 03 Dec 2016 22:33:06 GMTCreando un API RESTful con Laravel 5.2 parte 2

Luego de un tiempo sin escribir, voy a continuar con el tutorial acerca de REST API's con laravel.

En la primer parte pudimos llegar a listar proyectos y tareas, pero todavía no creamos el código para poder insertar, actualizar y eliminar estos recursos. Antes de comenzar la implementación, voy a mencionar ciertas características a tener en cuenta a la hora de crear una API REST.

URI's

Debemos identificar de manera única los recursos en el servidor. Para ésto utilizaremos URI's que tendrán la siguiente forma:

{protocolo}://{dominio o hostname}[:puerto (opcional)]/{ruta del recurso}?{consulta de filtrado}

En la parte 1 del tutorial usamos http://localhost/projects para obtener el listado del proyecto. Como verán respetamos la forma mencionada arriba.
Generalmente se recomienda utilizar como nombre del recurso un sustantivo en plurar. La idea de esto es que sea lo mas simple y uniforme dentro de lo posible.

Verbos HTTP

Los verbos HTTP mas comunes son:

GET: Para consultar y leer recursos.
POST: Para crear recursos.
PUT: Para editar recursos.
DELETE: Para eliminar recursos.
PATCH: Para editar partes concretas de un recurso.

Manos a la obra

Sabiendo ésto, vamos a describir los diferentes endpoints que va a tener nuestro Web Service. Si nos ubicamos en el archivo de rutas, vamos a ver que utilizamos las rutas preparadas para RESTful, osea que tenemos los siguientes endpoints:

Para proyectos

GET /projects
GET /projects/{id}
POST /projects
PUT /projects/{id}
DELETE /projects/{id}

Para tareas

GET /projects/{projectId}/tasks
GET /projects/{projectId}/tasks/{taskId}
POST /projects/{projectId}/tasks
PUT /projects/{projectId}/tasks/{taskId}
DELETE /projects/{projectId}/tasks/{taskId}

Completemos los controllers con los métodos mencionados.

<?php
// app/Http/Controllers/ProjectsController.php

namespace App\Http\Controllers;

use App\Project;
use App\Http\Requests;
use Illuminate\Support\Facades\Input;

class ProjectsController extends Controller
{
    public function index()
    {
        return Project::all();
    }

    public function store()
    {
        return Project::create(Input::all());
    }


    public function show($id)
    {
        return Project::findOrFail($id);
    }


    public function update($projectId)
    {
        Project::findOrFail($projectId)->update(Input::all());
    }


    public function destroy($id)
    {
        Project::findOrFail($id)->delete();
    }
}

Como podemos observar, los métodos que tiene el controlador concuerdan con los descritos en las rutas. Cuando creamos un recurso, se llamara al método store(), cuando queremos un recurso en concreto llamamos a show($id), cuando queremos actualizar llamamos a updtate($id) y cuando queremos eliminar llamamos al método destroy($id). A la hora de responder, estamos haciéndolo de la forma mas sencilla posible. Aprovechamos el código de estado propio del protocolo HTTP para indicar si fue exitoso o que pasó en el request, y cuando hace falta devolvemos algo que nos sirva. En el caso del store(), además de crear el recurso lo devolvemos, ésto le va a permitir al cliente evitar un request para saber el Id del nuevo recurso.

Por otro lado, el controlador de tareas nos va a quedar así:

<?php
// app/Http/Controllers/ProjectTasksController.php

namespace App\Http\Controllers;

use App\Project;
use App\Task;
use App\Http\Requests;
use Illuminate\Support\Facades\Input;

class ProjectTasksController extends Controller
{
    public function index($projectId)
    {
        return Task::where('project_id',$projectId)->get();
    }

    public function store($projectId)
    {
        $project = Project::findOrFail($projectId);
        $input = Input::all();
        $input['project_id'] = $project->id;
        return Task::create($input);
    }

    public function show($projectId,$taskId)
    {
        return Task::findOrFail($taskId);
    }

    public function update($projectId, $taskId)
    {
        Task::findOrFail($taskId)->update(Input::all());
    }

    public function destroy($projectId, $taskId)
    {
        Task::findOrFail($taskId)->delete();
    }
}

Muy similar al anterior, pero al tener una relación con los proyectos, se debe indicar a que proyecto está asociada la tarea.

Antes de comenzara usar el API debemos tener en cuenta que en laravel 5.2 todas las rutas que ubiquemos en app/Http/routes.php estarán bajo el middleware group "web". Esto quiere decir que tendrá asociado el middleware VerifyCsrfToken, el cuál nos pedirá que enviemos un token en las peticiones que no son GET. Este problema se puede solucionar de varias maneras. Se podría comentar la línea donde se incluye.

 protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            // \App\Http\Middleware\VerifyCsrfToken::class,
        ],

        'api' => [
            'throttle:60,1',
        ],
    ];

Otra opción podría ser crear un archivo de rutas para las rutas del api. Como se usa en laravel 5.3, podríamos crear el archivo routes/api.php y asociarlo en el service provider.

<?php
// app/Providers/RouteServiceProvider.php

namespace App\Providers;

use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * This namespace is applied to your controller routes.
     *
     * In addition, it is set as the URL generator's root namespace.
     *
     * @var string
     */
    protected $namespace = 'App\Http\Controllers';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    public function boot(Router $router)
    {
        //

        parent::boot($router);
    }

    /**
     * Define the routes for the application.
     *
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    public function map(Router $router)
    {
        
        $this->mapApiRoutes($router);

        //
    }

    /**
     * Define the "web" routes for the application.
     *
     * These routes all receive session state, CSRF protection, etc.
     *
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    protected function mapWebRoutes(Router $router)
    {
        $router->group([
            'namespace' => $this->namespace, 'middleware' => 'web',
        ], function ($router) {
            require app_path('Http/routes.php');
        });
    }

    protected function mapApiRoutes(Router $router)
    {
        $router->group([
            'namespace' => $this->namespace, 'middleware' => 'api',
        ], function ($router) {
            require base_path('routes/api.php');
        });
    }
}

Con esto ya podremos utilizar esta API REST muy sencilla. Podrían probarla utilizando algún cliente como Postman o Advanced REST client. Ambos se pueden descargar desde las apps de Chrome.

Creando un API RESTful con Laravel 5.2 parte 2
En esta imagen podemos ver como realizamos una petición usando el verbo POST, donde creamos un nuevo proyecto. Recuerden enviar los datos utilizando x-www-form-urlencoded.

Con esto finalizamos el tutorial de REST en laravel 5.2. En futuros tutoriales vamos a hablar con mayor detalle del uso de REST API's y las mejores prácticas, validaciones, paginación, transformers, documentación y otros elementos que harán nuestras API's más robustas y sencillas de consumir.

Espero que les haya sido útil, y no duden en dejarnos sus consultas y comentarios debajo!

Gracias por leernos!

Encontranos en @coffeedevs

]]>
<![CDATA[Laravel Forge, servidores administrados para PHP]]>

En otras ocasiones hemos hablado de la importancia de nuestro entorno de producción y las ventajas de utilizar Git y VPS para el deployment de nuestras aplicaciones.

Pero, tener tu propio servidor VPS puede consumir bastante tiempo y hay mucho para aprender si tu conocimiento no involucra servidores,

]]>
https://blog.coffeedevs.com/laravel-forge-servidores-administrados-para-php/5ae33e2526ada43e672b6a30Fri, 18 Nov 2016 20:14:00 GMTLaravel Forge, servidores administrados para PHP

En otras ocasiones hemos hablado de la importancia de nuestro entorno de producción y las ventajas de utilizar Git y VPS para el deployment de nuestras aplicaciones.

Pero, tener tu propio servidor VPS puede consumir bastante tiempo y hay mucho para aprender si tu conocimiento no involucra servidores, servidores web o terminales linux, o quizá simplemente quieres algo más parecido a Heroku, donde puedes deployear tu aplicación a producción solo con un git push y a la vez no perder el control de tu entorno.

Pues bien, la solución existe y se llama Laravel Forge.

Qué es Laravel Forge?

Forge es una aplicación web desarrollada por Taylor Otwell, creador de Laravel.

Esta herramienta se conecta a nuestro proveedor de infraestructura, sea Linode, DigitalOcean, Amazon Web Services u otro, y nos permite crear nuevos servidores
con PHP 7, Nginx, MySql o MariaDB, Postgres y Redis por defecto, sin que nosotros tengamos que instalar nada manualmente.

Si alguna vez tuvieron que configurar un certificado SSL, saben lo engorroso (pero necesario) que es todo eso, desde configurar el servidor web hasta generar el certificado y agregarlo a nuestro servidor.

Con Forge, díganle adiós a todo eso porque provee una opción muy sencilla de instalación y renovación de certificados SSL, incluyendo https://letsencrypt.org/, el proveedor gratuito de certificados!

Y además de todo eso, los proyectos que subamos a Forge, con un simple click podemos configurarlos como auto-deploy, lo que significa que cada vez que hagamos un git push, Forge hara un git pull en el servidor que corresponda, correrá composer y php artisan migrate y sin realizar nada, ya tendremos nuestro sitio en producción.
El tiempo que nos ahorra esta feature para iterar cambios en nuestro día a día hace que el servicio se pague solo, y que si nunca trabajaron con este tipo de workflows, queden asombrados con la rapidez con la que pueden desplegar cambios.

Y todo esto no es solo para Laravel, Forge también nos permite subir proyectos PHP tradicionales, Wordpress, Symfony o páginas simples sin backend, manteniendo los mismos features de instalación rápida de SSL y auto-deploy.

Si todavía no los convencí, pueden probarlo gratis por 5 días y jugar un poco.

Nosotros ya no podemos vivir sin Forge!

Espero que les haya sido útil, y no olviden dejarnos sus dudas o comentarios debajo!

]]>
<![CDATA[Laravel Passport, o como crear tu propio servidor OAuth 2]]>

Laravel 5.3 vino cargado de excelentes nuevas features, entre las cuales están:

Los primeros tres ya los hemos cubierto en otros posts de este mismo blog, y hoy paso a traerles un nuevo integrante,

]]>
https://blog.coffeedevs.com/laravel-passport-o-como-crear-tu-propio-servidor-oauth-2/5ae33e2526ada43e672b6a2fWed, 16 Nov 2016 23:05:59 GMTLaravel Passport, o como crear tu propio servidor OAuth 2

Laravel 5.3 vino cargado de excelentes nuevas features, entre las cuales están:

Los primeros tres ya los hemos cubierto en otros posts de este mismo blog, y hoy paso a traerles un nuevo integrante, Laravel Passport.

Qué es Laravel Passport?

Passport es un paquete oficial de Laravel para integrar fácilmente un servidor OAuth 2 a tu aplicación de Laravel.

Tradicionalmente, instalar y configurar un paquete de OAuth 2, o implementarlo manualmente, ha sido un verdadero dolor de cabeza, pero por suerte, Taylor Otwell, creador de Laravel, armó para la versión 5.3, un paquete independiente que permite integrar rápidamente las funcionalidades de OAuth en nuestra aplicación.

Integrando Laravel Passport a nuestra aplicación

Para empezar, Passport es un paquete externo al core del framework, por lo que debemos requerirlo con Composer:

composer require laravel/passport

Una vez que terminó de instalarse, podemos agregarlo a nuestro archivo app.php como un ServiceProvider:

Laravel\Passport\PassportServiceProvider::class,

Ahora ya podremos realizar la migración, que contiene las tablas necesarias para generar clientes, tokens y demás.

php artisan migrate

Luego, tenemos que utilizar el siguiente comando para que Passport genere dos claves RSA que utilizará para encriptar nuestros tokens, y además creará dos clientes nuevos, uno para Personal Access Tokens y otro para Password Grants.

php artisan passport:install

Si vamos a crear tokens para aplicaciones propias (first-party), hasta aquí está bien, pero si queremos realizar algo parecido a Github, donde nuestros usuarios pueden registrar aplicaciones y que esas aplicaciones se conecten con la nuestra, necesitamos generar clientes nuevos asociados con esos usuarios.

Para que los usuarios de tu aplicación puedan solicitar tokens, tienes que agregarle el Trait HasApiTokens al Model para que quede así:

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;
}

Después, tenemos que agregar a nuestro AuthServiceProvider el siguiente método para registrar las rutas de Passport:

    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }

Por último, tenemos que determinar en nuestro archivo session.php que utilizaremos el driver de Passport para las sesiones de nuestro API:

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],

Con eso ya queda configurado nuestro servidor para recibir peticiones de acceso con OAuth y entregar tokens de acceso.

Passport además propone una implementación frontend en Vue.js con componentes que permiten visualizar, consumir y generar clientes OAuth.
Puede utilizarse o pueden crear sus propias implementaciones que choquen contra el backend.

Muy lindo todo, pero para qué?

Ahora que tenemos integrado nuestro servidor OAuth en nuestra aplicación, que conseguimos?

  • Permitimos a otras aplicaciones que se integren la nuestra de forma segura.

  • Podemos desarrollar aplicaciones nuestras que se integren con nuestra versión actual, manteniendo un mismo punto de acceso (nuestro API) para todas, y que manejen de forma sencilla y segura la autenticación.

Un saludo y espero que les haya resultado de utilidad!

]]>
<![CDATA[4 paquetes para mejorar tu experiencia con Laravel]]>

Hoy les traemos 4 paquetes que utilizamos en nuestros proyectos Laravel que quizá no conozcan pero que resultan muy útiles para el día a día.

Prestisimo

Prestissimo es un paquete para Composer (el manejador de dependencias de PHP) que permite paralelizar las descargas, lo

]]>
https://blog.coffeedevs.com/4-paquetes-para-mejorar-tu-experiencia-con-laravel/5ae33e2526ada43e672b6a2eWed, 02 Nov 2016 11:56:28 GMT4 paquetes para mejorar tu experiencia con Laravel

Hoy les traemos 4 paquetes que utilizamos en nuestros proyectos Laravel que quizá no conozcan pero que resultan muy útiles para el día a día.

Prestisimo

Prestissimo es un paquete para Composer (el manejador de dependencias de PHP) que permite paralelizar las descargas, lo que agiliza muchísimo la instalación de paquetes, sobretodo en proyectos grandes como Laravel.

Simplemente tienen que instalar prestissimo como dependencia global de Composer y listo, cada vez que utilizen el comando composer install o update, Prestissimo actuará en su lugar y veras como los tiempos de instalación bajan considerablemente.

Prestissimo es la versión de Composer del próximo paquete que mejorará tu vida como desarrollador:

Yarn

Yarn es un manejador de dependencias para módulos Javascript escrito y mantenido por Facebook.

Yarn funciona como npm, utilizando el mismo repositorio de paquetes, pero descarga los paquetes de forma paralela, igual que Prestissimo, por lo que reduce el tiempo de instalación total. Además, Yarn guarda en caché todos los paquetes que descarga, lo que permite que puedas instalarlos de nuevo aunque no tengas conexión, y además son mucho más rápidos de instalar que si los tuvieras que descargar de nuevo!

Y por último y no menos importante, Yarn introduce a las dependencias de Javascript un archivo .lock igual que en Composer que una vez en el sistema de control de versiones (git o similar), hará que todas las instalaciones de esos paquetes en distintos ambientes de desarrollo sean siempre iguales, con la enorme ventaja de que todos los developers tendrán el mismo conjunto de modulos de node, evitándonos el problema de eliminar la carpeta node_modules y reinstalar cada vez que teníamos un problema con npm para actualizar dependencias o versiones de paquetes nuevos.

Laravel Debugbar

Laravel Debugbar es un paquete para Laravel para ayudar a resolver problemas en nuestras aplicaciones.

Se inyecta dinámicamente en nuestra aplicación y nos va mostrando un montón de información útil sobre la misma:

  • Qué excepciones se produjeron y en que parte del código
  • Cuántas consultas estamos realizando para renderizar una vista en particular.
  • Cuánto tiempo tardó Laravel en generar el resultado.
  • Cuáles templates de Blade se utilizaron para renderizar la vista.
  • El estado de la sesión y del request.

Y muchos otros datos más, que nos permiten ir debuggeando nuestra aplicación y mejorando los tiempos de respuesta de la misma.

Indispensable!

Laravel-Lang

Laravel-Lang es un paquete de idiomas para Laravel, con los archivos de Laravel en distintos idiomas listos para que podamos utilizar en nuestras aplicaciones.
Esto incluye los mensajes de error de validación de formularios, de autenticación, de paginación y los mensajes que se muestran a la hora de recuperar/renovar la contraseña.

Para los que trabajamos con clientes latinoamericanos o que utilizan otro idioma distinto al inglés por defecto, este paquete es una bendición y nos ahorra muchísimo tiempo.

Eso fue todo, espero que les haya sido útil.

Dejen sus comentarios con los paquetes que a ustedes les resultaron útiles!

]]>