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
<?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

```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箇所で以下のように呼び出します。

```php
<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つめのエラー

```php
@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

```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には配列が来る想定だけど文字列がきているのが原因のようです。
以下のように呼び出せば解決しました。

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

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

## 参考記事
https://blog.capilano-fw.com/?p=4466