Cómo Crear un Sistema CRUD con Laravel-Livewire

Claudio Vallejo
8 min readMar 1, 2020
Laravel + Laravel Livewire !

En esta oportunidad realizaremos un proyecto que nos permita implementar un sistema de contactos utilizando Laravel Livewire (awesome work! Caleb Porzio) a través del método CRUD (Create, Read, Update, Delete) pero con toda la magia y funcionalidad que nos entrega laravel-livewire.

1. Crear nuestro proyecto en Laravel

laravel new contactos

2. Ingresar a tu proyecto e instalar Tailwindcss

 cd contactos

Para Tailwindcss como preset puedes utilizar el comando (más info):

npx use-tailwind-preset

en mi caso utilizo la opción “yes” para la generación de los archivos necesarios para para la autenticación de usuarios “auth files”.

O seguir la documentación oficial para instalar y configurar lo que requieras.

“Siempre recuerda que debes configurar tu entorno con las variables correspondientes a la base de datos, idioma y lo que requieras”

3. Definir la ruta

Abrir el archivo routes/web.php y definir la ruta que utilizaremos para todas las operaciones CRUD (puesto que laravel livewire manejará todo lo demás por nosotros).

Route::view('contacts', 'users.contacts');

4. Genera la vistas para el CRUD

Si te fijas, al determinar una ruta del tipo users.contacts implica que deberás crearla dentro de la ruta resources/views/ y luego generar el archivo contacts.blade.php debiera quedar así:

Dentro del archivo contacts.blade.php debemos agregar el componente de laravel-livewire que crearemos en el próximo paso, quedando de la siguiente manera:

@extends('layouts.app')@section('content')
<div class="flex justify-center mx-auto p-4 max-w-4xl rounded shadow mb-4">
@livewire('contact')
</div>
@endsection

5. Generar el modelo ‘Contact’

La alternativa más simple y directa es generar el modelo a través del siguiente comando (adicionando el flag -mpara generar la migración de inmediato):

php artisan make:model Contact -m

El modelo debiera incorporar solo la variable protected $guarded = []; esto puesto que estamos en un ambiente de prueba y nos permite agregar todos los campos que quisiéramos pasar a la BD. Debiera verse así:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Contact extends Model
{
protected $guarded = [];
}

En este ejemplo solo utilizaremos dos campos, el Nombre y el correo electrónico, por lo que la migración debiera ser muy simple. Solo agrega las siguientes dos líneas a la migración nueva generada:

public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->bigIncrements('id');

$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
}

El correo está marcado como unique() con el objeto de evitar agregar dos usuarios con el mismo email.

Por úlitmo, correr el siguiente comando para generar la tabla en tu base de datos:

php artisan migrate

6. Instalar Laravel Livewire

Es muy simple, solo debes correr el siguiente comando en tu terminal:

composer require livewire/livewire

Hay que incorporar @livewireStyles antes del </head> y @livewireScripts antes de la etiqueta </body> en el archivo resources/views/layouts/app.blade.php quedando así:

<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title><!-- Styles -->
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
@livewireStyles</head>
<body class="bg-gray-100 h-screen antialiased leading-none">
<div id="app">
<nav class="bg-blue-900 shadow mb-8 py-6">
<div class="container mx-auto px-6 md:px-0">
<div class="flex items-center justify-center">
<div class="mr-6">
<a href="{{ url('/') }}" class="text-lg font-semibold text-gray-100 no-underline">
{{ config('app.name', 'Laravel') }}
</a>
</div>
<div class="flex-1 text-right">
@guest
<a class="no-underline hover:underline text-gray-300 text-sm p-3" href="{{ route('login') }}">{{ __('Login') }}</a>
@if (Route::has('register'))
<a class="no-underline hover:underline text-gray-300 text-sm p-3" href="{{ route('register') }}">{{ __('Register') }}</a>
@endif
@else
<span class="text-gray-300 text-sm pr-4">{{ Auth::user()->name }}</span>
<a href="{{ route('logout') }}"
class="no-underline hover:underline text-gray-300 text-sm p-3"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">{{ __('Logout') }}</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="hidden">
{{ csrf_field() }}
</form>
@endguest
</div>
</div>
</div>
</nav>
@yield('content')
</div>
<!-- Scripts -->
<script src="{{ mix('js/app.js') }}"></script>
@livewireScripts</body>
</html>

7. Crear el componente de Laravel-Livewire

Es posible crear los componentes de Laravel-Livewire a través de un comando artisan:

php artisan make:livewire contact

Con ello se crearán dos archivos. El primero app/Http/Livewire/Contact.php y el otro resources/views/livewire/contact.blade.php .

La estructura del primer archivo deberá quedar así:

<?phpnamespace App\Http\Livewire;use App\Contact as Contactos;
use Livewire\Component;
class Contact extends Component
{
public $data, $name, $email, $selected_id;
public $updateMode = false;
public function render()
{
$this->data = Contactos::all();
return view('livewire.contact');
}
private function resetInput()
{
$this->name = null;
$this->email = null;
}
public function store()
{
$this->validate([
'name' => 'required|min:5',
'email' => 'required|email:rfc,dns'
]);
Contactos::create([
'name' => $this->name,
'email' => $this->email
]);
$this->resetInput();
}
public function edit($id)
{
$record = Contactos::findOrFail($id);
$this->selected_id = $id;
$this->name = $record->name;
$this->email = $record->email;
$this->updateMode = true;
}
public function update()
{
$this->validate([
'selected_id' => 'required|numeric',
'name' => 'required|min:5',
'email' => 'required|email:rfc,dns'
]);
if ($this->selected_id) {
$record = Contactos::find($this->selected_id);
$record->update([
'name' => $this->name,
'email' => $this->email
]);
$this->resetInput();
$this->updateMode = false;
}
} public function destroy($id)
{
if ($id) {
$record = Contactos::where('id', $id);
$record->delete();
}
}
}

Hay que observar con detención todos los componentes de esta clase. Es acá donde se realizarán todas las operaciones CRUD. Hemos declarado las siguientes propiedades como públicas ( $data, $name, $email, $select_id, $updateMode ) las que serán cargadas de nuestro componente en la vista. Esta clase de componente realiza las acciones típicas de un controlador en Laravel.

8. Crear las vistas de los componentes de Laravel-Livewire

Ahora hay que crear dos archivos adicionales en la carpeta resources/views/livewire , el primero create.blade.php y el segundo update.blade.php . Con esto tendremos tres archivos dentro de esa carpeta:

El archivo contact.blade.php debe contener la siguiente estructura y contenido:

<div>

@if($updateMode)
@include('livewire.update')
@else
@include('livewire.create')
@endif
<table class="table-auto w-full">
<thead>
<tr class="bg-gray-200">
<th class="px-4 py-2">#</th>
<th class="px-4 py-2">Nombre</th>
<th class="px-4 py-2">Email</th>
<th class="px-4 py-2">acciones</th>
</tr>
</thead>
<tbody>
@forelse ($data as $item)
<tr class="text-center">
<td class="border px-4 py-2">{{ $item->id }}</td>
<td class="border px-4 py-2">{{ $item->name }}</td>
<td class="border px-4 py-2">{{ $item->email }}</td>
<td class="border px-4 py-2">
<button wire:click="edit({{ $item->id }})" class="px-2 py-1 bg-blue-200 text-blue-500 hover:bg-blue-500 hover:text-white rounded">Editar</button>
<button wire:click="destroy({{ $item->id }})" class="px-2 py-1 bg-red-200 text-red-500 hover:bg-red-500 hover:text-white rounded">Borrar</button>
</td>
</tr>
@empty
<tr class="text-center">
<td colspan="4" class="py-3 italic">No hay información</td>
</tr>
@endforelse
</tbody>
</table>
</div>

El siguiente archivo, create.blade.php posee el siguiente código:

<div class="w-full">
<div class="flex flex-wrap justify-between items-center mb-16">
<div class="w-auto pr-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="name">Nombre</label>
<input class="appearance-none block w-full bg-gray-200 text-gray-700 border {{ $errors->has('name') ? ' border-red-500' : 'border-gray-200' }} rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white" id="name" wire:model="name" type="text" placeholder="Nombre completo...">
@error('name')
<span class="text-red-500 text-xs italic">{{ $message }}</span>
@enderror
</div>
<div class="w-auto px-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="email">Email</label>
<input class="appearance-none block w-full bg-gray-200 text-gray-700 border {{ $errors->has('name') ? ' border-red-500' : 'border-gray-200' }} rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="email" wire:model="email" type="text" placeholder="Correo electrónico...">
@error('email')
<span class="text-red-500 text-xs italic py-1">{{ $message }}</span>
@enderror
</div>
<div class="w-auto pl-3 text-right">
<div class="pt-5">
<button wire:click="store()" class="px-3 py-2 bg-purple-200 text-purple-500 hover:bg-purple-500 hover:text-purple-100 rounded">Agregar contacto</button>
</div>
</div>
</div>
</div>

El último archivo update.blade.php debe contener el código:

<div class="w-full">
<div class="flex flex-wrap justify-between items-center mb-16">
<input type="hidden" wire:model="selected_id">
<div class="w-auto pr-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="name">Nombre</label>
<input wire:model="name" type="text" class="appearance-none block w-full bg-gray-200 text-gray-700 border {{ $errors->has('name') ? ' border-red-500' : 'border-gray-200' }} rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white">
@error('name')
<span class="text-red-500 text-xs italic">{{ $message }}</span>
@enderror
</div>
<div class="w-auto px-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="email">Email</label>
<input wire:model="email" type="text" class="appearance-none block w-full bg-gray-200 text-gray-700 border {{ $errors->has('email') ? ' border-red-500' : 'border-gray-200' }} rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500">
@error('email')
<span class="text-red-500 text-xs italic py-1">{{ $message }}</span>
@enderror
</div>
<div class="w-auto pl-3 text-right">
<button wire:click="update()" class="px-3 py-2 bg-orange-200 text-orange-500 hover:bg-orange-500 hover:text-orange-100 rounded">Actualizar contacto</button>
</div>
</div>
</div>

9. Capturas de pantalla del flujo

Ingresa primero a la dirección de tu proyecto, en este caso contactos.test/contacts y debieras ver una pantalla similar a esta:

pantalla inicial

En esta primera vista debieras notar que por defecto se presenta la palabra “no hay información” esto se debe a la utilización del loop @forelse y luego @empty lo que nos permite pasar un mensaje en caso que no existan valores.

Agrega el nombre completo y el correo de tu primer contacto (los archivos están con la validación de ambos campos y los mensajes de error incluidos). Debieras tener una pantalla similar a esta:

al agregar información, editar o borrar, te darás cuenta que el browser no se actualizará… es la magia de Livewire

Ahora puedes editar la información presionando el botón “editar”:

vista de edición
update con otros datos
vista con los datos actualizados

Por último, puedes borrar el contacto presionando el botón “borrar”. El usuario automáticamente será eliminado de tu base de datos y de la pantalla.

usuario eliminado

10. Consideraciones finales

Tu sistema está listo para ser utilizado en algún proyecto. Espero te motives a aprender más de Laravel, Laravel-Livewire (pssst… te paso un dato, Caleb además ha creado un microframework de javascript llamado “alpine.js”, la magia se amplifica!)

https://github.com/alpinejs/alpine

Finalmente podrás utilizar un sistema totalmente “mágico” para el ingreso, edición o borrado de tus contactos. Espero que esta aplicación CRUD explicada paso a paso sirva para comenzar a utilizar de mayor y mejor forma Laravel-Livewire.

Gracias por tu lectura.

Si te ha gustado, podrías darme un aplauso y seguirme :)

--

--

Claudio Vallejo

Wine, programmer, diver & photographer lover. Agronomist Engineer. CEO/Founder of Intelvid.la — Cofounder Tradesfere.com More: cvallejo.me