プロパティ
プロパティは、Livewireコンポーネント内のデータを保存/管理します。これらはコンポーネントクラスのpublicなプロパティとして定義し、サーバ側とクライアント側の両方でアクセス/変更できます。Properties store and manage data inside your Livewire components. They are defined as public properties on component classes and can be accessed and modified on both the server and client-side.
プロパティの初期化Initializing properties
コンポーネントのmount()
メソッドで、プロパティの初期値を設定できます。You can set initial values for properties within your component's mount()
method.
以下の例を考えてみましょう。Consider the following example:
<?php
namespace App\Livewire;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class TodoList extends Component
{
public $todos = [];
public $todo = '';
public function mount()
{
$this->todos = Auth::user()->todos; // [tl! highlight]
}
// ...
}
この例で、空のtodos
配列を定義し、認証済みユーザーの既存のtodosで初期化しました。これで、コンポーネントを初めてレンダーするときに、データベース内のすべての既存todosをユーザーへ表示しています。In this example, we've defined an empty todos
array and initialized it with existing todos from the authenticated user. Now, when the component renders for the first time, all the existing todos in the database are shown to the user.
一括代入Bulk assignment
mount()
メソッドで多くのプロパティを初期化すると、冗長に感じることがあります。これに対処するためLivewireは、fill()
メソッドにより複数のプロパティを一度に割り当てる便利な方法を提供しています。プロパティ名とそれぞれの値の連想配列を渡すことにより、複数のプロパティを同時に設定し、mount()
内の繰り返しコードを削減できます。Sometimes initializing many properties in the mount()
method can feel verbose. To help with this, Livewire provides a convenient way to assign multiple properties at once via the fill()
method. By passing an associative array of property names and their respective values, you can set several properties simultaneously and cut down on repetitive lines of code in mount()
.
一例を御覧ください。For example:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Post;
class UpdatePost extends Component
{
public $post;
public $title;
public $description;
public function mount(Post $post)
{
$this->post = $post;
$this->fill( // [tl! highlight]
$post->only('title', 'description'), // [tl! highlight]
); // [tl! highlight]
}
// ...
}
$post->only(...)
は、渡した名前に基づき、モデルの属性と値の連想配列を返すため、$title
および$description
プロパティは、それぞれ個別に設定しなくても、データベースから$post
モデルのtitle
およびdescription
を初期設定します。Because $post->only(...)
returns an associative array of model attributes and values based on the names you pass into it, the $title
and $description
properties will be initially set to the title
and description
of the $post
model from the database without having to set each one individually.
データ結合Data binding
Livewireは、wire:model
HTML属性による双方向データ結合をサポートしています。これにより、コンポーネントのプロパティとHTML入力間でデータを簡単に同期させ、ユーザーインターフェイスとコンポーネントの状態を同期させることができます。Livewire supports two-way data binding through the wire:model
HTML attribute. This allows you to easily synchronize data between component properties and HTML inputs, keeping your user interface and component state in sync.
wire:model
ディレクティブを使用して、TodoList
コンポーネントの$todo
プロパティを基本的な入力要素へ結合してみましょう。Let's use the wire:model
directive to bind the $todo
property in a TodoList
component to a basic input element:
<?php
namespace App\Livewire;
use Livewire\Component;
class TodoList extends Component
{
public $todos = [];
public $todo = '';
public function add()
{
$this->todos[] = $this->todo;
$this->todo = '';
}
// ...
}
<div>
<input type="text" wire:model="todo" placeholder="Todo..."> <!-- [tl! highlight] -->
<button wire:click="add">Add Todo</button>
<ul>
@foreach ($todos as $todo)
<li>{{ $todo }}</li>
@endforeach
</ul>
</div>
上記の例でテキスト入力の値は、"Add Todo"ボタンがクリックされたときに、サーバ上の$todo
プロパティと同期します。In the above example, the text input's value will synchronize with the $todo
property on the server when the "Add Todo" button is clicked.
ここまでは、wire:model
のほんの入り口にすぎません。データ結合の詳細は、フォームに関するドキュメントをご覧ください。This is just scratching the surface of wire:model
. For deeper information on data binding, check out our documentation on forms[/docs/forms].
プロパティのリセットResetting properties
ユーザーがアクションを実行した後、プロパティを初期状態にリセットする必要がある場合がありえます。このような場合に、単一もしくは複数のプロパティ名を受け入れ、それらの値を初期状態にリセットする、reset()
メソッドをLivewireは提供しています。Sometimes, you may need to reset your properties back to their initial state after an action is performed by the user. In these cases, Livewire provides a reset()
method that accepts one or more property names and resets their values to their initial state.
以下の例は、"Add Todo"ボタンがクリックされた後に、$this->reset()
を使用してtodo
フィールドをリセットすることにより、コードの重複を回避しています。In the example below, we can avoid code duplication by using $this->reset()
to reset the todo
field after the "Add Todo" button is clicked:
<?php
namespace App\Livewire;
use Livewire\Component;
class ManageTodos extends Component
{
public $todos = [];
public $todo = '';
public function addTodo()
{
$this->todos[] = $this->todo;
$this->reset('todo'); // [tl! highlight]
}
// ...
}
上記の例で、ユーザーが”Add Todo"をクリックすると、追加されたばかりのtodoを保持している入力フィールドがクリアされ、ユーザーは新しいtodoを書き込むことができます。In the above example, after a user clicks "Add Todo", the input field holding the todo that has just been added will clear, allowing the user to write a new todo.
Warning!
reset()
はmount()
で設定した値では動作ない:reset()
は、mount()
メソッドが呼び出される前のプロパティの状態にリセットします。mount()
でプロパティを別の値に初期化していた場合、プロパティを手作業でリセットする必要があります。[!warning]reset()
won't work on values set inmount()
reset()
will reset a property to its state before themount()
method was called. If you initialized the property inmount()
to a different value, you will need to reset the property manually.
プロパティの取得Pulling properties
もしくは、pull()
メソッドを使用して、値のリセットと取得を1つの操作で行うこともできます。Alternatively, you can use the pull()
method to both reset and retrieve the value in one operation.
上記の同じ例ですが、pull()
で簡略化しています。Here's the same example from above, but simplified with pull()
:
<?php
namespace App\Livewire;
use Livewire\Component;
class ManageTodos extends Component
{
public $todos = [];
public $todo = '';
public function addTodo()
{
$this->todos[] = $this->pull('todo'); // [tl! highlight]
}
// ...
}
上記例では単一の値を取得していますが、pull()
を使用して、すべてまたは一部のプロパティを(キーと値のペアとして)リセットおよび取得することもできます。The above example is pulling a single value, but pull()
can also be used to reset and retrieve (as a key-value pair) all or some properties:
// $this->all()と$this->reset()と同じ
$this->pull();
// $this->only(...)と$this->reset(...)と同じ
$this->pull(['title', 'content']);
サポート済みプロパティの型Supported property types
Livewireは、サーバリクエスト間でコンポーネントデータを管理する独自のアプローチを取っており、そのため限定したプロパティ型をサポートしています。Livewire supports a limited set of property types because of its unique approach to managing component data between server requests.
Livewireコンポーネントの各プロパティは、リクエスト間でJSONへシリアル化(または「デハイドレード」)し、次のリクエストではJSONからPHPへ「ハイドレード」します。Each property in a Livewire component is serialized or "dehydrated" into JSON between requests, then "hydrated" from JSON back into PHP for the next request.
この双方向の変換プロセスには特定の制限があり、Livewireが操作できるプロパティの型が制限されています。This two-way conversion process has certain limitations, restricting the types of properties Livewire can work with.
プリミティブ型Primitive types
Livewireは、文字列、整数などのプリミティブ型をサポートしています。これらの型はJSONとの間で簡単に変換できるため、Livewireコンポーネントのプロパティとして使用するのには理想的です。Livewire supports primitive types such as strings, integers, etc. These types can be easily converted to and from JSON, making them ideal for use as properties in Livewire components.
Livewireは、次のプリミティブプロパティ型をサポートしています。Array
、String
、Integer
、Float
、Boolean
、Null
。Livewire supports the following primitive property types: Array
, String
, Integer
, Float
, Boolean
, and Null
.
class TodoList extends Component
{
public $todos = []; // Array
public $todo = ''; // String
public $maxTodos = 10; // Integer
public $showTodos = false; // Boolean
public $todoFilter; // Null
}
一般的なPHP型Common PHP types
プリミティブ型に加え、LivewireはLaravelアプリケーションで使用される一般的なPHPオブジェクト型をサポートしています。ただし、これらの型は、リクエストごとにJSONへ_デハイドレード_し、PHPへ_ハイドレード_することに注意することとが重要です。これは、プロパティがクロージャなどのランタイム値を保持しない可能性があることを意味します。また、クラス名などのオブジェクトに関する情報がJavaScriptに公開される可能性があります。In addition to primitive types, Livewire supports common PHP object types used in Laravel applications. However, it's important to note that these types will be dehydrated into JSON and hydrated back to PHP on each request. This means that the property may not preserve run-time values such as closures. Also, information about the object such as class names may be exposed to JavaScript.
サポートしているPHP型:Supported PHP types:
型Type | 完全なクラス名Full Class Name |
---|---|
BackedEnumBackedEnum | BackedEnum BackedEnum |
CollectionCollection | Illuminate\Support\Collection Illuminate\Support\Collection |
Eloquent CollectionEloquent Collection | Illuminate\Database\Eloquent\Collection Illuminate\Database\Eloquent\Collection |
ModelModel | Illuminate\Database\Eloquent\Model Illuminate\Database\Eloquent\Model |
DateTimeDateTime | DateTime DateTime |
CarbonCarbon | Carbon\Carbon Carbon\Carbon |
StringableStringable | Illuminate\Support\Stringable Illuminate\Support\Stringable |
[!warning] Eloquent Collections and Models When storing Eloquent Collections and Models in Livewire properties, additional query constraints like select(...) will not be re-applied on subsequent requests.
Warning! Eloquentコレクションとモデル: EloquentコレクションとモデルをLivewire のプロパティに保存する場合、select(…) のような追加のクエリ制約は、後続のリクエストで再適用しません。詳細はEloquentの制約がリクエスト間で保持されないを参照してくださいSee Eloquent constraints aren't preserved between requests[#eloquent-constraints-arent-preserved-between-requests] for more details
これらのさまざまな型としてプロパティを設定する簡単な例を次に示します。Here's a quick example of setting properties as these various types:
public function mount()
{
$this->todos = collect([]); // コレクション
$this->todos = Todos::all(); // Eloquentコレクション
$this->todo = Todos::first(); // モデル
$this->date = new DateTime('now'); // DateTime
$this->date = new Carbon('now'); // Carbon
$this->todo = str(''); // Stringable
}
カスタム型のサポートSupporting custom types
Livewireは、以下の2つの強力なメカニズムを介して、アプリケーションでのカスタム型をサポートしています。Livewire allows your application to support custom types through two powerful mechanisms:
- WireablesWireables
- SynthesizersSynthesizers
Wireablesはシンプルで、ほとんどのアプリケーションで使いやすいため、以下ではこれを詳しく見ていきます。あなたがより柔軟性を必要とする高度なユーザー/パッケージ作成者である場合は、Synthesizersが最適です。Wireables are simple and easy to use for most applications, so we'll explore them below. If you're an advanced user or package author wanting more flexibility, Synthesizers are the way to go[/docs/synthesizers].
WireablesWireables
Wireablesは、Wireable
インターフェイスを実装するアプリケーション内の任意のクラスです。Wireables are any class in your application that implements the Wireable
interface.
たとえば、顧客に関する主要なデータを含むアプリケーションにCustomer
オブジェクトがあるとしましょう。For example, let's imagine you have a Customer
object in your application that contains the primary data about a customer:
class Customer
{
protected $name;
protected $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
}
このクラスのインスタンスをLivewireコンポーネントのプロパティに設定しようとすると、Customer
プロパティ型がサポートされていないことを示すエラーが発生します。Attempting to set an instance of this class to a Livewire component property will result in an error telling you that the Customer
property type isn't supported:
class ShowCustomer extends Component
{
public Customer $customer;
public function mount()
{
$this->customer = new Customer('Caleb', 29);
}
}
しかし、Wireable
インターフェイスを実装し、クラスにtoLivewire()
とfromLivewire()
メソッドを追加することにより、これを解決できます。これらのメソッドは、この型のプロパティをJSONへ変換する方法、およびJSONから元に戻す方法をLivewireへ指示します。However, you can solve this by implementing the Wireable
interface and adding a toLivewire()
and fromLivewire()
method to your class. These methods tell Livewire how to turn properties of this type into JSON and back again:
use Livewire\Wireable;
class Customer implements Wireable
{
protected $name;
protected $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
public function toLivewire()
{
return [
'name' => $this->name,
'age' => $this->age,
];
}
public static function fromLivewire($value)
{
$name = $value['name'];
$age = $value['age'];
return new static($name, $age);
}
}
これで、LivewireコンポーネントへCustomer
オブジェクトを自由に設定できるようになり、LivewireはこれらのオブジェクトをJSONへ変換し、PHPに戻す方法を知りました。Now you can freely set Customer
objects on your Livewire components and Livewire will know how to convert these objects into JSON and back into PHP.
前述のように、よりグローバルかつ強力な方法で型をサポートしたい場合に向け、LivewireはSynthesizersを提供しています。これは、さまざまなプロパティ型を処理するための高度な内部メカニズムです。Synthesizersの詳細はこちら。As mentioned earlier, if you want to support types more globally and powerfully, Livewire offers Synthesizers, its advanced internal mechanism for handling different property types. Learn more about Synthesizers[/docs/synthesizers].
JavaScript からのプロパティへのアクセスAccessing properties from JavaScript
Livewireプロパティは、JavaScriptを使い、ブラウザでも利用できるため、AlpineJSからJavaScript表現へアクセスして操作可能です。Because Livewire properties are also available in the browser via JavaScript, you can access and manipulate their JavaScript representations from AlpineJS[https://alpinejs.dev/].
Alpineは、Livewireに含まれている軽量なJavaScriptライブラリです。Alpineを使用すると、サーバへの完全なラウンドトリップを行わずに、Livewireコンポーネントへの軽量な操作を構築できます。Alpine is a lightweight JavaScript library that is included with Livewire. Alpine provides a way to build lightweight interactions into your Livewire components without making full server roundtrips.
内部的には、LivewireのフロントエンドはAlpineの上に構築しています。 実際、すべてのLivewireコンポーネントは、裏ではAlpineコンポーネントです。これは、Livewireコンポーネント内でAlpineを自由に使用できることを意味します。Internally, Livewire's frontend is built on top of Alpine. In fact, every Livewire component is actually an Alpine component under-the-hood. This means that you can freely utilize Alpine inside your Livewire components.
このページの残りの部分では、Alpineに関する基本的な知識があることを前提としています。Alpineに慣れていない場合は、Alpineドキュメントをご覧ください。The rest of this page assumes a basic familiarity with Alpine. If you're unfamiliar with Alpine, take a look at the Alpine documentation[https://alpinejs.dev/docs].
プロパティへのアクセスAccessing properties
Livewireは、$wire
マジックオブジェクトをAlpineへ公開しています。Livewireコンポーネント内の任意のAlpine式から$wire
オブジェクトへアクセスできます。Livewire exposes a magic $wire
object to Alpine. You can access the $wire
object from any Alpine expression inside your Livewire component.
$wire
オブジェクトは、LivewireコンポーネントのJavaScriptバージョンのように扱えます。PHPバージョンのコンポーネントと同じプロパティとメソッドをすべて含んでいますが、テンプレート中で特定の機能を実行するための専用メソッドもいくつか用意しています。The $wire
object can be treated like a JavaScript version of your Livewire component. It has all the same properties and methods as the PHP version of your component, but also contains a few dedicated methods to perform specific functions in your template.
たとえば、$wire
を使用して、todo
入力フィールドのライブ文字数を表示できます。For example, we can use $wire
to show a live character count of the todo
input field:
<div>
<input type="text" wire:model="todo">
Todo character length: <h2 x-text="$wire.todo.length"></h2>
</div>
ユーザーがフィールドに入力すると、現在記述中のtodoの文字長を表示し、ページ上でライブ更新します。これらはすべて、サーバにネットワークリクエストを送信せずに行います。As the user types in the field, the character length of the current todo being written will be shown and live-updated on the page, all without sending a network request to the server.
必要に応じ、より明示的な.get()
メソッドを使用し、同様に実現できます。If you prefer, you can use the more explicit .get()
method to accomplish the same thing:
<div>
<input type="text" wire:model="todo">
Todo character length: <h2 x-text="$wire.get('todo').length"></h2>
</div>
プロパティの操作Manipulating properties
同様に、$wire
を使用し、JavaScriptでLivewireコンポーネントのプロパティを操作できます。Similarly, you can manipulate your Livewire component properties in JavaScript using $wire
.
一例として、ユーザーが入力フィールドをリセットできるように、JavaScriptのみを使用してTodoList
コンポーネントに「クリア」ボタンを追加しましょう。For example, let's add a "Clear" button to the TodoList
component to allow the user to reset the input field using only JavaScript:
<div>
<input type="text" wire:model="todo">
<button x-on:click="$wire.todo = ''">Clear</button>
</div>
ユーザーが「クリア」をクリックすると、入力は空の文字列にリセットされます。サーバへネットワークリクエストを送信しません。After the user clicks "Clear", the input will be reset to an empty string, without sending a network request to the server.
後続のリクエストでは、$todo
のサーバ側の値が更新され、同期されます。On the subsequent request, the server-side value of $todo
will be updated and synchronized.
必要に応じて、クライアント側でプロパティを設定するため、より明示的な.set()
メソッドを使用することもできます。ただし、.set()
を使用すると、ネットワークリクエストがデフォルトですぐにトリガーされ、状態がサーバと同期されることに注意する必要があります。この動作が望ましい場合、これは優れたAPIです。If you prefer, you can also use the more explicit .set()
method for setting properties client-side. However, you should note that using .set()
by default immediately triggers a network request and synchronizes the state with the server. If that is desired, then this is an excellent API:
<button x-on:click="$wire.set('todo', '')">Clear</button>
サーバへネットワークリクエストを送信せずにプロパティを更新するために、3番目のboolパラメータを渡せます。これにより、ネットワークリクエストが延期され、後続のリクエストで状態がサーバ側で同期されます。In order to update the property without sending a network request to the server, you can pass a third bool parameter. This will defer the network request and on a subsequent request, the state will be synchronized on the server-side:
<button x-on:click="$wire.set('todo', '', false)">Clear</button>
セキュリティに関する考慮Security concerns
Livewireプロパティは強力な機能ですが、使用する前に注意すべきセキュリティに関する考慮事項がいくつかあります。While Livewire properties are a powerful feature, there are a few security considerations that you should be aware of before using them.
簡単に言うと、常にパブリックプロパティをユーザー入力として扱います。これは、従来のエンドポイントからのリクエスト入力であるかのように扱います。これを踏まえ、コントローラでリクエスト入力を処理する場合と同様に、プロパティをデータベースに永続化する前に、バリデートおよび承認が不可欠です。In short, always treat public properties as user input — as if they were request input from a traditional endpoint. In light of this, it's essential to validate and authorize properties before persisting them to a database — just like you would do when working with request input in a controller.
プロパティの値を信頼しないDon't trust property values
プロパティの承認とバリデートを怠ると、アプリケーションにセキュリティホールが発生する可能性を例示する、以下のUpdatePost
コンポーネントは攻撃に対して脆弱です。To demonstrate how neglecting to authorize and validate properties can introduce security holes in your application, the following UpdatePost
component is vulnerable to attack:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Post;
class UpdatePost extends Component
{
public $id;
public $title;
public $content;
public function mount(Post $post)
{
$this->id = $post->id;
$this->title = $post->title;
$this->content = $post->content;
}
public function update()
{
$post = Post::findOrFail($this->id);
$post->update([
'title' => $this->title,
'content' => $this->content,
]);
session()->flash('message', 'Post updated successfully!');
}
public function render()
{
return view('livewire.update-post');
}
}
<form wire:submit="update">
<input type="text" wire:model="title">
<input type="text" wire:model="content">
<button type="submit">Update</button>
</form>
一見すると、このコンポーネントは全く問題ないように見えるかもしれません。しかし、攻撃者がこのコンポーネントを使用し、アプリケーションで不正なことを行うことができる方法を見ていきましょう。At first glance, this component may look completely fine. But, let's walk through how an attacker could use the component to do unauthorized things in your application.
コンポーネントのパブリックプロパティのtitle
とcontent
プロパティと同様に、投稿id
を保存しているため、クライアント側で操作できます。Because we are storing the id
of the post as a public property on the component, it can be manipulated on the client just the same as the title
and content
properties.
wire:model="id"
を使用して入力を記述しなかったことは問題ではありません。悪意のあるユーザーは、ブラウザの開発者ツールを使用して、ビューを次のように簡単に変更できます。It doesn't matter that we didn't write an input with wire:model="id"
. A malicious user can easily change the view to the following using their browser DevTools:
<form wire:submit="update">
<input type="text" wire:model="id"> <!-- [tl! highlight] -->
<input type="text" wire:model="title">
<input type="text" wire:model="content">
<button type="submit">Update</button>
</form>
これで、悪意のあるユーザーは、id
入力を別のPostモデルのIDへ更新できます。フォームを送信し、update()
を呼び出すと、Post::findOrFail()
は、所有者がユーザーではない投稿を返し、更新します。Now the malicious user can update the id
input to the ID of a different post model. When the form is submitted and update()
is called, Post::findOrFail()
will return and update a post the user is not the owner of.
この種の攻撃を防ぐために、次のいずれかまたは両方の戦略を使用できます。To prevent this kind of attack, we can use one or both of the following strategies:
- 入力を承認するAuthorize the input
- プロパティの更新をロックするLock the property from updates
入力を承認するAuthorizing the input
$id
にwire:model
などのものを使用するとクライアント側で操作できるため、コントローラと同様にLaravelの認可を使用して、現在のユーザーが投稿を更新可能であることを確認できますBecause $id
can be manipulated client-side with something like wire:model
, just like in a controller, we can use Laravel's authorization[https://laravel.com/docs/authorization] to make sure the current user can update the post:
public function update()
{
$post = Post::findOrFail($this->id);
$this->authorize('update', $post); // [tl! highlight]
$post->update(...);
}
悪意のあるユーザーが$id
プロパティを変更した場合、追加した承認によりそれが検出され、エラーを投げます。If a malicious user mutates the $id
property, the added authorization will catch it and throw an error.
プロパティのロックLocking the property
Livewireでは、クライアント側でプロパティが変更されないようにするために、プロパティを「ロック」することも可能です。#[Locked]
属性を使用して、クライアント側の操作からプロパティを「ロック」できます。Livewire also allows you to "lock" properties in order to prevent properties from being modified on the client-side. You can "lock" a property from client-side manipulation using the #[Locked]
attribute:
use Livewire\Attributes\Locked;
use Livewire\Component;
class UpdatePost extends Component
{
#[Locked] // [tl! highlight]
public $id;
// ...
}
これで、ユーザーがフロントエンドで$id
を変更しようとすると、エラーが投げられます。Now, if a user tries to modify $id
on the front end, an error will be thrown.
#[Locked]
を使用すると、このプロパティがコンポーネントのクラス外のどこからでも操作されていないと想定できます。By using #[Locked]
, you can assume this property has not been manipulated anywhere outside your component's class.
プロパティのロックの詳細は、プロパティの変更ロックのドキュメントを参照してください。For more information on locking properties, consult the Locked properties documentation[/docs/locked].
EloquentモデルとロックEloquent models and locking
Eloquentモデルが、Livewire コンポーネントのプロパティに割り当てられると、Livewireは自動的にプロパティをロックし、IDが変更されないようにして、これらの種類の攻撃から安全を確保します。When an Eloquent model is assigned to a Livewire component property, Livewire will automatically lock the property and ensure the ID isn't changed, so that you are safe from these kinds of attacks:
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Post;
class UpdatePost extends Component
{
public Post $post; // [tl! highlight]
public $title;
public $content;
public function mount(Post $post)
{
$this->post = $post;
$this->title = $post->title;
$this->content = $post->content;
}
public function update()
{
$this->post->update([
'title' => $this->title,
'content' => $this->content,
]);
session()->flash('message', 'Post updated successfully!');
}
public function render()
{
return view('livewire.update-post');
}
}
プロパティはシステム情報をブラウザへ公開するProperties expose system information to the browser
もう1つ覚えておくべき重要なことは、Livewireプロパティをブラウザへ送信する前に、シリアル化または「デハイドレード」されることです。これはそれらの値をネットワーク経由で送信し、JavaScriptで理解できる形式に変換することを意味します。この形式は、プロパティの名前やクラス名など、アプリケーションに関する情報をブラウザへ公開する可能性があります。Another essential thing to remember is that Livewire properties are serialized or "dehydrated" before they are sent to the browser. This means that their values are converted to a format that can be sent over the wire and understood by JavaScript. This format can expose information about your application to the browser, including the names and class names of your properties.
たとえば、$post
という名前のパブリックプロパティを定義するLivewireコンポーネントがあるとします。このプロパティには、データベースからのPost
モデルのインスタンスが含まれています。この場合、ネットワーク経由で送信するこのプロパティのデハイドレードした値は、以下のようになります。For example, suppose you have a Livewire component that defines a public property named $post
. This property contains an instance of a Post
model from your database. In this case, the dehydrated value of this property sent over the wire might look something like this:
{
"type": "model",
"class": "App\Models\Post",
"key": 1,
"relationships": []
}
ご覧のとおり、$post
プロパティのデハイドレードした値は、モデルのクラス名(App\Models\Post
)、ID、および事前にロードされているリレーションを含んでいます。As you can see, the dehydrated value of the $post
property includes the class name of the model (App\Models\Post
) as well as the ID and any relationships that have been eager-loaded.
モデルのクラス名を公開したくない場合は、サービスプロバイダからLaravelの"morphMap"機能を使用して、モデルクラス名にエイリアスを割り当てることができます。If you don't want to expose the class name of the model, you can use Laravel's "morphMap" functionality from a service provider to assign an alias to a model class name:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Relations\Relation;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Relation::morphMap([
'post' => 'App\Models\Post',
]);
}
}
これでEloquentモデルが「デハイドレート」(シリアライズ)されても、元のクラス名は公開されず、"post"エイリアスのみ公開されます。Now, when the Eloquent model is "dehydrated" (serialized), the original class name won't be exposed, only the "post" alias:
{
"type": "model",
"class": "App\Models\Post", // [tl! remove]
"class": "post", // [tl! add]
"key": 1,
"relationships": []
}
Eloquentの制約はリクエスト間で保持されないEloquent constraints aren't preserved between requests
通常、Livewireはリクエスト間でサーバ側のプロパティを保持および再作成できます。ただし、リクエスト間で値を保持することが不可能なシナリオがいくつかあります。Typically, Livewire is able to preserve and recreate server-side properties between requests; however, there are certain scenarios where preserving values are impossible between requests.
たとえば、EloquentコレクションをLivewireプロパティとして保存する場合、select(...)
のような追加のクエリ制約は、後続のリクエストで再適用されません。For example, when storing Eloquent collections as Livewire properties, additional query constraints like select(...)
will not be re-applied on subsequent requests.
これを説明するために、Todos
Eloquentコレクションへselect()
制約を適用する、ShowTodos
コンポーネントを考えてみましょう。To demonstrate, consider the following ShowTodos
component with a select()
constraint applied to the Todos
Eloquent collection:
<?php
namespace App\Livewire;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class ShowTodos extends Component
{
public $todos;
public function mount()
{
$this->todos = Auth::user()
->todos()
->select(['title', 'content']) // [tl! highlight]
->get();
}
public function render()
{
return view('livewire.show-todos');
}
}
このコンポーネントを最初にロードすると、$todos
プロパティにはユーザーのtodosのEloquentコレクションを設定します。ただし、データベースの各行のtitle
およびcontent
フィールドのみクエリし、各モデルにロードします。When this component is initially loaded, the $todos
property will be set to an Eloquent collection of the user's todos; however, only the title
and content
fields of each row in the database will have been queried and loaded into each of the models.
LivewireがこのプロパティのJSONを後続のリクエストでPHPに_ハイドレート_すると、そのselect制約は失われます。When Livewire hydrates the JSON of this property back into PHP on a subsequent request, the select constraint will have been lost.
Eloquentクエリの整合性を確保するために、プロパティの代わりに算出プロパティを使用することをお勧めします。To ensure the integrity of Eloquent queries, we recommend that you use computed properties[/docs/computed-properties] instead of properties.
算出プロパティは、コンポーネント内で#[Computed]
属性でマークされたメソッドです。コンポーネントの状態の一部として保存せずに、即時に評価する動的プロパティとしてアクセスできます。Computed properties are methods in your component marked with the #[Computed]
attribute. They can be accessed as a dynamic property that isn't stored as part of the component's state but is instead evaluated on-the-fly.
算出プロパティを使用して、書き直した上記の例を以下に示します。Here's the above example re-written using a computed property:
<?php
namespace App\Livewire;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Computed;
use Livewire\Component;
class ShowTodos extends Component
{
#[Computed] // [tl! highlight]
public function todos()
{
return Auth::user()
->todos()
->select(['title', 'content'])
->get();
}
public function render()
{
return view('livewire.show-todos');
}
}
Bladeビューからこれらの_todos_にアクセスする方法を次に示します。Here's how you would access these todos from the Blade view:
<ul>
@foreach ($this->todos as $todo)
<li>{{ $todo }}</li>
@endforeach
</ul>
ビュー内では、$this->todos
のように、$this
オブジェクトの算出プロパティにのみアクセスできます。Notice, inside your views, you can only access computed properties on the $this
object like so: $this->todos
.
クラス内からも$todos
にアクセスできます。たとえば、markAllAsComplete()
アクションがある場合:You can also access $todos
from inside your class. For example, if you had a markAllAsComplete()
action:
<?php
namespace App\Livewire;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Computed;
use Livewire\Component;
class ShowTodos extends Component
{
#[Computed]
public function todos()
{
return Auth::user()
->todos()
->select(['title', 'content'])
->get();
}
public function markAllComplete() // [tl! highlight:3]
{
$this->todos->each->complete();
}
public function render()
{
return view('livewire.show-todos');
}
}
メソッドとして$this->todos()
を必要な場所で直接呼び出さないのはなぜか?そもそも#[Computed]
を使用する理由は何か?皆さん迷われていることでしょう。You might wonder why not just call $this->todos()
as a method directly where you need to? Why use #[Computed]
in the first place?
その理由は、算出プロパティにはパフォーマンス上の利点があるためです。算出プロパティは、1つのリクエスト中に最初に利用された後、自動的にキャッシュします。つまり、コンポーネント内で$this->todos
に自由にアクセスでき、実際のメソッドを1回だけ呼び出すことが保証されるため、同じリクエスト内で高価なクエリを複数回実行することはありません。The reason is that computed properties have a performance advantage, since they are automatically cached after their first usage during a single request. This means you can freely access $this->todos
within your component and be assured that the actual method will only be called once, so that you don't run an expensive query multiple times in the same request.
詳細は、算出プロパティのドキュメントを参照してください。For more information, visit the computed properties documentation[/docs/computed-properties].