4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel livewire】使う変数をプロパティで宣言するかViewに渡すか問題🔍

Posted at

結論

『値が変動する物』はプロパティに宣言
『値が変動しない物』はviewに渡す

そもそもの違い

プロパティで宣言してようがViewに渡そうがBlade内では同じように扱えますが全然違います。

プロパティ

プロパティで宣言した変数はJsonでフロントエンドとバックエンドで同期を行います。

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Sample0907 extends Component
{
    public $hoge = 'hogeValue';
    public $huga = 'hugaValue';
.......

Render内でviewに渡す

HTMLを生成する時にviewに渡しているだけです。
コントローラーなどで変数をbladeに渡しているのと同じです。

return view('hoge',compact('hoge'))

プロパティで宣言する時の注意点

配列が挿入順に回らない場合がある

例えば、このように配列をプロパティとして宣言するとします

class Sample0907 extends Component
{
    public $array = [];

    public function mount()
    {
        $array = [
            2 => '1番目',
            0 => '2番目',
            1 => '3番目'
        ];

        $this->array = $array;
    }

Bladeでdd()してみます。
スクリーンショット 2022-09-07 18.31.29.png
はい、勝手にソートされてます。

Livewireのソースを調べてみると、ソートしている箇所を見つけました。

[Laravelプロジェクト]/vendor/livewire/livewire/src/HydrationMiddleware/NormalizeDataForJavaScript.php
        $itemsWithNumericKeys = array_filter($value, function ($key) {
            return is_numeric($key);
        }, ARRAY_FILTER_USE_KEY);
        ksort($itemsWithNumericKeys);

ですので、セレクトボックスの項目などを

<select name="name" id="name">
@foreach($array as $key => $value)
  <option value="{{ $key }}">{{ $value }}</option>
@endforeach
</select>

のように書きたい場合、DBから取得したものを並べたい順にして生成しても
キーの連番に並び替えられます。

オブジェクトは配列に変換される

このようにオブジェクト群を内包した配列と、入力用の変数を1つ用意します。

class Sample0907 extends Component
{
    public $array = [];
    
    public $text;
    
    public function mount()
    {
        $array = [
            (object)['id' => 1, 'name' => '田中'],
            (object)['id' => 2, 'name' => '源田']
        ];

        $this->array = $array;
    }

Bladeも書きます

<div>
    @foreach($array as $key => $value)
        {{ $value->name }}<br/>
    @endforeach
    <input type="text" wire:model="text" />
</div>

スクリーンショット 2022-09-07 18.48.55.png

初回アクセスは問題ありません。

入力エリアに何か文字を入れてみましょう。
スクリーンショット 2022-09-07 18.49.41.png

はい、死にました。

どうやらLaravelのRequestの中でjsonが強制的に配列になるっぽいです

@hulkurLivewire は stdObjects を再水和できないため、そのような動作が発生することを期待しています。そのため、それらは配列として終了します。その理由は、Laravel リクエスト オブジェクトです。json_decode を実行すると、json オブジェクトが強制的に配列になります。この問題を参照してくださいlaravel/framework#443

詳しくコードを追えてる訳では無いのですが

Modelオブジェクトや、Model群を内包しているコレクションは特別扱いされてるみたいです。
以下のコードには記載されてませんがcarbonオブジェクトもです。

src/HydrationMiddleware/HydratePublicProperties.php
    protected static function dehydrateModel($value, $property, $response, $instance)
    {
        $serializedModel = $value instanceof QueueableEntity && ! $value->exists
            ? ['class' => get_class($value)]
            : (array) (new static)->getSerializedPropertyValue($value);

        // Deserialize the models into the "meta" bag.
        data_set($response, 'memo.dataMeta.models.'.$property, $serializedModel);

        $filteredModelData = static::filterData($instance, $property);

        // Only include the allowed data (defined by rules) in the response payload
        data_set($response, 'memo.data.'.$property, $filteredModelData);
    }

    protected static function dehydrateModels($value, $property, $response, $instance)
    {
        $serializedModel = (array) (new static)->getSerializedPropertyValue($value);

        // Deserialize the models into the "meta" bag.
        data_set($response, 'memo.dataMeta.modelCollections.'.$property, $serializedModel);

        $filteredModelData = static::filterData($instance, $property);

        // Only include the allowed data (defined by rules) in the response payload
        data_set($response, 'memo.data.'.$property, $filteredModelData);
    }

ですので、livewireでstdclassをプロパティとして扱うのはやめておきましょう。

プロパティをカスタムしたい場合

ドキュメントに記載されてます。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?