Skip to content

Instantly share code, notes, and snippets.

@yanker
Last active September 12, 2024 13:35
Show Gist options
  • Select an option

  • Save yanker/82e5b33d59dc04627883d9d1f8c96580 to your computer and use it in GitHub Desktop.

Select an option

Save yanker/82e5b33d59dc04627883d9d1f8c96580 to your computer and use it in GitHub Desktop.

NOTES OF LARAVEL 11

ROUTES

Las rutas se guardan en routes/web.php y se debe definir el tipo de peticion

  • GET
  • POST
  • PUT
  • PATCH
Route::get('/test/{id}/{category?}', function ($id, $category = null) {
    //return "hola Alex este es el post" . request('id');
    return ($category) ? "hola Alex este es el post {$id} y la categoria es {$category}" : "hola Alex este es el post {$id}";
});

// Language Translation
Route::get('index/{locale}', [App\Http\Controllers\HomeController::class, 'lang']);

Route::get('/', [App\Http\Controllers\HomeController::class, 'root'])->name('root');

ROUTES CON Y SIN NOMBRE

Contexto del Ejemplo

Supongamos que estás desarrollando una aplicación de administración de productos. Tienes un controlador llamado ProductController que maneja las operaciones relacionadas con los productos, como listar todos los productos, mostrar un producto específico, crear, editar y eliminar productos.

Ejemplo Explicado

Aquí tienes una ruta para listar todos los productos y una para mostrar un producto específico por su ID:

// Ruta para listar todos los productos
Route::get('/products', [ProductController::class, 'index'])->name('products.index');

// Ruta para mostrar un producto específico
Route::get('/products/{id}', [ProductController::class, 'show'])->name('products.show');

Detalles del Ejemplo

  1. Ruta para Listar Productos:

    Route::get('/products', [ProductController::class, 'index'])->name('products.index');
    • URL: La ruta responde a una solicitud HTTP GET en la URL /products.
    • Controlador y Método: Está asociado al método index del ProductController, que se encarga de listar todos los productos.
    • Nombre de la Ruta: Se le asigna el nombre 'products.index', lo que permite referirse a esta ruta en otras partes de la aplicación usando ese nombre en lugar de la URL directa.

    Ejemplo de uso:

    // Generar la URL para listar productos
    $url = route('products.index'); // Resultado: "/products"
    
    // Redireccionar a la página de productos
    return redirect()->route('products.index');
  2. Ruta para Mostrar un Producto Específico:

    Route::get('/products/{id}', [ProductController::class, 'show'])->name('products.show');
    • URL: La ruta responde a una solicitud HTTP GET en la URL /products/{id}, donde {id} es un parámetro dinámico que representa el ID del producto.
    • Controlador y Método: Está asociado al método show del ProductController, que se encarga de mostrar los detalles de un producto específico.
    • Nombre de la Ruta: Se le asigna el nombre 'products.show'.

    Ejemplo de uso:

    // Generar la URL para mostrar un producto con ID 5
    $url = route('products.show', ['id' => 5]); // Resultado: "/products/5"
    
    // Redireccionar a la página del producto con ID 5
    return redirect()->route('products.show', ['id' => 5]);

Beneficios de Usar Nombres de Ruta

  1. Mantenibilidad: Si cambias la URL de la ruta, no necesitas actualizar todos los lugares donde se usa la ruta. Solo cambias la URL en la definición de la ruta.
  2. Claridad: Usar nombres de rutas hace que el código sea más claro y fácil de leer, ya que indica la intención del código.
  3. Conveniencia: Generar URLs y redirecciones es más sencillo y menos propenso a errores cuando se usan nombres de rutas.

Resumen

  • Con name('products.index'): Puedes referirte a la ruta que lista todos los productos usando 'products.index'.
  • Con name('products.show'): Puedes referirte a la ruta que muestra un producto específico usando 'products.show'.

Esto ayuda a que el código sea más limpio y fácil de mantener.

CONTROLLERS

En vez de hacer los procesos en las rutas, esto lo hacemos con los controladores

php artisan make:controller ItemsController

Método _Invoke

Sí, el método __invoke sigue utilizándose en Laravel 11. En Laravel, el método __invoke es una característica de PHP que permite a los objetos ser llamados como si fueran funciones. Esto es útil para crear controladores de una sola acción, middleware, y otros componentes que necesitan comportarse como funciones pero aún así mantener la flexibilidad de las clases.

Por ejemplo, en Laravel puedes definir un controlador de una sola acción así:

namespace App\Http\Controllers;

class MyController
{
    public function __invoke()
    {
        return 'Hello, world!';
    }
}

Y luego lo registras en las rutas como una ruta de controlador de una sola acción:

use App\Http\Controllers\MyController;

Route::get('/hello', MyController::class);

En este ejemplo, cuando se hace una solicitud a /hello, Laravel invoca el método __invoke de MyController.

Laravel sigue soportando este patrón en versiones recientes como Laravel 11, ya que es una técnica conveniente y elegante para manejar rutas o middleware de una sola acción.

Creación de Vista con PHP Artisan

php artisan make:view \_test/create

Para crear una vista utilizamos esta nomenclatura si queremos meterlo o crear un directorio, ponemos le nombre del directorio seguido del nombre de la vista.

NOTA: utilizar el nombre de la vista con el nombre del método nos ayudará a tener mejor organizado todo

Envio de variables a las vistas

public function show($id)
{
    return view(
        '_test.show',
        ['id' =>  $id]
    );
}
esto de aqui es igual a esto
    public function show($id)
{
    return view('_test.show',compact($id));
}

El capitulo 05 explica los componentes

Generación de Componentes

php artisan make:component <nombre componente>

Esto lo que hace es crear 2 archivos por un lado el componente en resources/views/components para ser reutilizado y por otro lado en App/View/Components para poder crear un clase que maneje dicho controlador

Para llamar a un componente desde una plantilla blade utilziamos la zintaxis (desde Blade 11) ejemplo

 <x-alert type="info" title="¡Error!" subtitle="Algo salió mal. Por favor, intenta de nuevo.">
</x-alert>

e indicamos los atributos

La expresión que mencionas:

class="alert {{ $attributes->merge(['class' => $alertClass]) }}"

es utilizada en Laravel Blade para asignar dinámicamente clases CSS a un elemento HTML. Vamos a desglosarla:

Desglose de la Expresión

  1. class="alert":
    Esta parte establece una clase CSS fija, en este caso, alert, que siempre estará presente en el elemento HTML.

  2. {{ ... }}:
    Los dobles corchetes {{ }} son utilizados en Blade para imprimir el valor de una variable o una expresión PHP dentro del HTML. Todo lo que está dentro de los corchetes se evalúa y se inserta en el lugar correspondiente.

  3. $attributes->merge(['class' => $alertClass]):

    • $attributes: Es una variable especial disponible en los componentes de Blade que contiene todos los atributos HTML adicionales que puedan pasarse al componente cuando se llama.
    • merge(['class' => $alertClass]): Esta función combina cualquier clase adicional que se pase a través de $attributes con la clase dinámica alertClass, que normalmente depende de alguna lógica en la clase del componente.

Ejemplo en Contexto

Supongamos que tienes un componente Alert que espera un tipo de mensaje (danger, warning, success, etc.) y, en base a eso, define una clase CSS específica:

alert.blade.php:

<div class="alert {{ $attributes->merge(['class' => $alertClass]) }}">
    {{ $slot }}
</div>

Llamada del Componente

Luego, cuando llames al componente en una vista, podrías hacerlo así:

<x-alert type="danger" class="extra-class">
    Este es un mensaje de peligro.
</x-alert>

¿Qué Sucede?

  • $alertClass: Podría ser algo como alert-danger, dependiendo del valor de type en el componente.
  • $attributes->merge(['class' => $alertClass]): Combina extra-class (pasada en el llamado) con alert-danger, resultando en algo como alert alert-danger extra-class.

Resultado Final

El HTML generado sería algo como:

<div class="alert alert-danger extra-class">Este es un mensaje de peligro.</div>

Esto permite que las clases CSS sean flexibles y se puedan combinar de manera dinámica según el contexto en el que se utilice el componente.

Layouts

Creamos una plantilla y ponemos esta etiqueta para decirle que el contenido es variable

@yield('content')

Desde la vista extendemos

@extends('layouts.nombre-plantilla)

y para meter contenido en la plantilla deberemos llamar a la directiva

@section('content)
contenido que será renderizado en la plantilla
@endsection

Migraciones

// Ejecuta las migraciones
php artisan migrate

// Deshace migraciones
php artisan migrate:rollback

// Hace todos los down y luego todos los up de las migraciones, pero es un método destructivo porque elimina los registros
php artisan migration:refresh

// Para crear tablas. te genera la estructura base para crear una tabla
php artisan make:migration create\_<nombre_migracion>\_table

// Crear migración
php artisan make:migration <nombre_migracion>

Update Table

// Craar update de una migración
php artisan make:migration add*<nombre>\_to*<nombretbla>\_table

// Ejemplo
php artisan make:migration add_new_to_sys_items_table

Esta forma no es agresiva ya que no elimina datos

Modelos con ELOQUENT

// Crear Modelo
php artisan make:model Items

Conveciones de modelos: Los modelos deben ser en singular y la tabla de la DB en plural asi no hará falta crear la variable protected $table=<nombretabla> porque tomará como base el nombre y el plural en la base de datos, ejemplo

Si tenemos una tabla llamada sys_items y el modelo se llama SysItem no hará falta indicar la tabla pero por ejemplo si hacemos lo mismo con la tabla sys_familys, dará un error porque ELOQUENT/LARAVEL buscará la tabla sys_families

Route::get('/prueba', function () {

    $fam = SysItem::find(1);
    $fam->title = 'Prueba3333';
    //$fam->type = 'Casetas';
    $fam->active = 1;
    $fam->save();

    return $fam;

});

Mutadores y Accesores

Esto es para normalizar, prevenir y validar los datos de entrada en los formularios

protected function title(): Attribute
{

        return Attribute::make(
            // Mutador
            set: fn($value) => strtoupper($value),

            // Accesor
            get: fn($value) => (
                strtolower($value) . 'hola'
            ),
        );
        // return Attribute::make(
        //     set: function($value){
        //         return strtoupper($value);
        //     }
        // );
    }

    protected function description(): Attribute
    {


        return Attribute::make(
            set: fn($value) => strtolower($value),
        );

SEEDERS

Están dentro de la carpeta /database.

Sirve para insertar datos de ejemplo o sistema de datos base

// Ejecutar los seeder
php artisan db:seed

// Elimina/Crea las tablas y ejecuta los seeders
php artisan migrate:fresh -- seed

// Para crear un SEEDER debemos hacer
php artisan make:seeder <NombreSeeder>
php artisan make:seeder FamilysSeed

FACTORIES

Están dentro de la carpeta /database y sirve para crear datos de ejemplo

// Crear un seeder
php artisan make:factory <NombremodeloFactory>

Y esto se pone en el seeder pra ejecutarlo
SysFamily::factory(10)->create();
<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SysFamily>
 */
class SysFamilyFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            //
            'title' => $this->faker->sentence(),
            'type' => $this->faker->randomElement(['Casetas', 'Jardinería', 'Maquinaria']),
            'active' => $this->faker->randomElement([1, 0]),
        ];
    }
}

ROUTES

Route Resources

El comando php artisan route:list o php artisan r:l --> Lo que hace es listar todas las rutas que tenemos definidas en nuestro archivo La ruta resource lo que hace es crear el listado de rutas en 1 sola linea, por ejemplo todas estas lineas de rutas puedes ser sustituidas por una sola Ejemplo:

// Familias
Route::get('/familias/listar', [FamilyController::class, 'index'])->name('familys.list');
Route::get('/familias/detalles/{id}', [FamilyController::class, 'show'])->name('familys.details');
Route::get('/familias/crear', [FamilyController::class, 'create'])->name('familys.create');
Route::post('/familias/crear', [FamilyController::class, 'store'])->name('familys.store');
Route::get('/familias/editar/{id}', [FamilyController::class, 'edit'])->name('familys.edit');
Route::post('/familias/editar/{id}', [FamilyController::class, 'update'])->name('familys.update');
Route::get('/familias/eliminar/{id}', [FamilyController::class, 'delete'])->name('familys.delete');
Route::resource ('familias',FamilyController::class);

Esto creará todas las rutas, pero sino queremos que no se cree alguna ruta tan solo debemos añadir esto

Route::resource ('familias',FamilyController::class)->except(['destroy','edit']);

O solo querememos que nos cree unas en especifico

Route::resource ('familias',FamilyController::class)->only(['create','update']);

Hay un total de 7 rutas para hacer el CRUD

Además podemos ver con que nombre se nombrarán nuestras rutas.

Route::resource ('familias',FamilyController::class)->only(['create','update'])->names('post');

También puedo especificar parametros en esta ruta de recurso

Route::resource('familias',FamilyController::class)
->only(['create','update'])
->parameters(['familia'=>'family'])
->names('post');

Esto lo que hace es cambiar el nomnbre del parametro a recibir de familias por family

En cuanto a las rutas de API tan solo tienen 5 métodos de CRUD

Route::apiResource('familias',FamilyController::class)

Routes Model Binding

Las rutas de modelo lo que hace es simplificar el código en blade podemos ir a un registro de la siguiente manera

// Tan solo indicando el objecto $post, LARAVEL ya sabe que debe utilizar la ID no hace falta poner $post->id
{{ route('familys.edit',$post) }}

En cuanto al controlador hacemos un cambio para ahorrar 1 linea pasamos de esto

    public function show($id)
    {
        $family = SysFamily::find($id);

        return response()->json($family);
    }

a

    public function show(SysFamily $id)
    {
        //$family = SysFamily::find($id);

        return response()->json($family);
    }

Indicando solo en el controlador el Modelo a utilizar, y ya sabe LARAVEL que debe utilizar ID

Ahora bien, si queremos que se utilice otro tipo de valor que no sea el ID deberemos ir al método y crear un método public para decile que utilice otro valor

public function getRouteKeyName(){

    return 'slug';
}

ASIGNACIÓN MASIVA

    $family = new SysFamily();
    $family->title = $request->title;
    $family->type = $request->type;
    $family->active = $request->active;
    $family->save();

esto podriamos conseguir poner asi

    Sysamily::create([
    $family->title = $request->title;
    $family->type = $request->type;
    $family->active = $request->active;
    ]);

y esto otro podriamos resumirlo a, pero esto es alo inseguro porque pueden editarnos el formulario y meterse mal todo.

    SysFamily::create($request->all());

Para evitar eso debemos hacer esto, deberemos ir al controlador y crear una propiedad protegida con los nombres los campos que podrán usarse para asignación masiva

    protected $fillable = ['title', 'type', 'description', 'active'];

También podemos hacer lo contrario, podemos poner que campos NO queremos que se guarden

    protected $guarded = ['active'];

Si queremos usar asignación masiva en el método update podremos hacerlo de la siguiente manera

    $sysFamily->update($request->all);

VALIDACIONES

Las validaciones de las entradas de formulario se deben hacer en el método store, y es asi

// Validaciones en la creación
public function store (Request $request){
    $errors = $request->validate([
        'title' => 'required|min:5|max:10', // Forma más corriente
        'slug' => ['required','min:5','max:10'], // Forma más compleja
        'token' => 'required|unique:SysFamily',
    ]);
}

// Validaciones en la edición
public function edit (Request $request){
    $errors = $request->validate([
        'title' => 'required|min:5|max:10', // Forma más corriente
        'slug' => ['required','min:5','max:10'], // Forma más compleja
        'token' => 'required|unique:SysFamily,token,{$family->id}', // Con esto conseguimos que excluya el registro que estamos editando
    ]);
}

Además en la plantilla de Blade podemos agregar un div que nos muestre los errores del formulario

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

Además para no perder los datos que no se han validado en ese formulario en el campo debemos poner en el campo value esto

{{old('title')}}

Nota si queremos hacerlo en el formulario de edición debemos hacerlo asi para actualizar los cambios

{{old('title',$family->title)}}

Para mostrar el mensaje debajo del campo usamos esto

<form action="{{ route('ruta.de.envio') }}" method="POST">
    @csrf

    <!-- Campo para el nombre -->
    <div class="form-group">
        <label for="name">Nombre</label>
        <input type="text" name="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}">

        <!-- Mostrar el error del campo "name" -->
        @error('name')
            <div class="invalid-feedback">
                {{ $message }}
            </div>
        @enderror
    </div>
</form>

Para ver todas las reglas de validación podemos ir a: https://laravel.com/docs/11.x/validation#available-validation-rules

VALIDACIONES (Form Request)

'php artisan make:request ` esto creará el archivo dentro de App\Http\Request

Para ello en nuestro controlador deberemos llamar al objecto Family deberemos hacerlo a StoreFamilyRequest que hará la validación previa

Revisar este video: https://www.youtube.com/watch?v=CnsaIC9JR4Q&list=PLZ2ovOgdI-kVtF2yQ2kiZetWWTmOQoUSG&index=22

Traducción de las Validaciones

Usaremos el paquete: https://laravel-lang.com/basic-usage.html#installation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment