# Symfony Live ComponentsとUX 3.0:JavaScriptなしでリアクティブアプリを構築する方法(2026年版)
> Symfony Live ComponentsとUX 3.0を使用して、JavaScriptフレームワーク不要でリアクティブなUIを構築する方法を解説します。LiveProp、LiveAction、フォーム処理、遅延読み込み、URLバインディングを網羅したチュートリアルです。
- Published: 2026-05-10
- Updated: 2026-05-10
- Author: SharpSkill
- Tags: symfony, live components, symfony ux, php, twig, reactive ui
- Reading time: 10 min
---
Symfony Live Componentsは、PHPとTwigだけでリアクティブかつリアルタイムなユーザーインターフェースを実現する仕組みです。2026年4月にリリースされた[Symfony UX 3.0](https://symfony.com/blog/symfony-ux-3-0-0-released)では、2.x系の非推奨機能がすべて削除され、最低要件がPHP 8.4およびSymfony 7.4に引き上げられました。さらに、4つの廃止パッケージが除外され、これまでで最も軽量なUXツールキットとなっています。
> **Live Componentsとは?**
>
> Live Componentsは、あらゆるTwigコンポーネントをステートフルでインタラクティブな要素に変換します。ユーザー操作に応じてサーバーサイドで再レンダリングが行われ、JavaScriptを一切記述する必要がありません。データバインディング、アクション、バリデーション、フォーム処理はすべてPHP内で完結します。
## Symfony UX 3.0とLive Componentsのセットアップ
インストールにはSymfony 7.4以上、PHP 8.4以上、そしてフロントエンドアセット用にAssetMapperまたはWebpack Encoreが必要です。
```bash
# terminal
composer require symfony/ux-live-component
# With AssetMapper (recommended for Symfony 7.4+)
php bin/console importmap:require @symfony/ux-live-component
# Verify installation
php bin/console debug:twig --filter=component
```
AssetMapperは、Node.js、Webpack、その他のビルドステップを一切使用せずにJavaScriptを配信します。Live Componentsを駆動するStimulusコントローラーは自動的にロードされます。
## LivePropを使ったリアクティブ検索コンポーネントの作成
ユーザーが入力するたびに結果をフィルタリングする検索バーを、JavaScriptゼロで実装できます。`#[LiveProp]`属性はプロパティをステートフルとしてマークし、暗号化されたURLセーフトークンを通じて再レンダリング間で値を保持します。
```php
query) < 2) {
return [];
}
return $this->productRepository->search(
query: $this->query,
category: $this->category === 'all' ? null : $this->category,
limit: 20,
);
}
}
```
対応するTwigテンプレートでは、`data-model`を使って入力をプロパティにバインドします。
```twig
{# templates/components/ProductSearch.html.twig #}
{% for product in this.products %}
{{ product.name }}
{{ product.price|format_currency('EUR') }}
{% else %}
{% if query|length >= 2 %}
No results for "{{ query }}".
{% endif %}
{% endfor %}
```
`debounce(300)`修飾子は、最後のキーストロークから300ミリ秒待ってからリクエストを送信します。リストアイテムの`key`属性は効率的なDOMモーフィングを可能にし、変更された要素のみが更新されます。
> **LivePropによるURLバインディング**
>
> LivePropで`url: true`を設定すると、プロパティの値がクエリパラメータとしてブラウザURLに同期されます。たった1つの属性で、ブックマーク可能で共有可能な検索結果が実現します。
## LiveActionによるユーザーアクションの処理
データバインディングに加えて、`#[LiveAction]`はPHPメソッドをフロントエンドから呼び出し可能なアクションとして公開します。引数は`#[LiveArg]`を通じて渡されます。
```php
cartService->add($productId, $quantity);
$this->items = $this->cartService->getItems();
// Notify other components on the page
$this->emit('cart:updated', [
'count' => count($this->items),
]);
}
#[LiveAction]
public function removeItem(#[LiveArg] int $itemId): void
{
$this->cartService->remove($itemId);
$this->items = $this->cartService->getItems();
$this->emit('cart:updated', ['count' => count($this->items)]);
}
public function getTotal(): float
{
return array_sum(array_map(
fn(CartItem $item) => $item->getPrice() * $item->getQuantity(),
$this->items,
));
}
}
```
テンプレートでは、`live_action()`ヘルパーまたは`data-action`属性を使用してアクションをトリガーします。
```twig
{# templates/components/ShoppingCart.html.twig #}
Cart ({{ items|length }})
{% for item in items %}
{{ item.name }} x{{ item.quantity }}
{{ (item.price * item.quantity)|format_currency('EUR') }}
{% endfor %}
Total: {{ this.total|format_currency('EUR') }}
```
`emit()`メソッドは、ページ上の他のLive Componentsにイベントをブロードキャストします。例えば、カートバッジコンポーネントは`#[LiveListener('cart:updated')]`でリッスンし、ページ全体をリロードすることなくカウントを更新できます。
## JavaScriptなしのリアルタイムフォームバリデーション
Live Componentsは[Symfony Forms](https://symfony.com/doc/current/forms.html)と直接統合されます。`ComponentWithFormTrait`は、フォームの状態、バリデーションエラー、送信をコンポーネントのライフサイクルに接続します。
```php
createForm(RegistrationType::class, $this->initialFormData ?? new User());
}
#[LiveAction]
public function save(EntityManagerInterface $em): mixed
{
// Submits + validates — re-renders with errors if invalid
$this->submitForm();
$user = $this->getForm()->getData();
$em->persist($user);
$em->flush();
$this->addFlash('success', 'Account created.');
return $this->redirectToRoute('app_login');
}
}
```
```twig
{# templates/components/RegistrationForm.html.twig #}
{{ form_start(form, {
attr: {
'data-action': 'live#action:prevent',
'data-live-action-param': 'save'
}
}) }}
{{ form_row(form.email) }}
{{ form_row(form.plainPassword, { label: 'Password' }) }}
{{ form_row(form.fullName) }}
{{ form_end(form) }}
```
バリデーションエラーは、ユーザーがフィールド間を移動する際にインラインで表示されます。`data-model`の`on(change)`修飾子がblur時に再レンダリングをトリガーし、Symfony Validatorの制約メッセージが即座に表示されます。
## パフォーマンスのための遅延読み込みとレイジーローディング
ダッシュボード、分析チャート、長いリストなどの重いコンポーネントは、遅延レンダリングの恩恵を受けます。初期ページロードをブロックする代わりに、コンポーネントはプレースホルダーをレンダリングし、ページの準備ができた後にAJAXでコンテンツを取得します。
```php
analytics->getMetrics($this->period);
}
}
```
```twig
{# Parent page: load the dashboard after the page renders #}
{# Or load when scrolled into view #}
```
コンポーネントテンプレート内のプレースホルダーマクロは、実際のコンテンツが読み込まれるまでユーザーに表示される内容を定義します。
```twig
{# templates/components/AnalyticsDashboard.html.twig #}
Analytics — {{ period }}
{% for metric in this.metrics %}
{{ metric.label }}
{{ metric.value|number_format }}
{% endfor %}
{% macro placeholder(props) %}
{% endmacro %}
```
`loading="defer"`モードはページロード直後にAJAXリクエストを発行します。`loading="lazy"`モードはIntersectionObserverを使用し、コンポーネントがビューポートにスクロールされたときにのみリクエストが発行されます。どちらのアプローチも初期ページレスポンスを高速に保ちます。
> **UX 3.0でCSRFが廃止**
>
> Symfony UX 3.0では、Live ComponentsのCSRFトークンが同一オリジン/CORSプロテクションに置き換えられました。`#[AsLiveComponent]`の`csrf`引数はもう存在しません。サーバーが同一オリジンポリシーを適用していることを確認してください。
## イベントによるコンポーネント間通信
Live Componentsはイベントシステムを通じて通信します。子コンポーネントがイベントを発行し、親(または兄弟)コンポーネントがリッスンして反応します。
```php
count = $cartService->getItemCount();
}
// Automatically re-renders when ShoppingCart emits 'cart:updated'
#[LiveListener('cart:updated')]
public function onCartUpdated(#[LiveArg] int $count): void
{
$this->count = $count;
}
}
```
このパターンにより、コンポーネント間の結合が疎になります。ShoppingCartコンポーネントはCartBadgeを直接参照せず、イベントバスが接続を処理します。
## Symfony UX 3.0の主な変更点
UX 3.0はクリーンアップリリースです。2.x系で非推奨警告なしに動作しているアプリケーションは、最小限の手間でアップグレードできます。
| 変更点 | 以前(2.x) | 以後(3.0) |
|--------|-------------|-------------|
| CSRFプロテクション | `#[AsLiveComponent]`の`csrf: true` | 同一オリジン/CORS(自動) |
| Twig CVA関数 | `cva()` | twig/html-extra 3.12+の`html_cva()` |
| コンポーネントデフォルト設定 | 任意 | `twig_component.defaults`が必須 |
| 削除されたパッケージ | Swup, LazyImage, Typed, TogglePassword | ネイティブAPIまたはUX Toolkit |
| PHP要件 | 8.1以上 | 8.4以上 |
| Symfony要件 | 6.4以上 | 7.4以上 |
2.xサイクル中に導入された[UX Toolkit](https://symfony.com/blog/symfonyux-2-32-0-released)は、Shadcn UIまたはFlowbite 4.0でスタイリングされたプリビルドUIコンポーネント(Button、Dialog、Card、Table、Pagination)を提供し、削除されたパッケージの穴を埋めます。
[Symfonyの面接対策](/technologies/symfony/interview-questions/events-subscribers)を準備している方にとって、Live Componentsとイベントシステムの理解はシニアレベルのポジションでますます重要になっています。[Symfony面接対策ガイド](/blog/symfony/symfony-interview-questions)では、この実践的な知識と相性の良い基礎的なトピックを取り上げています。
## まとめ
- Live Componentsは、CRUDが中心となるSymfonyアプリケーションのほとんどにおいて、JavaScriptフレームワークの必要性を排除します。データバインディング、アクション、バリデーション、フォーム処理はすべてPHPとTwigで完結します
- `#[LiveProp(writable: true, url: true)]`は、たった1つの属性でブックマーク可能かつ共有可能なステートフルインターフェースを作成します
- 遅延読み込みとレイジーローディング(`loading="defer"` / `loading="lazy"`)は、重いコンポーネントが非同期でレンダリングされる間、初期ページロードを高速に保ちます
- UX 3.0はCSRFトークンを廃止し、同一オリジン/CORSプロテクションを採用しました。可動部品が少ないシンプルなセキュリティです
- イベントシステム(`emit` / `#[LiveListener]`)は、グローバルな状態管理なしでコンポーネント間の疎結合な通信を実現します
- API連携には、バックエンド中心のアーキテクチャ向けに[Symfony 7でのAPI Platform](/blog/symfony/symfony-7-api-platform-best-practices)を補完的に活用できます
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/ja/blog/symfony/symfony-live-components-ux-3-reactive-apps-without-javascript