# Symfony Live Components และ UX 3.0: แอปพลิเคชันแบบ Reactive โดยไม่ต้องใช้ JavaScript ในปี 2026
> Symfony Live Components สร้างอินเทอร์เฟซแบบ reactive ด้วย PHP และ Twig โดยไม่ต้องใช้ JavaScript บทช่วยสอนเกี่ยวกับ LiveProp, LiveAction, form และ deferred loading
- Published: 2026-05-10
- Updated: 2026-05-10
- Author: SharpSkill
- Tags: symfony, live-components, ux-3, php, reactive
- Reading time: 8 min
---
Symfony Live Components นำเสนออินเทอร์เฟซผู้ใช้แบบ reactive และ real-time ทั้งหมดด้วย PHP และ Twig เปิดตัวในเดือนเมษายน 2026 [Symfony UX 3.0](https://symfony.com/blog/symfony-ux-3-0-0-released) ลบ deprecation ทั้งหมดจากเวอร์ชัน 2.x ยกระดับความต้องการขั้นต่ำเป็น PHP 8.4 และ Symfony 7.4 พร้อมทั้งตัดแพ็กเกจที่ล้าสมัยออกสี่ตัว — สร้าง UX toolkit ที่กระชับที่สุดเท่าที่เคยมีมา
> **Live Components คืออะไร?**
>
> Live Components เปลี่ยน component Twig ใดก็ได้ให้เป็นเอลิเมนต์ที่มี state และโต้ตอบได้ ซึ่งถูก render ใหม่ฝั่ง server เมื่อผู้ใช้มีปฏิสัมพันธ์ — โดยไม่ต้องเขียน JavaScript data binding, action, validation และการจัดการ form ทั้งหมดเกิดขึ้นใน PHP
## การตั้งค่า Symfony UX 3.0 กับ Live Components
การติดตั้งต้องใช้ Symfony 7.4+, PHP 8.4+ และ AssetMapper หรือ Webpack Encore สำหรับ asset ฝั่ง frontend
```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 จัดการการส่งมอบ JavaScript โดยไม่ต้องใช้ Node.js, Webpack หรือขั้นตอน build ใดๆ Stimulus controller ที่ขับเคลื่อน Live Components จะถูกโหลดโดยอัตโนมัติ
## การสร้าง Component ค้นหาแบบ Reactive ด้วย LiveProp
แถบค้นหาที่กรองผลลัพธ์ขณะที่ผู้ใช้พิมพ์ — ไม่ต้องใช้ JavaScript เลย แอตทริบิวต์ `#[LiveProp]` ทำเครื่องหมาย property ว่ามี state ซึ่งจะถูกรักษาไว้ระหว่างการ re-render ผ่าน token ที่เข้ารหัสและปลอดภัยสำหรับ URL
```php
query) < 2) {
return [];
}
return $this->productRepository->search(
query: $this->query,
category: $this->category === 'all' ? null : $this->category,
limit: 20,
);
}
}
```
เทมเพลต Twig ที่สอดคล้องกันจะผูก input กับ property ด้วย `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 %}
```
Modifier `debounce(300)` รอ 300ms หลังจากการกดแป้นพิมพ์ครั้งสุดท้ายก่อนส่ง request แอตทริบิวต์ `key` บน item ของรายการช่วยให้ DOM morphing ทำงานอย่างมีประสิทธิภาพ — เฉพาะเอลิเมนต์ที่เปลี่ยนแปลงเท่านั้นที่ถูกอัปเดต
> **URL Binding ด้วย LiveProp**
>
> การตั้งค่า `url: true` บน LiveProp จะซิงค์ค่า property กับ URL ของเบราว์เซอร์เป็น query parameter ผลการค้นหาที่สามารถ bookmark และแชร์ได้ — ด้วยแอตทริบิวต์เดียว
## การจัดการ Action ของผู้ใช้ด้วย LiveAction
นอกเหนือจาก data binding แล้ว `#[LiveAction]` เปิดเผย method PHP เป็น action ที่สามารถเรียกใช้จาก frontend ได้ อาร์กิวเมนต์ถูกส่งผ่าน `#[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,
));
}
}
```
เทมเพลตเรียก action ด้วย helper `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()` กระจาย event ไปยัง Live Components อื่นบนหน้า — ตัวอย่างเช่น component badge ตะกร้าสินค้าสามารถรับฟังด้วย `#[LiveListener('cart:updated')]` และอัปเดตจำนวนโดยไม่ต้องโหลดหน้าใหม่ทั้งหมด
## การตรวจสอบ Form แบบ Real-Time โดยไม่ต้องใช้ JavaScript
Live Components ทำงานร่วมกับ [Symfony Forms](https://symfony.com/doc/current/forms.html) ได้โดยตรง `ComponentWithFormTrait` เชื่อมต่อสถานะ form, ข้อผิดพลาดจาก validation และการ submit เข้ากับ lifecycle ของ component
```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) }}
```
ข้อผิดพลาดจาก validation จะแสดงแบบ inline เมื่อผู้ใช้เลื่อนระหว่างฟิลด์ — modifier `on(change)` บน `data-model` จะทริกเกอร์ re-render เมื่อ blur แสดงข้อความ constraint จาก Symfony Validator ทันที
## Deferred และ Lazy Loading เพื่อประสิทธิภาพ
Component ที่หนัก — dashboard, กราฟวิเคราะห์, รายการยาว — ได้ประโยชน์จาก deferred rendering แทนที่จะบล็อกการโหลดหน้าแรก component จะแสดง placeholder และดึงเนื้อหาผ่าน AJAX หลังจากหน้าพร้อมแล้ว
```php
analytics->getMetrics($this->period);
}
}
```
```twig
{# Parent page: load the dashboard after the page renders #}
{# Or load when scrolled into view #}
```
มาโคร placeholder ภายในเทมเพลต component กำหนดสิ่งที่ผู้ใช้เห็นขณะที่เนื้อหาจริงกำลังโหลด
```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 request ทันทีเมื่อหน้าโหลด โหมด `loading="lazy"` ใช้ IntersectionObserver — request จะถูกส่งเมื่อ component เลื่อนเข้ามาใน viewport เท่านั้น ทั้งสองวิธีรักษาการตอบสนองของหน้าแรกให้เร็ว
> **CSRF ถูกลบใน UX 3.0**
>
> Symfony UX 3.0 แทนที่ token CSRF ด้วยการป้องกัน same-origin/CORS สำหรับ Live Components อาร์กิวเมนต์ `csrf` บน `#[AsLiveComponent]` ไม่มีอีกต่อไป ต้องแน่ใจว่า server บังคับใช้นโยบาย same-origin
## การสื่อสารระหว่าง Component ด้วย Events
Live Components สื่อสารผ่านระบบ event component ลูกส่ง event ออกไป component แม่ (หรือ sibling) รับฟังและตอบสนอง
```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;
}
}
```
รูปแบบนี้รักษาให้ component แยกจากกัน component ShoppingCart ไม่ได้อ้างอิง CartBadge โดยตรง — event bus จัดการการเชื่อมต่อ
## สิ่งที่เปลี่ยนแปลงใน Symfony UX 3.0
UX 3.0 เป็นรุ่นที่ทำความสะอาด แอปพลิเคชันที่ทำงานโดยไม่มีคำเตือน deprecation บน 2.x สามารถอัปเกรดได้โดยมีอุปสรรคน้อยที่สุด
| การเปลี่ยนแปลง | ก่อน (2.x) | หลัง (3.0) |
|---------------|------------|------------|
| การป้องกัน CSRF | `csrf: true` บน `#[AsLiveComponent]` | Same-origin/CORS (อัตโนมัติ) |
| ฟังก์ชัน Twig CVA | `cva()` | `html_cva()` จาก twig/html-extra 3.12+ |
| Config defaults ของ component | ไม่บังคับ | `twig_component.defaults` บังคับ |
| แพ็กเกจที่ถูกลบ | Swup, LazyImage, Typed, TogglePassword | ใช้ native API หรือ UX Toolkit |
| ความต้องการ PHP | 8.1+ | 8.4+ |
| ความต้องการ Symfony | 6.4+ | 7.4+ |
[UX Toolkit](https://symfony.com/blog/symfonyux-2-32-0-released) ซึ่งเปิดตัวในช่วง 2.x มี component UI สำเร็จรูป (Button, Dialog, Card, Table, Pagination) ที่ styled ด้วย Shadcn UI หรือ Flowbite 4.0 — เติมเต็มช่องว่างที่แพ็กเกจที่ถูกลบทิ้งไว้
กำลังเตรียม[คำถามสัมภาษณ์งาน Symfony](/technologies/symfony/interview-questions/events-subscribers) อยู่หรือไม่? ความเข้าใจเกี่ยวกับ Live Components และระบบ event มีความเกี่ยวข้องมากขึ้นสำหรับตำแหน่งระดับ senior [คู่มือคำถามสัมภาษณ์ Symfony](/blog/symfony/symfony-interview-questions) ครอบคลุมหัวข้อพื้นฐานที่เหมาะสำหรับจับคู่กับความรู้เชิงปฏิบัตินี้
## สรุป
- Live Components ขจัดความจำเป็นในการใช้ framework JavaScript ในแอปพลิเคชัน Symfony ที่เน้น CRUD ส่วนใหญ่ data binding, action, validation และการจัดการ form ยังคงอยู่ใน PHP และ Twig
- `#[LiveProp(writable: true, url: true)]` สร้างอินเทอร์เฟซที่มี state สามารถ bookmark และแชร์ได้ด้วยแอตทริบิวต์เดียว
- Deferred และ lazy loading (`loading="defer"` / `loading="lazy"`) รักษาการโหลดหน้าแรกให้เร็วในขณะที่ component หนักถูก render แบบ asynchronous
- UX 3.0 ยกเลิก token CSRF เพื่อใช้การป้องกัน same-origin/CORS — ความปลอดภัยที่เรียบง่ายกว่าด้วยชิ้นส่วนที่เคลื่อนไหวน้อยลง
- ระบบ event (`emit` / `#[LiveListener]`) ช่วยให้การสื่อสารระหว่าง component แยกจากกันโดยไม่ต้องจัดการ state แบบ global
- สำหรับ API ให้ผสม Live Components กับ [API Platform บน Symfony 7](/blog/symfony/symfony-7-api-platform-best-practices) สำหรับสถาปัตยกรรมที่เน้น backend
---
Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack.
HTML version of this page: https://sharpskill.dev/th/blog/symfony/symfony-live-components-ux-3-reactive-apps-without-javascript