# LiveComponents Attributes Reference Complete reference for all LiveComponents attributes with examples and best practices. ## Table of Contents - [Component Attributes](#component-attributes) - [@LiveProp](#liveprop) - [@LiveAction](#liveaction) - [@Fragment](#fragment) - [Security Attributes](#security-attributes) - [@RateLimit](#ratelimit) - [@Authorize](#authorize) - [@Idempotent](#idempotent) - [@Encrypted](#encrypted) - [Performance Attributes](#performance-attributes) - [@Optimistic](#optimistic) - [@Cached](#cached) - [@NoBatch](#nobatch) - [Validation Attributes](#validation-attributes) - [@Validated](#validated) - [State Management Attributes](#state-management-attributes) - [@Persisted](#persisted) --- ## Component Attributes ### @LiveProp **Purpose**: Mark a component property as reactive - automatically synchronized between server and client. **Signature**: ```php #[LiveProp( writable: bool = false, // Allow client-side updates lazy: bool = false, // Load on first access computed: bool = false, // Computed from other props dehydrate: ?callable = null, // Custom serialization hydrate: ?callable = null // Custom deserialization )] ``` **Basic Usage**: ```php final class Counter extends LiveComponent { #[LiveProp] public int $count = 0; #[LiveProp(writable: true)] public string $searchQuery = ''; #[LiveProp(lazy: true)] public array $expensiveData = []; #[LiveAction] public function increment(): void { $this->count++; } } ``` **Writable Props** (Two-Way Binding): ```php final class SearchForm extends LiveComponent { #[LiveProp(writable: true)] public string $query = ''; #[LiveProp(writable: true)] public array $filters = []; #[LiveAction] public function search(): void { // $this->query automatically updated from client $this->results = $this->searchService->search($this->query, $this->filters); } } ``` **HTML Template**: ```html
``` **Lazy Props** (Load on Demand): ```php final class Dashboard extends LiveComponent { #[LiveProp] public string $userId; #[LiveProp(lazy: true)] public array $analytics = []; #[LiveAction] public function loadAnalytics(): void { // Only load when explicitly requested $this->analytics = $this->analyticsService->getForUser($this->userId); } } ``` **Computed Props**: ```php final class ShoppingCart extends LiveComponent { #[LiveProp] public array $items = []; #[LiveProp(computed: true)] public function total(): Money { return array_reduce( $this->items, fn($total, $item) => $total->add($item->price), Money::zero() ); } } ``` **Custom Serialization**: ```php final class DateRangePicker extends LiveComponent { #[LiveProp( dehydrate: [self::class, 'dehydrateDate'], hydrate: [self::class, 'hydrateDate'] )] public \DateTimeImmutable $startDate; public static function dehydrateDate(\DateTimeImmutable $date): string { return $date->format('Y-m-d'); } public static function hydrateDate(string $date): \DateTimeImmutable { return new \DateTimeImmutable($date); } } ``` **Best Practices**: - ✅ Use `writable: true` only for user input fields - ✅ Use `lazy: true` for expensive data that's not always needed - ✅ Keep props serializable (primitives, arrays, or custom dehydrate/hydrate) - ❌ Don't make service dependencies `#[LiveProp]` - ❌ Don't expose sensitive data as LiveProps **Gotchas**: - Writable props validate on server before updating - Computed props are read-only on client - Lazy props won't be available until explicitly loaded --- ### @LiveAction **Purpose**: Mark a method as a server-side action that can be triggered from the client. **Signature**: ```php #[LiveAction( name: ?string = null, // Custom action name debounce: ?int = null, // Debounce in milliseconds throttle: ?int = null, // Throttle in milliseconds confirm: ?string = null // Confirmation message )] ``` **Basic Usage**: ```php final class TodoList extends LiveComponent { #[LiveProp] public array $todos = []; #[LiveAction] public function addTodo(string $text): void { $this->todos[] = [ 'id' => uniqid(), 'text' => $text, 'done' => false ]; } #[LiveAction] public function toggleTodo(string $id): void { foreach ($this->todos as &$todo) { if ($todo['id'] === $id) { $todo['done'] = !$todo['done']; } } } #[LiveAction] public function removeTodo(string $id): void { $this->todos = array_filter( $this->todos, fn($todo) => $todo['id'] !== $id ); } } ``` **HTML Template**: ```html
``` **Debounced Actions** (Search Input): ```php final class SearchComponent extends LiveComponent { #[LiveProp(writable: true)] public string $query = ''; #[LiveProp] public array $results = []; #[LiveAction(debounce: 300)] public function search(): void { // Only executes 300ms after user stops typing $this->results = $this->searchService->search($this->query); } } ``` **Throttled Actions** (Rate Limited): ```php final class AnalyticsTracker extends LiveComponent { #[LiveAction(throttle: 1000)] public function trackEvent(string $eventName): void { // Maximum once per second $this->analyticsService->track($eventName); } } ``` **Confirmation Actions**: ```php final class UserManager extends LiveComponent { #[LiveAction(confirm: 'Are you sure you want to delete this user?')] public function deleteUser(string $userId): void { $this->userService->delete($userId); } } ``` **Custom Action Names**: ```php final class PaymentForm extends LiveComponent { #[LiveAction(name: 'submit-payment')] public function processPayment(array $paymentData): void { $this->paymentService->process($paymentData); } } ``` **Best Practices**: - ✅ Use debounce for search/autocomplete - ✅ Use throttle for tracking/analytics - ✅ Use confirm for destructive actions - ✅ Keep actions focused (single responsibility) - ❌ Don't perform long-running operations (use jobs) - ❌ Don't return data (update LiveProps instead) **Gotchas**: - Actions automatically re-render component by default - Debounce/throttle applied client-side before request - Confirmation shows native browser confirm dialog --- ### @Fragment **Purpose**: Mark an action to update only specific fragments of the component (partial rendering). **Signature**: ```php #[Fragment( string|array $names // Fragment name(s) to update )] ``` **Basic Usage**: ```php final class Dashboard extends LiveComponent { #[LiveProp] public array $stats = []; #[LiveProp] public array $notifications = []; #[LiveAction] #[Fragment('stats')] public function refreshStats(): void { // Only re-renders the 'stats' fragment $this->stats = $this->statsService->getLatest(); } #[LiveAction] #[Fragment('notifications')] public function refreshNotifications(): void { // Only re-renders the 'notifications' fragment $this->notifications = $this->notificationService->getUnread(); } #[LiveAction] #[Fragment(['stats', 'notifications'])] public function refreshAll(): void { // Re-renders both fragments $this->stats = $this->statsService->getLatest(); $this->notifications = $this->notificationService->getUnread(); } } ``` **HTML Template**: ```html

Statistics

{{ stat.label }}: {{ stat.value }}

Notifications

{{ notification.message }}
``` **Nested Fragments**: ```php final class ProductList extends LiveComponent { #[LiveProp] public array $products = []; #[LiveProp] public array $filters = []; #[LiveAction] #[Fragment('product-list')] public function applyFilter(string $category): void { $this->filters['category'] = $category; $this->products = $this->productService->search($this->filters); } #[LiveAction] #[Fragment('product-item')] public function toggleFavorite(string $productId): void { $this->productService->toggleFavorite($productId); } } ``` **HTML Template with Nested Fragments**: ```html

{{ product.name }}

``` **Performance Benefits**: ```php // Without fragments (full re-render) #[LiveAction] public function updateSmallPart(): void { // Re-renders entire 10KB template } // With fragments (partial re-render) #[LiveAction] #[Fragment('small-part')] public function updateSmallPart(): void { // Only re-renders 500 bytes // 95% network reduction! } ``` **Best Practices**: - ✅ Use fragments for large components with independent sections - ✅ Name fragments semantically (`user-profile`, not `fragment-1`) - ✅ Keep fragments independent (minimal cross-dependencies) - ✅ Use nested fragments for list items - ❌ Don't create too many small fragments (overhead) - ❌ Don't use fragments for tiny components (< 1KB) **Gotchas**: - Fragment names must match exactly between PHP and HTML - Nested fragments require unique identifiers (e.g., `data-product-id`) - Missing fragment in template causes full re-render --- ## Security Attributes ### @RateLimit **Purpose**: Limit the rate at which an action can be executed to prevent abuse. **Signature**: ```php #[RateLimit( int $requests, // Number of allowed requests int $window, // Time window in seconds string $key = 'ip' // Rate limit key ('ip', 'user', 'component') )] ``` **IP-Based Rate Limiting**: ```php final class ContactForm extends LiveComponent { #[LiveAction] #[RateLimit(requests: 3, window: 3600, key: 'ip')] public function submitForm(array $formData): void { // Max 3 submissions per hour per IP address $this->emailService->send($formData); } } ``` **User-Based Rate Limiting**: ```php final class ApiExplorer extends LiveComponent { #[LiveAction] #[RateLimit(requests: 100, window: 60, key: 'user')] public function executeQuery(string $query): void { // Max 100 queries per minute per authenticated user $this->results = $this->apiService->query($query); } } ``` **Component-Based Rate Limiting**: ```php final class ExpensiveReport extends LiveComponent { #[LiveAction] #[RateLimit(requests: 5, window: 300, key: 'component')] public function generateReport(): void { // Max 5 reports per 5 minutes for this component instance $this->report = $this->reportService->generate(); } } ``` **Multiple Rate Limits**: ```php final class PaymentForm extends LiveComponent { #[LiveAction] #[RateLimit(requests: 3, window: 60, key: 'ip')] #[RateLimit(requests: 10, window: 3600, key: 'user')] public function processPayment(array $paymentData): void { // IP: Max 3 per minute // User: Max 10 per hour $this->paymentService->process($paymentData); } } ``` **Best Practices**: - ✅ Use `key: 'ip'` for public endpoints (contact forms, registrations) - ✅ Use `key: 'user'` for authenticated endpoints - ✅ Use `key: 'component'` for expensive operations - ✅ Set generous limits to avoid false positives - ❌ Don't rate limit critical user flows too aggressively **Gotchas**: - Rate limit exceeded returns 429 Too Many Requests - Client automatically shows retry-after countdown - Rate limits are per-action (not per-component) --- ### @Authorize **Purpose**: Restrict action execution to users with specific roles or permissions. **Signature**: ```php #[Authorize( array $roles = [], // Required roles (any match) array $permissions = [], // Required permissions (all match) bool $requireAll = false // Require all roles (default: any) )] ``` **Role-Based Authorization**: ```php final class UserManagement extends LiveComponent { #[LiveAction] #[Authorize(roles: ['admin'])] public function deleteUser(string $userId): void { // Only admins can delete users $this->userService->delete($userId); } #[LiveAction] #[Authorize(roles: ['admin', 'moderator'])] public function banUser(string $userId): void { // Admins OR moderators can ban $this->userService->ban($userId); } } ``` **Permission-Based Authorization**: ```php final class DocumentEditor extends LiveComponent { #[LiveAction] #[Authorize(permissions: ['documents.edit'])] public function saveDocument(string $content): void { $this->documentService->save($content); } #[LiveAction] #[Authorize(permissions: ['documents.delete'])] public function deleteDocument(string $documentId): void { $this->documentService->delete($documentId); } } ``` **Combined Authorization**: ```php final class BillingPanel extends LiveComponent { #[LiveAction] #[Authorize( roles: ['admin', 'billing'], permissions: ['billing.process-refund'], requireAll: true )] public function processRefund(string $orderId): void { // Must have (admin OR billing role) AND billing.process-refund permission $this->billingService->refund($orderId); } } ``` **Dynamic Authorization**: ```php final class ProjectEditor extends LiveComponent { #[LiveProp] public string $projectId; #[LiveAction] public function saveProject(array $data): void { // Custom authorization logic if (!$this->authService->canEditProject($this->projectId)) { throw new UnauthorizedException('You cannot edit this project'); } $this->projectService->save($this->projectId, $data); } } ``` **Best Practices**: - ✅ Use roles for broad access control - ✅ Use permissions for fine-grained control - ✅ Combine roles and permissions for complex requirements - ✅ Show/hide UI elements based on authorization - ❌ Don't rely solely on client-side authorization **Gotchas**: - Authorization failure returns 403 Forbidden - Unauthorized actions don't execute (state unchanged) - Client-side UI should match server-side authorization --- ### @Idempotent **Purpose**: Ensure an action can be safely retried without duplicate side effects. **Signature**: ```php #[Idempotent( string $keyParam = 'idempotencyKey', // Parameter name for idempotency key int $ttl = 3600 // TTL in seconds (default: 1 hour) )] ``` **Basic Usage**: ```php final class OrderForm extends LiveComponent { #[LiveAction] #[Idempotent] public function submitOrder(string $idempotencyKey, array $orderData): void { // Duplicate requests with same idempotencyKey return cached result $order = $this->orderService->create($orderData); $this->orderId = $order->id; } } ``` **HTML Template**: ```html
``` **Custom Key Parameter**: ```php final class PaymentProcessor extends LiveComponent { #[LiveAction] #[Idempotent(keyParam: 'transactionId', ttl: 7200)] public function processPayment(string $transactionId, array $paymentData): void { // Uses 'transactionId' as idempotency key // Cached for 2 hours $this->paymentService->process($transactionId, $paymentData); } } ``` **Use Cases**: - ✅ Order submissions - ✅ Payment processing - ✅ Email sending - ✅ API calls to external services - ✅ Database writes **Best Practices**: - ✅ Use for all non-idempotent operations (CREATE, DELETE) - ✅ Use longer TTL for critical operations (payments: 24 hours) - ✅ Generate idempotency keys client-side (UUID v4) - ❌ Don't use for read-only operations (unnecessary overhead) **Gotchas**: - Idempotent actions return cached response on retry - TTL determines how long duplicates are prevented - Client must provide idempotency key (automatic with `data-lc-idempotency`) --- ### @Encrypted **Purpose**: Automatically encrypt and decrypt sensitive LiveProp values. **Signature**: ```php #[Encrypted( string $algorithm = 'aes-256-gcm' // Encryption algorithm )] ``` **Basic Usage**: ```php final class PaymentForm extends LiveComponent { #[LiveProp] public string $orderId; #[LiveProp] #[Encrypted] public string $creditCardNumber = ''; #[LiveProp] #[Encrypted] public string $cvv = ''; #[LiveAction] public function processPayment(): void { // Properties automatically decrypted here $this->paymentService->charge( $this->creditCardNumber, $this->cvv ); } } ``` **Multiple Encrypted Props**: ```php final class UserProfile extends LiveComponent { #[LiveProp] public string $userId; #[LiveProp] #[Encrypted] public string $ssn = ''; #[LiveProp] #[Encrypted] public string $bankAccount = ''; #[LiveProp] #[Encrypted] public array $sensitiveNotes = []; } ``` **Best Practices**: - ✅ Encrypt all PII (personally identifiable information) - ✅ Encrypt financial data (credit cards, bank accounts) - ✅ Encrypt authentication tokens - ✅ Use in combination with HTTPS - ❌ Don't encrypt non-sensitive data (performance overhead) - ❌ Don't rely solely on encryption (validate and sanitize) **Gotchas**: - Encrypted props increase payload size (~30%) - Encryption/decryption adds ~5ms latency - Requires LIVECOMPONENT_ENCRYPTION_KEY in .env --- ## Performance Attributes ### @Optimistic **Purpose**: Configure optimistic UI updates for instant perceived performance. **Signature**: ```php #[Optimistic( bool $enabled = true, // Enable optimistic updates array $updateProps = [], // Props to update optimistically ?string $rollbackOn = null // Rollback condition )] ``` **Basic Usage**: ```php final class LikeButton extends LiveComponent { #[LiveProp] public int $likes = 0; #[LiveProp] public bool $isLiked = false; #[LiveAction] #[Optimistic(updateProps: ['likes', 'isLiked'])] public function toggleLike(): void { // Client updates UI immediately // Server confirms asynchronously if ($this->isLiked) { $this->likes--; $this->isLiked = false; } else { $this->likes++; $this->isLiked = true; } } } ``` **HTML Template**: ```html
``` **Conditional Rollback**: ```php final class InventoryManager extends LiveComponent { #[LiveProp] public int $stock = 100; #[LiveAction] #[Optimistic( updateProps: ['stock'], rollbackOn: 'stock < 0' )] public function reserveItem(int $quantity): void { if ($this->stock < $quantity) { throw new InsufficientStockException(); } $this->stock -= $quantity; } } ``` **Best Practices**: - ✅ Use for user interactions (likes, votes, favorites) - ✅ Use for non-critical updates - ✅ Provide visual feedback for rollbacks - ❌ Don't use for financial transactions - ❌ Don't use for destructive actions **Gotchas**: - Optimistic updates happen instantly (<50ms) - Server validation can trigger rollback - Network failures automatically rollback --- ### @Cached **Purpose**: Cache action results to improve performance for expensive operations. **Signature**: ```php #[Cached( int $ttl = 3600, // Cache TTL in seconds string $key = 'auto', // Cache key strategy array $tags = [] // Cache tags for invalidation )] ``` **Basic Usage**: ```php final class ReportViewer extends LiveComponent { #[LiveProp] public string $reportId; #[LiveProp] public array $reportData = []; #[LiveAction] #[Cached(ttl: 1800)] public function loadReport(): void { // Expensive operation cached for 30 minutes $this->reportData = $this->reportService->generate($this->reportId); } } ``` **Tagged Caching**: ```php final class ProductCatalog extends LiveComponent { #[LiveProp] public string $categoryId; #[LiveProp] public array $products = []; #[LiveAction] #[Cached(ttl: 3600, tags: ['products', 'category:{categoryId}'])] public function loadProducts(): void { $this->products = $this->productService->getByCategory($this->categoryId); } #[LiveAction] public function invalidateCache(): void { // Invalidate all product caches $this->cache->invalidateTags(['products']); } } ``` **Custom Cache Keys**: ```php final class UserDashboard extends LiveComponent { #[LiveProp] public string $userId; #[LiveAction] #[Cached(ttl: 600, key: 'user:{userId}:dashboard')] public function loadDashboard(): void { // Cache key: "user:123:dashboard" $this->dashboardData = $this->dashboardService->getForUser($this->userId); } } ``` **Best Practices**: - ✅ Cache expensive database queries - ✅ Cache external API calls - ✅ Use tags for batch invalidation - ✅ Set appropriate TTL based on data freshness needs - ❌ Don't cache user-specific sensitive data - ❌ Don't cache highly dynamic data **Gotchas**: - Cache invalidation is eventual (not immediate) - Tagged invalidation requires cache driver support - Cache misses execute full action --- ### @NoBatch **Purpose**: Disable automatic request batching for an action. **Signature**: ```php #[NoBatch] ``` **Basic Usage**: ```php final class FileUploader extends LiveComponent { #[LiveAction] #[NoBatch] public function uploadFile(UploadedFile $file): void { // File uploads should not be batched $this->uploadedFileId = $this->uploadService->store($file); } #[LiveAction] public function deleteFile(string $fileId): void { // Regular action - can be batched $this->uploadService->delete($fileId); } } ``` **Use Cases**: - ✅ File uploads - ✅ Real-time operations - ✅ Time-sensitive actions - ✅ Operations requiring immediate response **Best Practices**: - ✅ Use for operations that can't be delayed - ✅ Use for operations with large payloads - ❌ Don't overuse (batching improves performance) **Gotchas**: - Disables batching only for this specific action - Other actions in the same component can still batch - Increases number of HTTP requests --- ## Validation Attributes ### @Validated **Purpose**: Automatically validate action parameters before execution. **Signature**: ```php #[Validated( array $rules = [], // Validation rules per parameter ?string $errorFragment = null // Fragment to update on validation error )] ``` **Basic Usage**: ```php final class RegistrationForm extends LiveComponent { #[LiveProp] public array $errors = []; #[LiveAction] #[Validated( rules: [ 'email' => ['required', 'email', 'unique:users'], 'password' => ['required', 'min:8', 'confirmed'], 'username' => ['required', 'alphanumeric', 'min:3', 'max:20'] ], errorFragment: 'form-errors' )] public function register(string $email, string $password, string $username): void { // Parameters automatically validated $user = $this->authService->register($email, $password, $username); $this->redirect('/dashboard'); } } ``` **HTML Template**: ```html
{{ errors.email }}
{{ errors.password }}
{{ errors.username }}
Please correct the errors above.
``` **Available Validation Rules**: - `required` - Field must be present and non-empty - `email` - Valid email format - `min:n` - Minimum length/value - `max:n` - Maximum length/value - `numeric` - Numeric value - `alphanumeric` - Alphanumeric characters only - `unique:table,column` - Unique in database - `exists:table,column` - Exists in database - `confirmed` - Match confirmation field (password_confirmation) - `regex:pattern` - Match regex pattern - `in:foo,bar,baz` - Value in list - `url` - Valid URL format - `date` - Valid date format **Custom Validation**: ```php final class ProductForm extends LiveComponent { #[LiveAction] public function saveProduct(array $productData): void { // Custom validation logic $validator = new ProductValidator(); if (!$validator->validate($productData)) { $this->errors = $validator->getErrors(); return; // Stop execution } $this->productService->save($productData); } } ``` **Best Practices**: - ✅ Validate all user input - ✅ Use appropriate rules for each field type - ✅ Provide clear error messages - ✅ Use `errorFragment` to update only error section - ❌ Don't trust client-side validation alone **Gotchas**: - Validation errors prevent action execution - Errors automatically populate `$errors` property - Validation runs before authorization checks --- ## State Management Attributes ### @Persisted **Purpose**: Automatically persist component state across requests/sessions. **Signature**: ```php #[Persisted( string $storage = 'session', // Storage type ('session', 'cookie', 'database') int $ttl = 3600, // TTL in seconds array $props = [] // Specific props to persist (default: all LiveProps) )] ``` **Session Persistence**: ```php final class ShoppingCart extends LiveComponent { #[LiveProp] #[Persisted(storage: 'session')] public array $items = []; #[LiveAction] public function addItem(string $productId, int $quantity): void { // Cart persists across page navigations $this->items[] = [ 'product_id' => $productId, 'quantity' => $quantity ]; } } ``` **Cookie Persistence**: ```php final class ThemeSwitcher extends LiveComponent { #[LiveProp] #[Persisted(storage: 'cookie', ttl: 31536000)] public string $theme = 'light'; #[LiveAction] public function toggleTheme(): void { // Theme persists for 1 year $this->theme = $this->theme === 'light' ? 'dark' : 'light'; } } ``` **Database Persistence**: ```php final class DraftEditor extends LiveComponent { #[LiveProp] public string $documentId; #[LiveProp] #[Persisted(storage: 'database', ttl: 86400)] public string $draftContent = ''; #[LiveAction] public function autosave(string $content): void { // Draft persists for 24 hours $this->draftContent = $content; } } ``` **Selective Persistence**: ```php final class FilterPanel extends LiveComponent { #[LiveProp] public array $filters = []; #[LiveProp] public array $results = []; #[Persisted(storage: 'session', props: ['filters'])] public function mount(): void { // Only 'filters' persisted, not 'results' } } ``` **Best Practices**: - ✅ Use session for temporary state (shopping carts) - ✅ Use cookies for user preferences (theme, locale) - ✅ Use database for long-term drafts - ✅ Set appropriate TTL based on data sensitivity - ❌ Don't persist large amounts of data - ❌ Don't persist sensitive data in cookies **Gotchas**: - Session storage cleared on logout - Cookie storage limited to 4KB - Database storage requires additional queries --- ## Combining Attributes **Multiple Attributes on Single Action**: ```php final class PaymentProcessor extends LiveComponent { #[LiveAction] #[RateLimit(requests: 3, window: 3600, key: 'user')] #[Authorize(permissions: ['payments.process'])] #[Idempotent(ttl: 86400)] #[Validated(rules: [ 'amount' => ['required', 'numeric', 'min:1'], 'currency' => ['required', 'in:USD,EUR,GBP'] ])] #[Fragment('payment-result')] public function processPayment( string $idempotencyKey, float $amount, string $currency ): void { // Secure, rate-limited, idempotent, validated payment processing $this->paymentService->charge($amount, $currency); } } ``` **Execution Order**: 1. **@RateLimit** - Check rate limits first 2. **@Authorize** - Check permissions 3. **@Validated** - Validate parameters 4. **@Idempotent** - Check for duplicate requests 5. **@Cached** - Check cache (if applicable) 6. **Action Execution** - Execute action logic 7. **@Fragment** - Update specific fragments 8. **@Optimistic** - Apply optimistic updates 9. **@Persisted** - Persist state changes --- ## Summary Table | Attribute | Purpose | Performance Impact | Use Case | |-----------|---------|-------------------|----------| | `@LiveProp` | Reactive properties | Low | State synchronization | | `@LiveAction` | Server actions | Low | User interactions | | `@Fragment` | Partial updates | **High** (70%+ reduction) | Large components | | `@RateLimit` | Prevent abuse | Low | Public endpoints | | `@Authorize` | Access control | Low | Restricted actions | | `@Idempotent` | Duplicate prevention | Low | Critical operations | | `@Encrypted` | Data protection | Medium (+30% payload) | Sensitive data | | `@Optimistic` | Instant UI | **High** (<50ms latency) | Interactive UIs | | `@Cached` | Response caching | **High** (avoid queries) | Expensive ops | | `@NoBatch` | Disable batching | Negative (more requests) | File uploads | | `@Validated` | Input validation | Low | User input | | `@Persisted` | State persistence | Medium | User preferences | --- ## Debugging Attributes **Check Attribute Configuration**: ```javascript // Client-side debugging const component = LiveComponent.getComponent('component-id'); console.log(component.config.attributes); // Output: { rateLimit: { requests: 60, window: 60 }, fragments: ['user-profile', 'notifications'], optimistic: { enabled: true, updateProps: ['likes'] }, cached: { ttl: 3600, tags: ['users'] } } ``` **Server-side Debugging**: ```php // Get action metadata $reflection = new \ReflectionMethod(MyComponent::class, 'myAction'); $attributes = $reflection->getAttributes(LiveAction::class); foreach ($attributes as $attribute) { var_dump($attribute->getArguments()); } ``` --- ## Best Practices Summary 1. **Use `@Fragment`** for components >5KB or with independent sections 2. **Use `@Optimistic`** for non-critical user interactions (likes, votes) 3. **Use `@RateLimit`** on all public endpoints and expensive operations 4. **Use `@Authorize`** for all privileged actions 5. **Use `@Idempotent`** for CREATE/DELETE operations 6. **Use `@Encrypted`** for PII and financial data 7. **Use `@Cached`** for expensive queries (>100ms) 8. **Use `@Validated`** for all user input 9. **Combine attributes** for defense-in-depth security 10. **Test attribute behavior** with integration tests --- For more examples and advanced patterns, see: - [Advanced Features Guide](advanced-features.md) - [Performance Guide](performance-guide.md) - [Security Guide](security-guide.md)