シンセサイザ
Livewireコンポーネントは、リクエスト間でJSONにデハイドレート(シリアライズ)され、PHPコンポーネントにハイドレート(アンシリアライズ)されるため、そのプロパティはJSONシリアライズ可能である必要があります。Because Livewire components are dehydrated (serialized) into JSON, then hydrated (unserialized) back into PHP components between requests, their properties need to be JSON-serializable.
ネイティブに、PHPはほとんどのプリミティブ値を簡単にJSONにシリアライズします。しかし、Livewireコンポーネントがより洗練されたプロパティ型(モデル、コレクション、Carbonインスタンス、Stringableなど)をサポートするためには、より堅牢なシステムが必要です。Natively, PHP serializes most primitive values into JSON easily. However, in order for Livewire components to support more sophisticated property types (like models, collections, carbon instances, and stringables), a more robust system is needed.
したがって、Livewireは「Synthesizers」と呼ばれる拡張ポイントを提供し、ユーザーは任意のカスタムプロパティ型をサポートできます。Therefore, Livewire provides a point of extension called "Synthesizers" that allow users to support any custom property types they wish.
ハイドレーションに関するドキュメントを読むことで、より詳しく学ぶことができます。[!tip] Make sure you understand hydration first Before using Synthesizers, it's helpful to fully understand Livewire's hydration system. You can learn more by reading the hydration documentation[/docs/hydration].
Tip: まずハイドレーションを理解してください Synthesizersを使用する前に、Livewireのハイドレーションシステムを完全に理解しておくことをお勧めします。
Synthesizersの理解Understanding Synthesizers
カスタムSynthesizersの作成を検討する前に、LivewireがLaravel Stringablesをサポートするために使用する内部Synthesizerを見てみましょう。Before exploring the creation of custom Synthesizers, let's first look at the internal Synthesizer that Livewire uses to support Laravel Stringables[https://laravel.com/docs/strings].
アプリケーションに次のCreatePost
コンポーネントが含まれているとします。Suppose your application contained the following CreatePost
component:
class CreatePost extends Component
{
public $title = '';
}
リクエスト間で、Livewireはこのコンポーネントの状態を次のようなJSONオブジェクトにシリアライズするかもしれません。Between requests, Livewire might serialize this component's state into a JSON object like the following:
state: { title: '' },
次に、$title
プロパティの値がプレーンな文字列ではなくStringableであるより高度な例を考えてみましょう。Now, consider a more advanced example where the $title
property value is a stringable instead of a plain string:
class CreatePost extends Component
{
public $title = '';
public function mount()
{
$this->title = str($this->title);
}
}
このコンポーネントの状態を表すデハイドレートされたJSONには、プレーンな空文字列の代わりにメタデータタプルが含まれています。The dehydrated JSON representing this component's state now contains a metadata tuple[/docs/hydration#deeply-nested-tuples] instead of a plain empty string:
state: { title: ['', { s: 'str' }] },
Livewireは、このタプルを使用して、次のリクエストで$title
プロパティをStringableにハイドレートできます。Livewire can now use this tuple to hydrate the $title
property back into a stringable on the next request.
Synthesizersの外部からの効果を見てきたので、Livewireの内部Stringableシンセの実際のソースコードを以下に示します。Now that you've seen the outside-in effects of Synthesizers, here is the actual source code for Livewire's internal stringable synth:
use Illuminate\Support\Stringable;
class StringableSynth extends Synth
{
public static $key = 'str';
public static function match($target)
{
return $target instanceof Stringable;
}
public function dehydrate($target)
{
return [$target->__toString(), []];
}
public function hydrate($value)
{
return str($value);
}
}
これを一つずつ分解してみましょう。Let's break this down piece by piece.
最初は$key
プロパティです。First is the $key
property:
public static $key = 'str';
すべてのシンセは、['', { s: 'str' }]
のようなメタデータタプルをStringableに変換するためにLivewireが使用する静的な$key
プロパティを含んでいる必要があります。気づいたかもしれませんが、各メタデータタプルには、このキーを参照するs
キーがあります。Every synth must contain a static $key
property that Livewire uses to convert a metadata tuple[/docs/hydration#deeply-nested-tuples] like ['', { s: 'str' }]
back into a stringable. As you may notice, each metadata tuple has an s
key referencing this key.
逆に、Livewireがプロパティをデハイドレートしている場合、シンセの静的なmatch()
関数を使用して、この特定のSynthesizerが現在のプロパティをデハイドレートするのに適した候補であるかどうかを識別します($target
はプロパティの現在の値です)。Inversely, when Livewire is dehydrating a property, it will use the synth's static match()
function to identify if this particular Synthesizer is a good candidate to dehydrate the current property ($target
being the current value of the property):
public static function match($target)
{
return $target instanceof Stringable;
}
match()
がtrueを返した場合、dehydrate()
メソッドを使用して、プロパティのPHP値を入力として受け取り、JSON化可能なメタデータタプルを返します。If match()
returns true, the dehydrate()
method will be used to take the property's PHP value as input and return the JSONable metadata[/docs/hydration#deeply-nested-tuples] tuple:
public function dehydrate($target)
{
return [$target->__toString(), []];
}
さて、次のリクエストの開始時に、このSynthesizerがタプル内の{ s: 'str' }
キーによって一致された後、hydrate()
メソッドが呼び出され、プロパティの生のJSON表現が渡され、プロパティに割り当てるための完全なPHP互換の値が返されることが期待されます。Now, at the beginning of the next request, after this Synthesizer has been matched by the { s: 'str' }
key in the tuple, the hydrate()
method will be called and passed the raw JSON representation of the property with the expectation that it returns the full PHP-compatible value to be assigned to the property.
public function hydrate($value)
{
return str($value);
}
カスタムSynthesizerの登録Registering a custom Synthesizer
カスタムプロパティをサポートするために独自のSynthesizerを作成する方法を示すために、次のUpdateProperty
コンポーネントを例として使用します。To demonstrate how you might author your own Synthesizer to support a custom property, we will use the following UpdateProperty
component as an example:
class UpdateProperty extends Component
{
public Address $address;
public function mount()
{
$this->address = new Address();
}
}
Address
クラスのソースコードを以下に示します。Here's the source for the Address
class:
namespace App\Dtos\Address;
class Address
{
public $street = '';
public $city = '';
public $state = '';
public $zip = '';
}
Address
型のプロパティをサポートするために、次のSynthesizerを使用できます。To support properties of type Address
, we can use the following Synthesizer:
use App\Dtos\Address;
class AddressSynth extends Synth
{
public static $key = 'address';
public static function match($target)
{
return $target instanceof Address;
}
public function dehydrate($target)
{
return [[
'street' => $target->street,
'city' => $target->city,
'state' => $target->state,
'zip' => $target->zip,
], []];
}
public function hydrate($value)
{
$instance = new Address;
$instance->street = $value['street'];
$instance->city = $value['city'];
$instance->state = $value['state'];
$instance->zip = $value['zip'];
return $instance;
}
}
アプリケーションでグローバルに利用できるようにするには、LivewireのpropertySynthesizer
メソッドを使用して、サービスプロバイダーのブートメソッドからシンセサイザーを登録できます。To make it available globally in your application, you can use Livewire's propertySynthesizer
method to register the synthesizer from your service provider boot method:
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Livewire::propertySynthesizer(AddressSynth::class);
}
}
データバインディングのサポートSupporting data binding
上記のUpdateProperty
の例を使用すると、wire:model
バインディングをAddress
オブジェクトのプロパティに直接サポートすることが望ましいでしょう。Synthesizersを使用すると、get()
メソッドとset()
メソッドを使用してこれをサポートできます。Using the UpdateProperty
example from above, it is likely that you would want to support wire:model
binding directly to properties of the Address
object. Synthesizers allow you to support this using the get()
and set()
methods:
use App\Dtos\Address;
class AddressSynth extends Synth
{
public static $key = 'address';
public static function match($target)
{
return $target instanceof Address;
}
public function dehydrate($target)
{
return [[
'street' => $target->street,
'city' => $target->city,
'state' => $target->state,
'zip' => $target->zip,
], []];
}
public function hydrate($value)
{
$instance = new Address;
$instance->street = $value['street'];
$instance->city = $value['city'];
$instance->state = $value['state'];
$instance->zip = $value['zip'];
return $instance;
}
public function get(&$target, $key) // [tl! highlight:8]
{
return $target->{$key};
}
public function set(&$target, $key, $value)
{
$target->{$key} = $value;
}
}