• Час читання ~7 хв
  • 13.07.2022

Laravel Livewire - це повноцінний фреймворк Laravel для побудови динамічних інтерфейсів. У недалекому минулому, щоб створити додаток за допомогою Laravel, вам довелося:

  1. Write Blade templates and render your app on the server side
  2. Write your backend as APIs that accept and respond with JSON, and then have a frontend framework like Vue, React, or Angular to consume the APIs and implement the UI

Але тепер у нас є третій варіант: Livewire. Я б із задоволенням детально зупинився на плюсах і мінусах варіантів 1 і 2 вище, але це вже було зроблено справедливо в цьому добре написаному дописі тут.

У цій статті ми глибоко зануримося в Livewire і подивимося, як його можна застосувати в реальних додатках.

Що ми побудуємо

Ми створимо простий додаток для ведення блогів з такими функціями:

  1. Anyone can create an account and log in
  2. Logged-in users can create and update their own posts
  3. Anyone can read posts

Передумови та налаштування

Цей підручник передбачає, що ви досить досвідчені з Laravel (зверніть увагу, що цей підручник використовує Laravel 7.x). Попередній досвід роботи з Livewire не потрібен — я думаю, що саме тому ми тут.

Звичайно, для початку ми повинні налаштувати наше середовище розробки. Спочатку створіть новий додаток Laravel:composer create-project --prefer-dist laravel/laravel:

^7.0 blog-wire

Потім встановіть пакунок Livewire за допомогою composer:

composer need livewire/livewire

Створіть нову базу даних і додайте до файлу облікові дані .env бази даних. І це все, що нам потрібно для початку роботи «Livewiring»!

Як працює Livewire?

Перш ніж ми почнемо, добре мати уявлення про те, як Livewire робить свою справу. Коротко:

  • Livewire відображає вихід початкового компонента на сторінку — так, подібно до типового серверного шаблону Blade
  • Коли відбувається взаємодія, Livewire робить AJAX-запит на сервер з оновленими даними
  • Сервер повторно відтворює компонент і відповідає оновленим HTML
  • Потім Livewire інтелектуально мутує DOM відповідно до того, що змінилося

Як бачите, це як мати свій фронтенд і бекенд в одному місці, без необхідності повторювати логіку.

Ключові поняття Livewire Активація Livewire на сторінці

Щоб Livewire працював на сторінці, вам потрібно включити стилі та сценарії Livewire

на кожну сторінку, які їх потребують. Зазвичай вони входять у ваш базовий шаблон. Ви б зробили це, використовуючи @livewireStyles і@livewireScripts:

//app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>@yield('title')</title>
    @livewireStyles
</head>
<body>
    @yield('content')
    @livewireScripts
</body>
</html>

Livewire компоненти

Livewire does all of its goodness around its components. Livewire компоненти are quite similar to typical Laravel Blade class-based components. Let’s take a quick look at the two.

Створення компонента

Laravel Blade Ви можете створити компонент Laravel Blade, виконавши таку команду:php ремісник make:

component Alert

Це створить новий Alert.php файл класу і помістить його в папкуApp\Views\Components. Потім створюється відповідний шаблон представлення і розміщується в resources/views/components. Для відображення компонента можна скористатися таким синтаксисом Blade: <x-alert/>.

Ви можете додатково вивчити компоненти Laravel Blade в документації.

Створення компонента

Livewire Щоб створити компонент Livewire, запустіть таку команду

:php ремісник make:livewire Alert

Команда також створить два нових файли: app\Http\Livewire\Alert.php і шаблон resources/views/livewire/alert.phpпредставлення .

Ви можете візуалізувати компонент Livewire за допомогою або <livewire:alert /> @livewire('alert').

As you can see, the commands look quite similar. The only major difference is that with Livewire компоненти, there’s a real-time sync (no page refresh required) between the component class and its view template. We will see how this works shortly.

Властивості

Livewire Загальнодоступні властивості класів компонентів доступні для перегляду шаблонів компонентів. На цьому справа не зупиняється — значення властивості синхронізується в режимі реального часу з представленням, таким чином, що при оновленні значення властивості в представленні, воно автоматично оновлюється в класі компонента.

//App\Http\Livewire\Alert.php
<?php
class Alert extends Component{
  public $message = "Our alert message";
}

// livewire/alert.blade.php
<div>
  <input wire:model="message">
  <br/>
  {{ $message }}
</div>

Щоб прив'язати властивість компонента до вхідного елемента html, слід використати наступний sytax:

wire:model="ім'я властивості"

By typing into the input box, you will see the value of $message updating in real time. This is very similar to the concept of data binding in frameworks like Vue.js, React, and Angular. Learn more about Властивості here.

Дії

з Livewire Так само, як можна прив'язувати дані в шаблоні подання до загальнодоступних властивостей компонентів, можна також зіставляти події на стороні клієнта з методами у ваших компонентах. Наприклад, ви можете реагувати на події кліків, події ключа та ключа тощо, використовуючи методи, визначені у вашому класі компонентів.

Давайте розглянемо приклад:

<?php

use Livewire\Component;
class PostAlert extends Component{
  public $liked = true;
  public function render(){
    return view('livewire.post-alert');
  }

  public function toggleLike(){
    $this->liked = !$this->liked;
  }
}


// livewire/post-alert.blade.php
<div>
    <h4>Seeing livewire action in action 😜</h4>
    <button class="btn btn-primary" wire:click="toggleLike()">
        Like
    </button>
    @if ($liked)
        <i class="fa fa-heart text-danger h4"></i>
    @else
        <i class="fa fa-heart text-secondary h4"></i>
    @endif
</div>

У класі компонентів вище ми створили методtoggleLike(), який перемикає значення властивості на її протилежне логічне значенняliked. У поданні шаблону ми маємо кнопку та значок серця, які або пофарбовані в червоний, або в сірий колір залежно від вартості liked властивості.

Ми використовували синтаксис, wire:click=[action name] щоб прив'язати toggleLike метод до події кліку.

Livewire Action ToggleLike Event
Livewire action toggling a button.

A lot Livewire’s use cases revolve around properties and actions, and as such, they are very important to understand. These concepts can be applied to things like create form, edit form, delete form, etc. Read more about Дії here.

Перевірка

даних Livewire робить перевірку даних безпроблемною. Щоб перевірити дані, що надходять із подання шаблону форми, потрібно написати властивість$rules, яка містить правила перевірки, як у Laravel. Після цього ви викликаєте метод, $this→validate() який виконує перевірку.

Давайте розглянемо форму для створення запису блогу:

 ...
class CreatePost extends Component
{
    public $title, $body;
    public $success;
    protected $rules = [
        'title' => 'required|string|max:220',
        'body' => 'required'
    ];

    public function render()
    {
        return view('livewire.create-post')
            ->extends('layouts.app')
            ->section('content');
    }
    public function create(){
        $this->validate();
        Post::create([
            'title' => $this->title,
            'slug' => Str::slug($this->title),
            'body' => $this->body,
            'author_id' => auth()->id()
        ]);

        $this->success = true;
    }
}


// livewire/create-post
<div class="container">
    @if ($success)
        <div class="alert alert-success">
            Post has been created successfully
        </div>
    @endif
    <form wire:submit.prevent="create">
        <div class="form-group">
            <label for="Post title">Post title</label>
            <input wire:model="title" type="text" name="title" id="title" class="form-control" placeholder="Title of the post">
            @error('title') <span class="error">{{ $message }}</span> @enderror
        </div>
        <div class="form-group">
            <label for="Post body">Post Body</label>
            <textarea name="body" id="body" placeholder="Body of post here..." wire:model="body" class="form-control"></textarea>
            @error('body') <span class="error">{{ $message }}</span> @enderror
        </div>
        <div>
            <button class="btn btn-primary" type="submit">Publish</button>
        </div>
    </form>
</div>
 
У коді форми вище, коли користувач надсилає запис, і він не проходить перевірку, відображаються помилки перевірки, і все це без оновлення сторінки.

Початок роботи з Laravel Livewire

Досить сказав — давайте перейдемо до дій. Ви можете слідкувати за репозиторієм GitHub, коли ми створюємо наш демонстраційний додаток.

Оскільки ми хочемо, щоб користувачі, які ввійшли в систему, могли керувати власними публікаціями, вони повинні спочатку створити обліковий запис. Для цього ми будемо використовувати вбудовану систему аутентифікації Laravel.

Спочатку встановіть laravel/ui composer package:

composer need laravel/ui

Потім запустіть php artisan ui vue --auth на риштування всю систему аутентифікації, а потім php artisan migrate виконайте міграцію БД.

N.B., most of the things we used to do with controllers will now be done using Livewire компоненти.

Давайте продовжимо створювати модель, необхідну для нашого додатка для публікацій у блозі, :

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
    use SoftDeletes;

    protected $guarded = [];
    public function author(){
        return $this->belongsTo(User::class, 'author_id', 'id');
    }
}

Тепер ми створимо наш файл міграції, App\Post
php artisan make:migration create_posts_table--table=posts:

Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug')->unique();
            $table->longText('body');
            $table->integer('author_id');
            $table->timestamps();
            $table->softDeletes();
});

Створення компонентів

Ми будемо створювати компонент для кожної потрібної дії блогу, тобто створювати публікацію, редагувати публікацію, список публікацій та переглядати публікацію. Давайте підемо далі і створимо компоненти:

  • php artisan make:livewire CreatePost
  • php artisan make:livewire EditPost
  • php artisan make:livewire ListPost
  • php artisan make:livewire HomePost
  • php artisan make:livewire ReadPost

Ми можемо відтворити компонент Livewire безпосередньо з таких маршрутів:Route::get('/posts/create', [\App\Http\Livewire\CreatePost::

class, '__invoke'])->middleware('auth');

Instead of calling controller actions, we will be routing to the Livewire компоненти, as shown above. Let’s now add all the routes we’ll need in web.php:

Route::get('/', function () {
    return view('index');
});
Auth::routes();
Route::get('/post/{slug}', [\App\Http\Livewire\ReadPost::class, '__invoke']);
Route::get('/home', '[email protected]')->name('home');
class, '__invoke'])->middleware('auth');
Route::get('/posts/{id}/edit', [\App\Http\Livewire\EditPost::class, '__invoke'])->middleware('auth');

//ListPost.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class ListPost extends Component
{
    public function render()
    {
        $posts = \App\Post::latest()->paginate(20);
        return view('livewire.list-post', ['posts' => $posts])
            ->extends('layouts.app')
            ->section('content');
    }
}



//livewire/list-post.blade.php
<div>
    <h4>My Posts <a href="{{ url('posts/create') }}" class="btn btn-primary"><i class="fa fa-plus"></i> Add new</a></h4>
    <ul class="list-group list-group-flush">
        @forelse ($posts as $post)
            <li class="list-group-item">

                <div class="float-right">
                    <a href='{{ url("posts/{$post->id}/edit") }}' class="btn btn-primary"><i class="fa fa-edit"></i> Edit</a>
                </div>
                <div>
                    <h5>{{ $post->title }}</h5>
                    <p>{!! substr(strip_tags($post->body), 0, 200) !!}</p>
                    <small class="text-muted">Published {{ $post->created_at }}</small>
                </div>

            </li>    
        @empty
            <li>You have not written any posts yet, write one now</li>
        @endforelse

    </ul>
</div>

//CreatePost.php
<?php
namespace App\Http\Livewire;
use App\Post;
use Livewire\Component;
use Illuminate\Support\Str;
class CreatePost extends Component
{
    public $title, $body;
    public $success;
    protected $rules = [
        'title' => 'required|string|max:220',
        'body' => 'required'
    ];

    public function render()
    {
        return view('livewire.create-post')
            ->extends('layouts.app')
            ->section('content');
    }
    public function create(){
        $this->validate();
        Post::create([
            'title' => $this->title,
            'slug' => Str::slug($this->title),
            'body' => $this->body,
            'author_id' => auth()->id()
        ]);

        $this->success = true;
    }
}

У наведеному вище компоненті ми створюємо публічні змінні для утримання заголовка та основного вмісту публікації блогу, а також success змінну, щоб вказати, чи успішне створення публікації.

У методі render() Livewire дозволяє нам вказати файл макета, який буде використовуватися для візуалізації компонента, і розділ, де ми хочемо, щоб він відображався за допомогою extends() методів andsection(), відповідно.

Тепер вигляд шаблону виглядає так:Якщо ви перейдете своїм браузером до /posts/create, ви повинні побачити форму створення:

<div class="container">
    @if ($success)
        <div>
            <div class="alert alert-success">
                Post has been created successfully. <a href="{{ url('/home') }}">View all posts</a>
            </div>

        </div>
    @endif

    <form wire:submit.prevent="create">
        <div class="form-group">
            <label for="Post title"&gt;Post title</label>
            <input wire:model="title" type="text" name="title" id="title" class="form-control" placeholder="Title of the post">
            @error('title') <span class="error">{{ $message }}</span> @enderror
        </div>
        <div class="form-group">
            <label for="Post body">Post Body</label>
            <textarea name="body" id="body" placeholder="Body of post here..." wire:model="body" class="form-control"></textarea>
            @error('body') <span class="error">{{ $message }}</span> @enderror
        </div>
        <div>
            <button class="btn btn-primary" type="submit">Publish</button>
        </div>
    </form>
</div>

Creation Form Display

Це досить простий приклад того, як Livewire можна застосувати в реальному світі.

Висновок

Livewire усуває розрив між бекендом та фронтендом. Ви отримуєте переваги інтерактивності в режимі реального часу, не пишучи багато JavaScript самостійно. Якщо ви раніше використовували Vue.js, дуже легко побачити переваги Livewire.

Livewire не є чудовим вибором для програм, які є дуже вимогливими на стороні клієнта. Але в ситуаціях, коли вам потрібна програма з рендерингом сервера з посипанням реактивності, Livewire послужить вам хорошу службу.

Знову ж таки, додаток, який ми створили в цьому підручнику, можна знайти наGвонаHUB.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297