Proceso de Crear y Editar (CRUD) para los posts en Laravel Livewire

Veremos como crear el proceso CRUD en Livewire.

Las rutas:

Route::group(['prefix' => 'post'],function () {
       Route::get('/', App\Http\Livewire\Dashboard\Post\Index::class)->name("d-post-index");        // listado
       Route::get('/create', App\Http\Livewire\Dashboard\Post\Save::class)->name("d-post-create");  // crear
       Route::get('/edit/{id}', App\Http\Livewire\Dashboard\Post\Save::class)->name("d-post-edit");// edit
});

A continuación, se presenta el código para el apartado de crear y actualizar un post:

app/Http/Livewire/Dashboard/Post/Save.php

<?php

namespace App\Http\Livewire\Dashboard\Post;

use App\Models\Category;
use App\Models\Post;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
use Livewire\WithFileUploads;

class Save extends Component
{
   use WithFileUploads;

   public $title;
   public $date;
   public $text;
   public $description;
   public $posted;
   public $type;
   public $category_id;
   public $image;

   public $post;

   protected $rules = [
       'title' => "required|min:2|max:255",
       'description' => "required|min:2|max:255",
       'date' => "required",
       'type' => "required",
       'category_id' => "required",
       'posted' => "required",
       'text' => "required|min:2|max:5000",
       'image' => "nullable|image|max:1024",
   ];

   public function mount($id = null)
   {
       if ($id != null) {
           $this->post = Post::findOrFail($id);
           $this->title = $this->post->title;
           $this->text = $this->post->text;
           $this->date = $this->post->date;
           $this->description = $this->post->description;
           $this->posted = $this->post->posted;
           $this->type = $this->post->type;
           $this->category_id = $this->post->category_id;
       }
   }

   public function render()
   {
       $categories = Category::get();
       return view('livewire.dashboard.post.save', compact('categories'));
   }

   public function submit()
   {

       // validate

       $this->validate();

       // save

       if ($this->post) {
           $this->post->update([
               'title' => $this->title,
               'text' => $this->text,
               'description' => $this->description,
               'date' => $this->date,
               'posted' => $this->posted,
               'type' => $this->type,
               'category_id' => $this->category_id,
           ]);
           $this->dispatch("updated");
       } else {
           $this->post = Post::create(
               [
                   'title' => $this->title,
                   'slug' => str($this->title)->slug(),
                   'text' => $this->text,
                   'description' => $this->description,
                   'date' => $this->date,
                   'posted' => $this->posted,
                   'type' => $this->type,
                   'category_id' => $this->category_id,
               ]
           );
           $this->dispatch("created");
       }

       // upload
       if ($this->image) {
           $imageName = $this->post->slug . '.' . $this->image->getClientOriginalExtension();
           $this->image->storeAs('images/post', $imageName, 'public_upload');

           $this->post->update([
               'image' => $imageName
           ]);
       }
   }
}

Y su vista, que, como detalle importante, recuerda colocar el campo para las fechas como tipo date en HTML:

resources/views/livewire/dashboard/post/save.blade.php

<div>

   <div class="container">

       <x-action-message on="created">
           <div class="box-action-message">
               {{ __('Created post success') }}
           </div>
       </x-action-message>

       <x-action-message on="updated">
           <div class="box-action-message">
               {{ __('Updated post success') }}
           </div>
       </x-action-message>


       <x-form-section submit='submit'>

           <x-slot name="title">
               {{ __('Post') }}
           </x-slot>

           <x-slot name="description">
               Lorem ipsum dolor sit amet consectetur adipisicing elit. Neque hic voluptates quaerat accusantium a. Est
               voluptate voluptatibus necessitatibus a non iure rerum, nesciunt nisi assumenda quaerat nam incidunt ab.
               Facilis.
           </x-slot>

           @slot('form')

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Title</x-label>
                   <x-input type="text" wire:model.live='title' class="w-full" />
                   @error('title')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Date</x-label>
                   <x-input type="date" wire:model='date' class="w-full" />
                   @error('date')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Description</x-label>
                   <textarea wire:model='description' class="block w-full"></textarea>
                   @error('description')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Text</x-label>
                   <textarea wire:model='text' class="block w-full"></textarea>
                   @error('description')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Posted</x-label>
                   <select class="block w-full" wire:model='posted'>
                       <option value=""></option>
                       <option value="yes">Yes</option>
                       <option value="not">Not</option>
                   </select>
                   @error('posted')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Type</x-label>
                   <select class="block w-full" wire:model='type'>
                       <option value=""></option>
                       <option value="Advert">Advert</option>
                       <option value="post">Post</option>
                       <option value="course">Course</option>
                       <option value="movie">Movie</option>
                   </select>
                   @error('type')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Category</x-label>
                   <select class="block w-full" wire:model='category_id'>
                       <option value=""></option>
                       @foreach ($categories as $c)
                           <option value="{{ $c->id }}">{{ $c->title }}</option>
                       @endforeach
                   </select>
                   @error('category')
                       {{ $message }}
                   @enderror
               </div>

               <div class="col-span-10 sm:col-span-3">
                   <x-label for="">Image</x-label>
                   <x-input type="file" wire:model='image' class="w-full" />
                   @error('image')
                       {{ $message }}
                   @enderror

                   @if ($post && $post->image)
                       <img class="w-40 my-3" src="{{ $post->getImageUrl() }}" alt="{{ $post->title }}">
                   @endif
               </div>
           @endslot

           @slot('actions')
               <x-button type="submit">Send</x-button>
           @endslot
       </x-form-section>
   </div>
</div>

Transcripción del vídeo

En esta corta sección como te comenté en la introducción vamos a querer hacer el crud para nuestros posts es algo que debería hacerse relativamente rápido Aunque tenemos más Campos porque ya antes hicimos el crud para las categorías esto lo vamos a aprovechar en la siguiente sección que trabajemos con los filtros y los campos de búsqueda por lo tanto esta sección te lo pudieras tomar como un reto completamente como una práctica lo que hicimos antes y ahí tú lo desarrollas como quieras desde cero expando lo que ya tenemos para las categorías etcétera y obviamente voy a intentar avanzar lo más rápido posible porque ya es material visto Así que voy a remplazar lo que ya tenemos Recuerda que cada vez que es un reto básicamente es replicar y adaptar lo que ya tenemos entonces yo voy a intentar avanzar lo más posible por lo comentado antes porque es un tema que ya vimos Así que en esta parte vamos a comenzar es con la parte del save es decir guardar y actualizar o crear y actualizar por lo tanto tenemos que crear las rutas Bueno aquí te lo muestro rapidito.

Resumen

Tenemos que crear las rutas para tal fin en este caso bueno puedes crear todo de una vez Pero serían estas dos y dejas comentada esta para el Index agregamos aquí el enlace en el menú de navegación Aquí también para el responsive que está bueno Aquí creo que no lo referencia ahorita reviso y aquí también la parte de El guardado claro está el componente en Sí con todos los nuevos Campos El upload Claro está su vista que sería bueno esto sería la parte más tediosa curiosamente que es el montón de html inclusive se pudiera crear un componente para esto un componente anónimo en este caso un componente de laravel para evitar todo este montón de clases pudiera ser Interesante pero sería un lío ahí con los Textareas y los input y pasar el tipo Bueno sobre todo el textarea y los inputs pero bueno ahí pudiera estar puede ser que se defina como un slot o algo por el estilo no sé pero de repente lo vemos más adelante como algún reto o algo de momento podemos replicar todo tal cual lo tenemos así que pues expresado lo expresado adelante bien perfecto vamos allá.

Crear componente

Comencemos aquí definiendo los campos Tenemos aquí una propiedad public para la fecha voy a duplicar varias veces Aquí voy a colocar para el Bueno voy a colocar aquí primero el title para seguir ahí el juego que tenemos abajo aquí voy a colocar también el loot lo podemos autogenerar entonces así nos amos un campo voy a colocar el de description El de text creo que está aquí abajo aquí está aquí abajo voy a colocar aquí el de text el tipo Aquí está tipo y poed coloco tipo coloco posted coloco category ID y colocamos el de image creo que no lo coloqué no no coloqué falta uno colocamos image Ah ya tenemos los campos serían todos ellos:

class Save extends Component
{
   use WithFileUploads;

   public $title;
   public $date;
   public $text;
   public $description;
   public $posted;
   public $type;
   public $category_id;
   public $image;

Validaciones

Perfecto puedo cerrar esto y vamos allá Aquí me vas a permitir ya definido los campos duplicar lo que ya tenemos Porque si no vamos a tardar aquí un mundo y no quiero tardar tanto tiempo aquí la parte de la inicialización voy a traerme esto y empezamos de esto entonces Aquí más o menos esto mismo Está bien el image todo esto tenemos que agregar aquí algunos les cómo sería el date no me quiero preocupar mucho simplemente voy a indicar que es un campo requerido pero pudiéramos hacer algo con el formato pero otra vez no es la idea Cualquier cosa si te interesa me lo puedes solicitar para el final del curso ya que no quiero no es algo específico de Livewire pues entonces quiero explotar lo que tenemos en lightware category ID un poco lo mismo Perdón aquí no era catega ID el deposte también duplicar de acá ya que es lo mismo que se ha requerido el de tex aquí ya lo tenemos en este caso si va a ser requerido porque sería el contenido que le vamos a colocar pamos colocarlo aquí arriba inclusive y el image vamos a conservarlo tal cual está entonces reviso aquí rapidito title Me faltó el description coloco aquí description 255 Aquí voy a colocar hasta 5000 realmente puedes colocar lo que tú quieras o simplemente lo quitas pero como es el campo de texto largo colocamos t categorí ID posted text e image perfecto vamos con la parte del monted aquí buscamos es obviamente por el post así que bueno no [Música] esto curiosamente no lo encuentra Ah no Aquí está el de categoría Bueno se lo eliminó por alguna razón bueno no lo hemos importado Mejor dicho por aquí voy a duplicar esto varias veces por aquí voy a colocar lo mismo que tenemos arriba colocamos category ID colocamos posted colocamos type colocamos el image obviamente no colocamos description y para ver creo para ver falta date creo que con esto sería todo 

Método de submit

Perfecto ya aquí terminamos la inicialización vamos con la parte de submit y también de lad no hay más nada perfecto voy a copiar esto regreso acá y lo coloco bien Seguimos aquí adaptando para ver no si me puedo traer esto no no me lo puedo traer bueno vuelvo aquí duplico acá varias veces colocamos description colocamos aquí el de category ID colocamos el de fecha para que no se me olvide date colocamos el de tipo colocamos el de posted y ya:

class Save extends Component
{
      public function submit()
   {

       // validate

       $this->validate();
       }
  }

Importantísimo el slot este sería bu este sería para upate si podemos Bueno aquí depende de ti yo como so una aplicación de ejemplo Bueno aquí está el slug perdón voy a también actualizarlo pero eso sería un tema que se debería de elaborar un poco más porque si es una aplicación tipo blog y cambiamos el título usualmente no queremos cambiar el slug porque ahí pierdes la fuerza de posicionamiento que tenías para la publicación original pero eso es un factor seo no quiero mezclar tantas cosas y ya queda de como lo quieras hacer cualquier duda y lo puedes comentar coloco post coloco bueno todo el contenido que nos trajimos aquí creamos la imagen sería aquí publ lo la carpeta que creamos antes la extensión y lo demás y aquí actualizamos nuestro post Bueno aquí también okay punto importante Aquí también desde la parte de El render sería También tenemos que obtener aquí las categorías un detallito importante categories va a ser igual a category puntos dos puntos get y le paso acá las categorías importamos Ahí está perfecto en principio esto sería todo.

Vista

Vamos con la parte más pesada para mí que sería el de sabe, para ver aquí está aquí la tenemos entonces otra vez me disculpo voy a partir de lo que ya tenemos Porque no quiero que esto dure media hora coloco acá entonces Bueno aquí cambio a pos ahí cambia post aquí sería título post que quieras colocarle el título el texto imagen perfecto el no lo colocamos bueno colocamos el resto de los campos bien aquí Comencemos con el del date coloco date aquí sería date también y date también el del texto Okay aquí lo tenemos el siguiente sería el del description que sería similar al del texar que tenemos Este es un n input también que le colocamos para aquí No colocamos el textaare Bueno aquí voy a buscar De igual forma por si no lo veo textarea ara con el zoom no no hay nada bueno aquí tuvimos que utilizar fexar en un input ya que tenemos más texo funcionalmente es lo mismo pero obviamente un Tex aras es más cómodo voy a traerme todo esto voy a colocarlo acá y adicionalmente voy a colocarle de tipo blot para que ocupe todo el ancho toda la como quien dice la la fila sería bien perfecto esto mismo Sería para el content voy a quitar esto digo esto mismo Sería para el description que voy a colocar mejor arriba description aquí coloco description Bueno no puedo utilizar el multicursor si no lo va a cambiar en muchas partes esto no va me quedó aquí muerto y aquí también perfecto nos faltarían ya los Select este va a ser el último que voy a dejar Simplemente porque me gusta organizarlo de esta forma vamos con el Select voy a comenzar con el del tipo coloco aquí tipo coloco type Aquí también y aquí type Perdón aquí no va type aquí de una matamos este nos colocamos el Select aquí le indicamos algunas clases las mismas que tenemos arriba un blot para que estemos 100% seguros de que va a ocupar todo toda la fila y un with full para que ocupe todo el ancho aquí colocamos en opción Bueno ya esto depende un poco de ti yo coloco aquí siempre un option muerto y a partir de aquí coloco las opciones voy a colocar Yes también puedes emplear el Translate del laravel si quieres y not, perfecto vamos con el siguiente campo que sería bueno este era perdón lo mezclé Este era el de posted posted aquí tampoco coloqué la cuestión esta posted y posted esta sería el tipo la coloco Aquí también el type y aquí manejamos los distintos tipos que hayamos colocado que esper no de publicidad como se diga esta Sería para post duplico acá Bueno no lo selecciona este sería el de curso y este sería el de movie buen pendiente que sean los mismos valores que tienes ahí en el en el la migración si no te va a dar ahí una un error por la relación que no Conde los tipos y est en principio falta de la categoría también ya con esto sería prácticamente todo aquí sería el campo el de category ID category category ID aquí empleamos el el forage el B for each y por aquí sería la categoría colocamos categoría coloco categories me traigo aquí el option aquí imprimimos por el ID bueno el Cid que imprimimos el título Sería elt bueno creo que sería todo por acá me parece.

El estilo, depende de ti aparece así porque aquí tenemos o para el formulario aquí tenemos la grilla Recuerda que este componente que estamos ampliando para ver dónde está aquí está el formulario sección el el funciona en base a una grilla aquí están las grillas y aquí estamos ocupando una grilla de tipo tres pudieras colocarle aquí cuatro por ejemplo y ahí ocupa más espacio bueno cuatro no perdón sería seis para que ocupe todo el ancho ya que es de seis y irías así para el resto de los campos si es lo que tú quieres realmente a mí me da igual ya presentación aquí lo tenemos todo doy un a ver qué pasa Ya di otro error dice que la propiedad day no ha sido encontrada Qué raro porque si coloqué la validación y creo que también coloqué el campo y no no coloqué el campo Pobrecita la eliminé coloco date ahí Perfecto Bueno coloco aquí rapidito cualquier cosa para a ver si podemos terminar bueno Esto sucede si colocamos el input de tipo date esto ya es de html Y seguramente te cambia el estilo según el navegador y sistema operativo voy a colocar post y las categorías estamos enviar y otro bonito eror aquí dice que no encontró la ruta dashboard post save que en teoría es la que tenemos aquí creada aquí la llamamos dashboard post a create y en entonces para ver aquí Sería para ver Ah no perdón Esto no es la ruta esto es la propiedad categoría que indica lo que va a hacer correcto aquí indica que no encontró la categoría Okay claro aquí esta no la cambié esta y aquí es post simplemente vi los campos y no vi la propiedad y me eliminó la Data qué desgracia venimos otra vez damos enviar y parece que creo entonces Y al menos ahí tenemos algo chequeamos aquí la base de datos ahí está voy a crear otro para tener algo en el listado y ya eso sirve todo así que ya con esto vamos a ir a la parte de el listado Pero eso lo hacemos en la siguiente clase

- Andrés Cruz

In english

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz En Udemy

Acepto recibir anuncios de interes sobre este Blog.

!Cursos desde!

10$

En Udemy

Quedan 2d 20:05!


Udemy

!Cursos desde!

4$

En Academia

Ver los cursos

!Libros desde!

1$

Ver los libros
¡Hazte afiliado en Gumroad!