Laravel + livewireで誕生日から年齢を自動計算するサンプル

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、このブログに記事を書くために普段からいろいろな情報を集めるようにしているのですが、それでもはやり限界があって全ての情報を取得することは難しいものです。

先日もクライアントさんに教えていただいたのですが、どうやら livewire というLaravelのコンポーネント・システムが公開されているとのことでした。(いつも有益な情報ありがとうございます😊✨)

早速調べたところ、livewireのコンセプトは「最近のJavaScriptはちょっとしたことするだけなのに、複雑な作業が必要。もう、そういうのやめよう!」というものでした。

たしかに、最近のJavaScript開発は、npmを使って変更をwatchして、ビルドの完了を待って、やっとできたと思ったらまた変更が必要で・・・再読込が追いつかない・・・(以下繰り返し)

みたいな状況になるので、livewireのコンセプトにとても賛成です。(私自身もビルドはnpmのパッケージのみで独自のコードは直接Bladeに書き込む形式をとっています)

そこで!

今回は、そんな気になるlivewireの使い方を分かりやすくまとめてみることにしました。

ぜひ皆さんのお役に立てると嬉しいです😊✨

開発環境: Laravel 5.8

livewireの仕組み

livewireといってもcomposerのパッケージのひとつで、Laravelのテンプレート・エンジンBladeでコンポーネントを描画します。

そして、コンポーネントの内容をリアルタイムに変更(例えば、テキストの表示/非表示の切り替え)ができるのですが、これはAjaxを通してPHP側からHTMLを取得します。

そして、その通信はlivewireがやってくれるので独自にコードを書く必要はありません。

やりたいこと

今回は、以下のように誕生日(年・月・日)を入力すると自動的に年齢を計算して表示してくれるコンポーネント「birthday」を作ってみます。

なお、「日」のセレクトボックスは各月に合わせて28日〜31日が自動的に変更されるようにし、さらに「うるう年」の場合は「2月29日」も表示するようにします。

では、実際にlivewireをインストールしてコードを書いてみましょう!

livewireをインストールする

先ほども言いましたがlivewirecomposerにパッケージが用意されていますので、以下のコマンドだけでインストールが完了します。

composer require calebporzio/livewire

livewireに必要なファイルを作成する

ファイルの作成はlivewireが用意してくれているartisanコマンドで作成することができます。

以下のコマンドを実行してください。

php artisan make:livewire birthday

すると、以下2つのファイルが自動的に作成されます。

  • /app/Http/Livewire/Birthday.php ・・・ コンポーネントを管理するPHPクラス
  • /resources/views/livewire/birthday.blade.php ・・・ コンポーネントのビュー

コンポーネントに必要なコードを追加する

先ほど作成したファイルに必要なコードを追加していきます。
それぞれみていきましょう。

PHPクラス

中身はlivewireが用意しているComponetクラスを拡張する形になっています。中身を以下のように変更してください。

/app/Http/Livewire/Birthday.php

<?php

namespace App\Http\Livewire;

use Carbon\Carbon;
use Livewire\Component;

class Birthday extends Component
{
    // ここの変数がビュー内で変数として使える
    public $year = 0;
    public $month = 0;
    public $day = 0;
    public $age = -1;
    public $last_day_of_month = 0;

    // 準備が完了したら実行される
    public function mount($year = 0, $month = 0, $day = 0) {

        $this->year = $year;
        $this->month = $month;
        $this->day = $day;
        $this->onChange();

    }

    // 入力ボックスに変更があった場合に呼ばれる
    public function onChange()
    {
        $year = intval($this->year);
        $month = intval($this->month);
        $day = intval($this->day);

        // 該当月の日(28〜31日)を計算
        if($year > 0 && $month > 0) {

            $this->last_day_of_month = Carbon::create($this->year, $this->month)->endOfMonth()->day;

        }

        // 年齢を計算
        if(checkdate($month, $day, $year)) {

            $this->age = Carbon::createFromDate($this->year, $this->month, $this->day)->age;

        } else {

            $this->age = -1;

        }
    }

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

まず、ここで重要なのが「publicメンバ変数」です。
今回のコードでは5つ変数を宣言していますが、これらは自動的に/resources/views/livewire/birthday.blade.phpの中で、通常の変数として利用することができます。

{{ $year }}
{{ $month }}
{{ $day }}
{{ $age }}
{{ $last_day_of_month }}

続いてmount()ですが、これはコンポーネントの準備ができた時点で呼ばれるメソッドです。

コンポーネントの呼び出しは以下のようになりますが、このmount()に引数を用意しているとその次のようにデフォルト値を指定することも可能になります。

@livewire('birthday')

デフォルト値あり↓↓↓

@livewire('birthday', 2000, 12, 31)

また、onChange()は(年・月・日)が変更されたときに実行されるメソッドですが、この中では以下2つのことを行っています。

  • 「日」のセレクトボックスの内容を変更(28日〜31日)
  • 年齢を計算

ビュー

では、ビューにもコードを追加していきましょう。

/resources/views/livewire/birthday.blade.php

<div>

    <!-- 年 -->
    <select name="birth-year" wire:model="year" wire:change="onChange">
        <option></option>
        @for($i = 1900 ; $i <= date('Y') ; $i++)
        <option value="{{ $i }}">{{ $i }}年</option>
        @endfor
    </select>

    <!-- 月 -->
    <select name="birth-month" wire:model="month" wire:change="onChange">
        <option></option>
        @for($i = 1 ; $i <= 12 ; $i++)
        <option value="{{ $i }}">{{ $i }}月</option>
        @endfor
    </select>

    <!-- 日 -->
    <select name="birth-day" wire:model="day" wire:change="onChange">
        <option></option>
        @for($i = 1 ; $i <= $last_day_of_month ; $i++)
        <option value="{{ $i }}">{{ $i }}日</option>
        @endfor
    </select>

    <!-- 年齢 -->
    @if($age > -1)
        &nbsp;/&nbsp;{{ $age }} 才
    @endif

</div>

この中では、(年・月・日)のセレクトボックスと年齢を表示しているだけですが、重要なのは「日」のセレクトボックスにある$last_day_of_monthの部分です。なぜなら、この数字が条件によって28日〜31日に変更されることになるからです。

また、年齢は-1(初期値)の場合は表示をしないようにしています。

コンポーネントを表示させる

では、ここまでで作成したコンポーネントをLaravelのページに表示させてみます。

とはいっても、livewire専用のディレクティブが用意されているのでビュー内で以下のようにするだけです。

<html>
<head>
    @livewireStyles
</head>
<body>
<div>
    @livewire('birthday')
</div>
@livewireScripts
</body>
</html>

【追記:2020.3.21】バージョンアップによる変更があったため修正しました。過去バージョンでは@livewireStyles@livewireScriptsの代わりに@livewireAssetsを使ってください。

@livewire('*****')がコンポーネント本体、そして@livewireStyles@livewireScriptsがスタイルシートとJavaScriptを描画する部分になります。

テストしてみる(動画)

では、今回作成したlivewireコンポーネントを実行してみましょう!(2000年はうるう年なので、2月が29日まであることに注目して見てください)

うまくいきました!

お疲れ様でした😊✨

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回ははじめてlivewireに挑戦してみましたが、使ってみた感想としては、「直感的で使いやすい!」でした。

というのも、livewireと言ってもテンプレートエンジンはBladeが使えますし、PHP側も通常よくあるクラスのパターンと同じなので、Laravelを使ってる方でしたらすぐ使えるようになると思います。JavaScriptコードもすでに用意してくれていますしね😚

ただ、一点だけこれからの開発に期待したい部分があって、それが「バインディングデータをJavaScript側から取得しやすくしてほしい」というものでした。

というのも、livewireコンポーネント内の値を取得するには、document.getElementByIddocument.querySelectorを使って取得する必要があるようなのですが、コンポーネントを同じページで複数使う場合は少しややこしくなってしまいます。

そのため、例えば以下のようにrefidを指定できるようにして・・・

<!-- 注:このやり方は存在しません -->

@livewire('birthday')
    @ref('my-birthday')
@endlivewire

<lw:birthday id="partners-birthday"></lw:birthday>

Vueのように値が直接アクセスできればより便利かなと感じました。

// 注:このやり方は存在しません
livewire.$refs['my-birthday'].year;

といっても、現時点でGitHubのスターが781となっていて相当注目を集めているので、きっとこれから進化していくと思います。ということで、私もこれからのlivewireに注目したいと思います。(時間が出来たらpull requestとかしてみようかな)

ぜひ、皆さんもlivewireに挑戦してみてくださいね。

ではでは〜!

このエントリーをはてなブックマークに追加       follow us in feedly