Jamming Out with Laravel Livewire

May 03, 2020

Taking asynchronous back to the future

I first saw Laravel Livewire at Laracon Online back in February, and my co-workers and I were all pretty excited to try it out. During the convention, Livewire creator Caleb Porzio (@calebporzio) demonstrated his new (old) way of thinking about asynchronous, which really gets back to a more traditional method of creating a dynamic DOM. Just like back in the day, Livewire will return the actual HTML as a string to be displayed within the browser, rather than make a request to an API and have it return, say, an array of JSON objects. Leveraging Laravel's component feature to boot, Livewire is intriguing, and seemed worth giving a test drive.

I should say that Caleb's documentation is pretty great and would be a much better place to start if you're looking to begin learning Livewire. The purpose of this blog is really to get a working example and to share my thoughts on the framework/package.


Installation

Create our project

Just to keep things clean, I am going to create a fresh, brand-spankin' new Laravel project. We will name the project livewire-demo.

$ composer create-project laravel/laravel livewire-demo

Install Livewire

$ cd livewire-demo && composer require livewire/livewire

Include Livewire assets

If you started a fresh application, you can use the Laravel 7 syntax. Older versions will need to use the bottom syntax. We are just going to use the welcome.blade.php template that comes out of the box with a new Laravel project just to get started quickly.

Laravel 7+
resources/views/welcome.blade.php
<head>
    ... // All the other stuff in <head>
    <livewire:styles>
</head>
<body>
    ... // All the other stuff in <body>
    <livewire:scripts>
</body>
Older versions
resources/views/welcome.blade.php
<head>
    ... // All the other stuff in <head>
    @livewirestyles
</head>
<body>
    ... // All the other stuff in <body>
    @livewirescripts
</body>

Tidying up before getting started

I removed most of the styles in place, leaving just the font and some basic styles on the body to make things more aesthetically tolerable while we are working on this. This is my final Blade template.

resources/views/welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">

        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Nunito', sans-serif;
                font-weight: 200;
                height: 100vh;
                margin: 0;
                text-align: center;
            }
        </style>

        <livewire:styles>
    </head>
    <body>
        <div>
            <h1>Livewire Demo</h1>
        </div>

        <livewire:scripts>
    </body>
</html>

Start the server

Just for simplicity, we are going to use php artisan serve.

From terminal
$ php artisan serve

Laravel development server started: http://127.0.0.1:8000

Setting up

Having been working in Spotify recently, let's follow suit and say we are going to create a basic application for my vinyl collection. Here is what I am envisioning:

  1. Create an Album model with basic info like artist and release date and its affiliated migration file
  2. Create AlbumFactory and AlbumSeeder classes to populate the database with some dummy test albums just for our demo
  3. Create an AlbumSearch component powered by Livewire that will dynamically pull down these albums as we type in the search bar.

Getting set up

Create our model, factory, and seeder classes

To start we can create our Album model and migration using the make:model command with the -m flag to optionally create the migration at the same time. Let's go ahead and chain on our command to create our AlbumFactory and AlbumSeeder, as well.

From terminal
$ php artisan make:model Album -m && php artisan make:factory AlbumFactory && php artisan make:seeder AlbumSeeder
database/migrations/2020_04_16_180906_create_albums_table.php
<?php

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

class CreateAlbumsTable extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
   public function up()
   {
       Schema::create('albums', function (Blueprint $table) {
           $table->id();
           $table->string('artist');
           $table->string('name');
           $table->string('cover_image')->default('https://placehold.it/200x200');
           $table->date('release_date');
           $table->timestamps();
       });
   }

   /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   {
       Schema::dropIfExists('albums');
   }
}
database/factories/AlbumFactory.php
<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Album;
use Faker\Generator as Faker;

$factory->define(Album::class, function (Faker $faker) {
    return [
        'artist' => $faker->name,
        'name' => $faker->sentence,
        'cover_image' => $faker->imageUrl(200,200),
        'release_date' => $faker->dateTimeBetween(), // Defaults to between now and 30 years ago
    ];
});
database/seeders/AlbumSeeder.php
<?php

use Illuminate\Database\Seeder;

class AlbumSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        factory(\App\Album::class, 20)->create();
    }
}
Migrate & Seed

Run our migrations and then seed the database with our seeder.

From terminal
$ php artisan migrate && php artisan db:seed

Creating the Livewire Component

Use artisan to create a Livewire component

Livewire gives us a handy Artisan command that we can use to create a new component. Passing album-search to the make:livewire command will generate two files: a Laravel Component, located in app/Http/Livewire/AlbumSearch.php, and a Blade template, located in resources/views/livewire/album-search.php. Properties you set on the component, such as search below, are accessible within the Blade template using wire:model.

From terminal
$ php artisan make:livewire album-search
App/Http/Livewire/AlbumSearch.php
<?php

namespace App\Http\Livewire;

use App\Album;
use Livewire\Component;

class AlbumSearch extends Component
{
    public $search = '';

    public function render()
    {
        return view('livewire.album-search', [
            'albums' => Album::where('artist', 'LIKE', "%$this->search%")->get(),
        ]);
    }
}
resources/views/livewire/album-search.php
<div>
    <input wire:model="search" type="text" placeholder="Search albums..."/>

    <ul>
        @foreach($albums as $album)
            <li>{{ $album->artist }}</li>
        @endforeach
    </ul>
</div>

Wrapping up

I think my biggest takeaway from test driving Livewire is how much it actually feels like I am using a Javascript framework like React or Vue. Setting the properties on the PHP class feels very much like accessing state in React or a data value in Vue. I love the intuitive file structure for components and their Blade templates.

While I will probably continue to use Javascipt, the advantages to using Livewire instead would be that I can keep everything within the Laravel ecosystem. I could leverage things like the Laravel Debug Bar that I don't get to easily take advantage of when using a decoupled Javascript application for my front end. Caleb's documentation is fantastic, which goes a long way these days. It is clear he is passionate about the project, and generally I feel like it's a safe bet that Livewire will continue to grow and improve over time because of that. Overall, I enjoyed working in it and might use it again for some smaller pieces in an application where I don't want to pull in a whole new Javascript framework.

Join my mailing list to stay updated with web development news.

About the Author

Jed Darrohn is a software developer that specializes in Laravel, Vue.js, and React. He lives in Denver, Colorado with his Australian Shepherd, Bessie.

© 2021 Jed Darrohn

Sitemap