Livewire چیست ؟ قسمت دوم آموزش Livewire در لاراول

دسته بندی: لاراول
سطح مقاله: متوسط
زمان مطالعه: 26 دقیقه
۲۰ مهر ۱۳۹۹

در قسمت اول از مجموعه مقالات Livewire چیست، با فریم ورک فول استک Livewire در لاراول آشنا شدیم و دیدیم که با استفاده از آن، نیازی به نوشتن کدهای جاوااسکریپت نداریم و می‌توانیم وب اپلیکیشن‌های پویا ایجاد کنیم. فرآیند و شیوه‌ی کار آن را با ایجاد یک پروژه‌ی عملی آموختیم و توانستیم بدون نیاز به Refresh شدن صفحه، نظرات خود را در وب اپلیکیشن ثبت کنیم. در انتهای مقاله، به منظور عمق بخشیدن به آموخته‌ها، یک درخواست Ajax ارسالی به سمت سرور را به طور کامل بررسی کردیم.

در این قسمت، قصد داریم تا پروژه‌ی ایجاد شده را توسعه دهیم. ارتباط با دیتابیس را برقرار کنیم و بخش‌های متنوع و جذابی از فریم‌ورک Livewire را با هم و به صورت عملی، فرا بگیریم. پس تا انتهای این مقاله با ما همراه باشید.

فهرست محتوای این مقاله

ارتباط با دیتابیس

در قدم اول نیاز داریم ارتباط با دیتابیس را برقرار کنیم تا نظرها را ذخیره کرده و بتوانیم سیستم ورود و ثبت نام را ایجاد کنیم.

ایجاد دیتابیس

ابتدا با استفاده از Wamp یا Xampp، ماژول MySql را فعال کرده و در  PhpMyAdmin، دیتابیس مورد نظر خود را ایجاد کنید. سپس فایل env. را با توجه به مشخصات دیتابیس، بروز رسانی کنید:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=pdf
DB_USERNAME=root
DB_PASSWORD=

ایجاد جداول

فایل Migration جدول نظرات را با استفاده از دستور زیر ایجاد کنید:

php artisan make:migration create_comments_table --create=comments

سپس ستون‌های مورد نیاز جدول را در فایلی که ایجاد شده، تعریف کنید:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->text('body');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('comments');
    }
}

پس از آن، در دایرکتوری پروژه با استفاده از دستور زیر جداول را ایجاد کنید:

php artisan migrate

ایجاد Model

با استفاده از دستور زیر برای جدول Comments، یک مدل ایجاد کنید:

php artisan make:model Comment

در فایل Comment.php ایجاد شده در پوشه‌ی app، رابطه‌ی بین جدول نظرات و کاربران را تعریف می‌کنیم:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    protected $guarded = [];

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
}

Lifecycle Hooks

هر کامپوننت Livewire، یک چرخه‌ی عمر دارد. Lifecycle Hookها به شما کمک می‌کنند تا در بخش‌های مختلف چرخه‌ی عمر کامپوننت، کدهای به‌خصوصی را اجرا کنید. در ادامه برخی از آن‌ها را در کدهای خود استفاده می‌کنیم تا با نحوه‌ی استفاده از آن‌ها بیشتر آشنا شوید.

ذخیره‌ی نظر جدید

برای ذخیره‌ کردن نظرها، باید محتوای متد ()addComment را به صورت زیر تغییر دهید. فعلا برای این جلسه، به id کاربر، یک مقدار پیش‌فرض اختصاص دهید:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;

class Comments extends Component
{
    public $comments;
    public $newComment;

    public function addComment()
    {
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
    }

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

یکی از Lifecycle Hookها، متد ()mount است که پس از هر بار Refresh صفحه، اجرا می‌شود. می‌توان از آن برای مقداردهی اولیه‌ به خصوصیات کامپوننت استفاده کرد. مثلا:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;

class Comments extends Component
{
    public $comments;
    public $newComment;

    public function mount()
    {
        $this->comments = Comment::latest()->get();
    }

    public function addComment()
    {
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);
        
        $this->newComment = '';

       $this->comments = Comment::latest()->get();
    }

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

حذف نظر

برای افزودن قابلیت حذف نظر، باید خروجی کامپوننت را بروز کنیم. برای این منظور، ابتدا نیاز است که FontAwsome را در صفحه‌ی خود داشته باشیم. پس در فایل welcome.blade.php در مسیر resources/views کد زیر را می‌نویسیم:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Livewire</title>
       <!-- Fonts -->
    <link rel="dns-prefetch" href="//fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css"
          integrity="sha256-h20CPZ0QyXlBuAw7A+KluUYx/3pK+c7lYEpqLTlxjYQ=" crossorigin="anonymous" />
   <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <livewire:styles />

   <style>
      * {
         font-family: 'Nunito', monospace;
      }
   </style>
</head>

<body class="d-flex justify-content-center">
<div class="w-75 d-flex mt-5">
    <div class="w-100 mx-3 rounded border p-5">
        <livewire:comments />
    </div>
</div>

<livewire:scripts />
</body>

</html>

سپس آیکون مورد نظرمان را به فایل comments.blade.php در همان مسیر و پوشه‌ی Livewire اضافه می‌کنیم:

<div class="mx-3">
    <h1 style="font-size: 2rem">Comments</h1>

    @error('newComment') <div class="alert-danger p-3 rounded">{{ $message }}</div> @enderror

    <form class="my-4 d-flex" wire:submit.prevent="addComment">
        <input type="text" class="w-100 rounded border shadow py-2 px-3 mr-2 my-2" placeholder="Write your comment here..." wire:model.debounce.500ms="newComment">
        <div class="py-2">
            <button type="submit" class="p-2 btn btn-success w-20 rounded shadow text-white">Add</button>
        </div>
    </form>
        @foreach($comments as $comment)
    <div class="rounded border shadow p-3 my-2">
        <div class="d-flex justify-content-between my-2">
            <div class="d-flex">
                <p>{{ $comment['body'] }}</p>
            </div>
            <i class="fas fa-times text-danger" style="cursor: pointer;"
               wire:click="removeComment({{$comment->id}})"></i>
        </div>
    </div>
        @endforeach
</div>

که خروجی به شکل زیر خواهد بود:

Livewire چیست

می‌بینید که در تگ i که برای نمایش آیکون استفاده کرده‌ایم، اکشن removeComment را به رویداد کلیک، bind کرده‌ایم. در کد فوق به نحوه‌ی پاس دادن پارامتر به اکشن نیز، دقت کنید. پس باید متد ()removeComment را در کامپوننت Comments تعریف کنیم:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;
use Livewire\WithPagination;

class Comments extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

    public $newComment;

    public function updated($field)
    {
        $this->validateOnly($field, ['newComment' => 'required|max:255']);
    }

    public function addComment()
    {
        $this->validate(['newComment' => 'required|max:255']);
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
    }

    public function removeComment($commentId)
    {
        $comment = Comment::find($commentId)->delete();
    }

    public function render()
    {
        return view('livewire.comments', [
            'comments' => Comment::latest()->paginate(2),
        ]);
    }
}

صفحه‌بندی یا Pagination

در این مرحله می‌خواهیم برای نظرها صفحه‌بندی ایجاد کنیم. برای این منظور، خروجی کامپوننت را به شکل زیر بروز کنید:

<div class="mx-3">
    <h1 style="font-size: 2rem">Comments</h1>

    <form class="my-4 d-flex" wire:submit.prevent="addComment">
        <input type="text" class="w-100 rounded border shadow py-2 px-3 mr-2 my-2" placeholder="Write your comment here..." wire:model.debounce.500ms="newComment">
        <div class="py-2">
            <button type="submit" class="p-2 btn btn-success w-20 rounded shadow text-white">Add</button>
        </div>
    </form>
        @foreach($comments as $comment)
    <div class="rounded border shadow p-3 my-2">
        <div class="d-flex justify-content-between my-2">
            <div class="d-flex">
                <p>{{ $comment['body'] }}</p>
            </div>
            <i class="fas fa-times text-danger" style="cursor: pointer;"
               wire:click="removeComment({{$comment->id}})"></i>
        </div>
    </div>
        @endforeach
    @if($comments->isNotEmpty())
    <div class="d-flex justify-content-center mt-4">
        {{ $comments->links() }}
    </div>
    @endif
</div>

پس در کامپوننت Comments داریم:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;

class Comments extends Component
{
    public $comments;
    public $newComment;

    public function mount()
    {
        $this->comments = Comment::latest()->paginate(2);
    }

    public function addComment()
    {
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
        $this->comments = Comment::latest()->paginate(2);
    }

    public function removeComment($commentId)
    {
        $comment = Comment::find($commentId)->delete();
    }

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

اکنون اگر صفحه‌ی پروژه را در مرورگر خود Refresh کنید، با اخطار زیر مواجه می‌شوید:

Livewire چیست

با استفاده از Paginator لاراول، نظرات به صورت شیء برگشت داده می‌شوند و چون در خصوصیات public کامپوننت‌ها در Livewire، نمی‌توان شیء ذخیره کرد، به اخطار بالا برمی‌خوریم.

پس نیاز است که خصوصیت comments و متد ()mount را حذف کنیم و نظرات را به ()view در متد ()render پاس دهیم:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;

class Comments extends Component
{
    public $newComment;

    public function addComment()
    {
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
    }

    public function removeComment($commentId)
    {
        $comment = Comment::find($commentId)->delete();
    }

    public function render()
    {
        return view('livewire.comments', [
            'comments' => Comment::latest()->paginate(2),
        ]);
    }
}

که خروجی به شکل زیر خواهد بود:

Livewire چیست

اکنون اگر روی صفحات دیگر کلیک کنید، مشاهده خواهید کرد که صفحات از نو بارگذاری می‌شوند. برای جلوگیری از این کار، در کامپوننت Comments، کد زیر را اضافه کنید:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;
use Livewire\WithPagination;

class Comments extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

    public $newComment;

    public function addComment()
    {
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
    }

    public function removeComment($commentId)
    {
        $comment = Comment::find($commentId)->delete();
    }

    public function render()
    {
        return view('livewire.comments', [
            'comments' => Comment::latest()->paginate(2),
        ]);
    }
}

WithPagination یک Trait مربوط به Livewire است که با استفاده از آن در کامپوننت‌ها، می‌توان بدون نیاز به بارگذاری مجزای هر صفحه و با درخواست‌های Ajax، عملیات صفحه بندی را پیاده‌سازی کرد.

چون ما از Bootstrap در پروژه‌‌ی خود استفاده می‌کنیم، با افزودن خصوصیت paginationTheme و اختصاص مقدار bootstap به آن، می‌توانیم همانند لاراول، از تم Bootstrap برای نمایش صفحه‌بندی استفاده کنیم.

اعتبارسنجی

در این مرحله، می‌خواهیم نظرهای ورودی را اعتبارسنجی کنیم و اخطارهای مربوطه را برای کاربر نمایش دهیم. پیغام‌های اخطار با استفاده از متغیر $message در View قابل دسترسی هستند. پس در فایل comments.blade.php در مسیر resources/views/livewire که همان خروجی کامپوننت است، یک تگ div برای نمایش Errorها ایجاد کنید:

<div class="mx-3">
    <h1 style="font-size: 2rem">Comments</h1>

    @error('newComment') <div class="alert-danger p-3 rounded">{{ $message }}</div> @enderror

    <form class="my-4 d-flex" wire:submit.prevent="addComment">
        <input type="text" class="w-100 rounded border shadow py-2 px-3 mr-2 my-2" placeholder="Write your comment here..." wire:model.debounce.500ms="newComment">
        <div class="py-2">
            <button type="submit" class="p-2 btn btn-success w-20 rounded shadow text-white">Add</button>
        </div>
    </form>
        @foreach($comments as $comment)
    <div class="rounded border shadow p-3 my-2">
        <div class="d-flex justify-content-between my-2">
            <div class="d-flex">
                <p>{{ $comment['body'] }}</p>
            </div>
            <i class="fas fa-times text-danger" style="cursor: pointer;"
               wire:click="removeComment({{$comment->id}})"></i>
        </div>
    </div>
        @endforeach
    @if($comments->isNotEmpty())
    <div class="d-flex justify-content-center mt-4">
        {{ $comments->links() }}
    </div>
    @endif
</div>

و سپس کامپوننت Comments در مسیر app/Http/Livewire را با استفاده از متد ()validate مربوط به Livewire، به شکل زیر بروز کنید:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;
use Livewire\WithPagination;

class Comments extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

    public $newComment;

    public function addComment()
    {
        $this->validate(['newComment' => 'required|max:255']);
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
    }

    public function removeComment($commentId)
    {
        $comment = Comment::find($commentId)->delete();
    }

    public function render()
    {
        return view('livewire.comments', [
            'comments' => Comment::latest()->paginate(2),
        ]);
    }
}

برای آن‌که اعتبارسنجی به شکل Real-Time انجام شود، می‌توانیم از یک Lifecycle Hook دیگر با نام ()updated استفاده کنیم. متد زمانی اجرا می‌شود که داده‌ی مربوط به تگ‌ HTML که در آن‌ از wire:model استفاده کرده‌ایم، تغییر کند و درخواست‌ Ajax مربوط به آن، به سمت سرور ارسال شود. این متد دو پارامتر ورودی می‌گیرد که پارامتر اول همان خصوصیت کامپوننت (در اینجا newComment) و پارامتر دوم مقدار تازه‌ی آن خصوصیت است. ما به منظور اجرای اعتبارسنجی، فقط به پارامتر اول نیاز داریم. پس در کامپوننت Comments، از تابع ()validateOnly مربوط به Livewire برای اعتبارسنجی نظر جدید استفاده می‌کنیم:

<?php

namespace App\Http\Livewire;

use App\Comment;
use Livewire\Component;
use Livewire\WithPagination;

class Comments extends Component
{
    use WithPagination;

    protected $paginationTheme = 'bootstrap';

    public $newComment;

    public function updated($field)
    {
        $this->validateOnly($field, ['newComment' => 'required|max:255']);
    }

    public function addComment()
    {
        $this->validate(['newComment' => 'required|max:255']);
        $newComment = Comment::create([
            'body' => $this->newComment,
            'user_id' => 1
        ]);

        $this->newComment = '';
    }

    public function removeComment($commentId)
    {
        $comment = Comment::find($commentId)->delete();
    }

    public function render()
    {
        return view('livewire.comments', [
            'comments' => Comment::latest()->paginate(2),
        ]);
    }
}

اکنون می‌توانید به راحتی، از ویژگی اعتبارسنجی Real-Time در Livewire استفاده کنید و از مزایای آن بهره ببرید. با وارد کردن نظرات مختلف در صفحه‌ی پروژه، ملاحظه می‌کنید که پیغام اخطار به صورت کاملا پویا نمایش داده می‌شود و در صورت لزوم تغییر می‌کند.

هم‌چنین، هنگامی که مقدار زمان در عبارت "wire:model.debounce.500ms="newComment در تگ input را کاهش می‌دهیم، با افزایش تعداد درخواست‌های ارسالی به سمت سرور، سرعت نمایش پیغام اخطار کاهش می‌یابد.

قسمت دیگر این آموزش:

جمع‌بندی:

در این مقاله از سری مقالات آموزش لاراول و در ادامه‌ی مجموعه‌ی مقالات Livewire چیست، توانستیم با ویژگی‌های بیشتری از Livewire آشنا شویم و نحوه‌ی استفاده از آن‌ها را به صورت عملی فراگیریم. ارتباط با دیتابیس را برقرار و نظرات را در جدول مربوطه ذخیره کردیم. قابلیت حذف نظرات را به اپلیکیشن افزودیم و توانستیم صفحه‌بندی نظرات را بدون نیاز به ریفرش شدن صفحه، پیاده سازی کنیم. همچنین، قابلیت جذابی از Livewire که شامل اعتبارسنجی به صورت Real-Time است را نیز پیاده‌سازی کرده و کارکرد آن را به صورت عملی مشاهده کردیم.

در قسمت بعدی از مجموعه مقالات Livewire چیست، ویژگی‌های جذاب دیگری از این فریم ورک فول استک را با هم بررسی خواهیم کرد. پروژه‌ای که با هم ایجاد کردیم را بیش از پیش توسعه خواهیم داد و قابلیت آپلود فایل را به آن می‌افزاییم.

خوش‌حال می‌شویم نظرات، تجربیات و سوالات خود را با ما و سایر کاربران سون لرن به اشتراک بگذارید.

اگر به یادگیری بیشتر لاراول علاقه دارید می‌توانید در دوره آموزشی لاراول کاربردی (بسته پروژه محور) شرکت کنید، این دوره شامل ۱۲ پروژه کاربردی و پر استفاده در دنیای واقعی است، که تمامی پروژه‌ها به صورت کامل برنامه‌ نویسی خواهند شد، تا دانشجو بتواند با روند ایجاد و تکمیل پروژه به صورت کامل آشنا شود.

چه امتیازی به این مقاله می دید؟
نویسنده رضا زیدی
از یادگیری ، عمل‌گرایی و چالش‌های مربوطه ، لذت می‌برم ...

نظرات کاربران

اولین دیدگاه این پست رو تو بنویس !

ارسال دیدگاه
خوشحال میشیم دیدگاه و یا تجربیات خودتون رو با ما در میون بذارید :