PHP Livewire

De MediaWiki
Ir a la navegación Ir a la búsqueda

Introducción

  • Livewire permite o uso de compoñentes integrados en Laravel nos que se establece unha comunicación bidireccional (podemos enviar información desde o cliente (HTML) ao servidor (controlador) e viceversa sen necesidade de recargar completamente a páxina).
É o mesmo concepto que se empregaba en AJAX e que agora se usa con FETCH, pero integrado no framework de Laravel.



  • IMPORTANTE: Cando vexades a documentación mirade que version estades a consultar xa que dende a versión 2 á versión 3 houbo cambios.
Unha vez instalado en Laravel podedes consultar a versión instalada buscando a entrada livewire/livewire no arquivo composor.json no raíz do proxecto.
Polo de agora (versión 10-12) estamos a traballar coa versión 3.x de Livewire.


Instalación

  • No directorio raíz do proxecto Laravel escribe: composer require livewire/livewire
Unha vez instalado en Laravel podedes consultar a versión instalada buscando a entrada livewire/livewire no arquivo composor.json no raíz do proxecto.
Polo de agora (versión 10-12) estamos a traballar coa versión 3.x de Livewire.



Validación de campos

  • Imos crear a táboa marcas e imos crear unha relación entre perfumes e marcas.
A nivel de mysql:
CREATE TABLE perfumes.marcas (

  `id` int NOT NULL,

  `descripcion` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_spanish2_ci NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish2_ci;



INSERT INTO `marcas` (`id`, `descripcion`) VALUES
(1, 'Descripción actualizada da marca con id=1'),
(2, 'ADIDAS'),
(3, 'ARAMIS');


Táboa perfumes
CREATE TABLE perfumes.perfumes (
  `id` int NOT NULL,
  `descripcion` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_spanish2_ci NOT NULL,
  `prezo` decimal(8,2) NOT NULL,
  `data_compra` date DEFAULT NULL,
  `marca_id` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish2_ci;

ALTER TABLE perfumes.perfumes
  ADD PRIMARY KEY (`id`),
  ADD KEY `fk_PERFUMES_1_idx` (`id`),
  ADD KEY `fk_PERFUMES_MARCA_idx` (`marca_id`);

INSERT INTO perfumes.perfumes (`id`, `descripcion`, `prezo`, `data_compra`, `marca_id`) VALUES
(18, 'Best Aramis', '54.32', '2024-01-18', 2),
(19, 'Novo perfume da marca con id 1', '100.22', '2024-01-22', 1);



  • Creamos o modelo, ruta, controlador e polo de agora imos facer a vista para crear unha nova marca.
Dende o terminal escribimos: php artisan make:model Marca --resource


Arquivo: routes/web.php
<?php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\PerfumeController;
use App\Http\Controllers\MarcaController;

Route::resource('perfumes', PerfumeController::class);
Route::resource('marcas', MarcaController::class);


O arquivo de MarcaController xa se crearia con todo o código necesario para a xestión.


Arquivo resources/views/marcas/form_alta_marcas.blade.php (creado o cartafol marcas dentro de view)
@extends('plantilla');

@section('pageTitle', 'Alta de marcas')

@section('content')
<h2>Alta de novos perfumes</h2>



@if (session()->has('idPerfume'))
    <h4>Creado un novo rexistro co id: {{session('idPerfume')}}</h4>
@endif

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


@include('mensaxes.alertas_javascript')


@endsection


  • Como fixemos con perfume, os campos que conforman o formulario en Alta e Modificar son os mesmos, polo que imos crear un arquivo para facer un include nas dúas vistas:
Arquivo: resources/views/marcas/campos_marca.blade.php
<div>
    Descripción:<input type="text" maxlength="45" required size="45" name="descripcion" />
</div>



  • Como vemos o contido é parecido ao que tiñammos con perfumes, pero agora o contido (form e campos) os imos xestionar dende un compoñente Livewire.
Creamos o compoñente con esta orde: php artisan make:livewire marca
Isto creará dous arquivos en Laravel:
  • CLASS: app/Livewire/Marca.php => Ven a ser o controlador que vimos ata o de agora en Laravel.
  • VIEW: resources/views/livewire/marca.blade.php => Ven a ser a vista que vai visualizar Laravel no cliente.


Arquivo: app/Livewire/Marca.php
<?php

namespace App\Livewire;

use Livewire\Component;

class Marca extends Component
{
    public function render()
    {
        return view('livewire.marca');
    }
}
Básicamente indicamos en render a vista que vai enviar ao cliente.


Arquivo resource/views/Livewire/marca.blade.php
<form method="post" action="{{route('marcas.store')}}" name="formulario_marcas">

    @csrf
    @include('marcas.campos_marca')
    <div>
        <input type="submit" name="btnAlta" value="Alta" onClick="return confirm('Estás seguro de dar de alta a nova marca ');"/>
        <input type="reset" name="btnBorrar" value="Limpar" />

    </div>


</form>


  • Agora para incluir o compoñente Livewire nunha view de Laravel temos que poñer:
Arquivo resouces/views/marcas/form_alta_marca.blade.php
@extends('plantilla');

@section('pageTitle', 'Alta de marcas')

@section('content')
<h2>Alta de novos perfumes</h2>


<livewire:marca />


................


  • Se agora poñemosm na url: http://localhost:8080/marcas/create veremos que aparecerá unha vista tal cual aparecía cando fixemos o de perfume, pero a diferenza de perfumes, esta vista (os campos e form) se xestionan cun compoñente Livewire.


  • Agora imos ver os cambios que temos que facer para xestionar os campos do formulario.
Primero imos definir no controlador do compoñente livewire os campos que imos xestionar. No noso caso está a descripcion.
<?php

namespace App\Livewire;

use Livewire\Component;

class Marca extends Component
{
    public $descripcion = "Valor inicial";   // O valor inicial non é necesasrio. Soamente para que vexades como dito valor se carga na vista.

    public function render()
    {
        return view('livewire.marca');
    }
}



Arquivo: resources/views/marcas/campos_marca.blade.php
<div>
    Descripción:<input type="text" maxlength="45" required size="45" wire:model="descripcion" name="descripcion" />
</div>
  • wire:model="descripcion": O que estamos a dicir con isto é que este input está vinculado á propiedade $descripcion definida no compoñente Livewire. Calquera modificación realizada polo usuario no cliente (na páxina web) actualizará automaticamente o valor da propiedade no servidor grazas á reactividade proporcionada por Livewire. Ademais, se a propiedade no servidor cambia, ese cambio tamén se reflectirá no cliente.
Se vos dades conta non temos a propiedade value como tiñamos en perfumes.
Se agora cargades a páxina veredes como o valor inicial se carga no input.



  • Agora imos a facer a validación no servidor. Para iso temos que definir unha propiedade $rules coas regras de validación que xa empregamos en Laravel.
Ademáis imos crear un método ao que vai chamar o formulario cando faga submit e que fará a validación dos campos. No exemplo imos chamar ao método gardarMarca.
Arquivo: app/Livewire/Marca.php
<?php

namespace App\Livewire;

use Illuminate\Support\Facades\Log;

use Livewire\Component;

class Marca extends Component
{
    public $descripcion = "Valor inicial";

    protected $rules = [
        'descripcion' => 'required|string|min:5|max:45',
    ];

    public function render()
    {
        return view('livewire.marca');
    }

    public function gardarMarca(){
        $this->validate();

        Log::info('Pasa a validación');
    }
}
Para depurar o funcionamento dos compoñente livewire podemos empregar o facade Log::info e ver as mensaxes no arquivo /storage/logs/laravel.log (podedes borrar o contido antes de executar para ter todo limpo ao principio).


  • Para chamar a ese método temos que modificar a vista do compoñente livewire.
<form wire:submit.prevent="gardarMarca">

    @csrf
    @include('marcas.campos_marca')
    <div>
        <input type="submit" name="btnAlta" value="Alta" onClick="return confirm('Estás seguro de dar de alta a nova marca ');"/>
        <input type="reset" name="btnBorrar" value="Limpar" />

    </div>


</form>
Con isto wire:submit.prevent="gardarMarca" estamos a decir que cando faga o submit chame de forma asíncrona ao controlador do compoñente livewire ao método gardarMarca.
Nota: Podemos asociar calquera click de botón directamente ao un método no controlador do livewire, da forma: <button wire:click="gardarMarca">+</button>


  • Tamén imos visualizar os erros de validación que poida enviar o controlador Livewire se non pasa a validación. Para iso temos que empregar a directiva @error sobre cada un dos campos que teñen validación. No exemplo se coloca ao lado do input, pero poderían ir en calquera parte.
Arquivo: resources/views/marcas/campos_marca.blade.php
<div>
    Descripción:<input type="text" maxlength="45" required size="45" wire:model="descripcion" name="descripcion" />  
    @error('descripcion') <span class="error">{{ $message }}</span> @enderror
</div>


  • Se queremos personalizar as mensaxes de erro:
Arquivo: app/Livewire/Marca.php
<?php
...........

    protected $messages = [
        'descripcion.required' => 'La descripción es obligatoria.',
        'descripcion.string' => 'La descripción debe ser una cadena de texto.',
        'descripcion.min' => 'La descripción debe tener al menos 5 caracteres.',
        'descripcion.max' => 'La descripción no puede tener más de 45 caracteres.',
    ];
   ..............



  • Fixerase que neste caso a validación faise cando o usuario preme o botón de submit.
Se queremos que se faga a validación cando o usuario cambio o contido da caixa de texto temos que:
  • Empregar o método update($propiedade) que será chamado de forma automáticamente cando o campo teña unha modificación. Dito método fará a validación da propiedade. Temos que chamar ao método validatyOnly.
  • Cambiar a propiedade wire:model da caixa de texto por wire:model.live
Lembrar que estas chamadas fanse ao servidor polo que pode ser que non nos interese para aforrar recursos e comunicacións entre cliente e o servidor.


Arquivo: app/views/campos_marca.blade.php
MOI IMPORTANTE: Tedes que cambiar a propiedade wire:model por wire:model.live
<div>
    Descripción:<input type="text" maxlength="45" size="45" required
        wire:model.live="descripcion" name="descripcion" />
    @error('descripcion') <span class="error">{{ $message }}</span> @enderror
</div>
Arquivo: app/Livewire/Marca.php
    ..............
    public function updated($propiedade){
        $this->validateOnly($propiedade);
    }
    .............


Ao facer isto, cada vez que se preme no imput fará a validación.
Lembrar que poñer isto non quita que teñades a chamada $this->validate() cando se vaia a dar de alta/modificar os datos



  • Mirade a documentación xa que a validación tamén se pode definir en cada un dos campos en vez de empregar a propiedade $rules: https://livewire.laravel.com/docs/validation (escoller versión 3 na parte esquerda da páxina)


Operacións de alta-baixa-modificación

Alta

* A alta faise como sempre pero agora está no controlador do compoñente livewire.
Arquivo: app/Livewire/Marca.php
    .............
    public function gardarMarca(){
        $this->validate();

        Log::info('Pasa a validación');

        $marcaCreada = Marca::create([
            'descripcion' => $this->descripcion
        ]);

        session()->flash('message', "Marca creada correctamente con id $marcaCreada->id");
        $this->reset(['descripcion']);
    }

: Fixarse que para enviar unha información á vista empregamos session()->flash que vai gardar nunha variable de sesión (message) o texto a amosar.
: Dita variable non pode ser empregada pola páxina, soamente polo compoñente livewire xa que non se recarga a páxina enteira.
: A chamada a reset vai poñer en branco os valor da variable $descripcion do compoñente.


Funcionamento


Volver á UD7


-- Ángel D. Fernández González -- (2025).