Laravel + livewire 年齢算出


laravelを使った開発が一旦暇になったのでlaravel8にあるlivewireを試しにいじってみました。
ある方の記事を参考に進めていった際2箇所ほどエラーにあったのでその際の記録。
(参考にした記事は誕生日から年齢を算出するものです。)

livewireをインストール

composer require calebporzio/livewire

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

php artisan make:livewire birthday

以下のファイルが作成される

app/Http/Livewire/Birthday.php
resources/views/livewire/birthday.blade.php

年齢算出処理作成

app/Http/Livewire/Birthday.php

<?php

namespace App\Http\Livewire;

use Carbon\Carbon;
use Livewire\Component;

class Birthday extends Component
{
    /** bladeとのデータ共有プロパティ */
    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');
    }
}

ビュー作成

resources/views/livewire/birthday.blade.php

<div>
    {{--  --}}
    {{ Form::select('birth-year',
        array_combine(range(1950, date("Y")), range(1950, date("Y"))),
        '', [
        'wire:model' => 'year',
        'wire:change' => 'onChange',
    ])}}
    {{--  --}}
    {{ Form::select('birth-month',
        array_combine(range(1, date("m")), range(1, date("m"))),
        '', [
        'wire:model' => 'month',
        'wire:change' => 'onChange',
    ])}}
    {{--  --}}
    {{ Form::select('birth-day',
        array_combine(range(1, $last_day_of_month), range(1, $last_day_of_month)),
        '', [
        'wire:model' => 'day',
        'wire:change' => 'onChange',
    ])}}
    {{-- 年齢 --}}
    @if($age > -1)
        / {{ $age }}
    @endif
</div>

呼び出したいblade箇所で以下のように呼び出します。

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

1つ目のエラー

Call to undefined method CompilerEngine::startLivewireRendering()

参考記事主さんが質問していました。
https://github.com/livewire/livewire/issues/711

bootstrap/cache/packages.php

facade/ignitionを
livewire/livewireの上に移動すれば解決とな。

2つめのエラー

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

呼び出し箇所を上記のようにしたら以下のエラー。

array_intersect_key(): Expected parameter 1 to be an array, int given (View: {ファイルパス}\index.blade.php)

エラー発生箇所は以下。

vendor\calebporzio\livewire\src\LifecycleManager.php

public function mount($params = [])
{
    // Assign all public component properties that have matching parameters.
    collect(array_intersect_key($params, $this->instance->getPublicPropertiesDefinedBySubClass()))
            ->each(function ($value, $property) {
                $this->instance->{$property} = $value;
            });

@livewire('birthday', 2000, 12, 31)で呼び出すと$paramsには'2000'がきていました。

$paramsには配列が来る想定だけど文字列がきているのが原因のようです。
以下のように呼び出せば解決しました。

@livewire('birthday', ['year' => 2000, 'month' => 12, 'day' =>31])

routeの第2引数の書き方と同じ要領。

参考記事