- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
7.9 KiB
7.9 KiB
X-Component Syntax
Unified component system für LiveComponents und HTML Components mit moderner <x-*> Syntax.
Übersicht
Der XComponentProcessor handelt beide Komponenten-Typen automatisch:
LiveComponents (Interactive/Stateful)
<x-datatable id="users" page="1" pageSize="25" />
<x-counter id="demo" initialValue="0" />
HTML Components (Static)
<x-button variant="primary">Submit</x-button>
<x-card title="Profile">Content here</x-card>
Auto-Detection
Der Processor erkennt automatisch welcher Komponenten-Typ verwendet werden soll:
1. Prüfe: Ist LiveComponent mit #[LiveComponent] registriert?
→ Ja: Process as LiveComponent (stateful)
2. Prüfe: Ist HTML Component mit #[ComponentName] registriert?
→ Ja: Process as HTML Component (static)
3. Keins gefunden?
→ Error with helpful message
LiveComponents
Definition
use App\Framework\LiveComponents\Attributes\LiveComponent;
use App\Framework\LiveComponents\Contracts\LiveComponentContract;
#[LiveComponent(name: 'datatable')]
final readonly class DataTableComponent implements LiveComponentContract
{
public function __construct(
private ComponentId $id,
private ?ComponentData $initialData = null
) {}
#[Action]
public function changePage(int $page): void
{
// Interactive behavior
}
public function getRenderData(): RenderData
{
return new RenderData(
templatePath: 'livecomponent-datatable',
data: [
'page' => $this->getData()->get('page'),
'items' => $this->loadItems()
]
);
}
}
Usage
<!-- Basic usage -->
<x-datatable id="users" page="1" pageSize="25" />
<!-- Type coercion -->
<x-datatable
id="users" <!-- string: "users" -->
page="1" <!-- int: 1 -->
pageSize="25" <!-- int: 25 -->
sortAsc="true" <!-- bool: true -->
filters='["active"]' <!-- array: ["active"] -->
/>
<!-- Rendered output (with state wrapper) -->
<div
data-component-id="datatable:users"
data-component-state='{"page":1,"pageSize":25}'
>
<!-- Component HTML -->
</div>
Features
- ✅ Stateful: Komponente behält State
- ✅ Interactive:
#[Action]Methods für User-Interaktion - ✅ Type Coercion: Automatische Typ-Konvertierung
- ✅ Prop Validation: Validierung gegen ComponentMetadata
- ✅ SSE Support: Server-Sent Events für Realtime Updates
HTML Components
Definition
use App\Framework\View\Attributes\ComponentName;
use App\Framework\View\ValueObjects\HtmlElement;
#[ComponentName(tag: 'button')]
final readonly class Button extends HtmlElement
{
public function __construct(
private string $content,
private string $variant = 'default'
) {}
public function withVariant(string $variant): self
{
return new self($this->content, $variant);
}
public function __toString(): string
{
return sprintf(
'<button class="btn btn-%s">%s</button>',
$this->variant,
htmlspecialchars($this->content)
);
}
}
Usage
<!-- Basic usage -->
<x-button>Click me</x-button>
<!-- With variant modifier -->
<x-button variant="primary">Submit</x-button>
<!-- Rendered output (static HTML) -->
<button class="btn btn-primary">Submit</button>
Features
- ✅ Stateless: Einfache HTML-Generierung
- ✅ Factory Methods: Static constructors für Variants
- ✅ Modifiers: Fluent API mit
withX()Methods - ✅ Type Safe: PHP Classes statt Template Strings
Type Coercion (LiveComponents only)
LiveComponents supporten automatische Typ-Konvertierung:
<x-component
string="text" <!-- "text" -->
int="123" <!-- 123 -->
float="12.5" <!-- 12.5 -->
bool-true="true" <!-- true -->
bool-false="false" <!-- false -->
null-value="null" <!-- null -->
array='[1,2,3]' <!-- [1,2,3] -->
object='{"key":"val"}' <!-- ["key" => "val"] -->
/>
HTML Components erhalten alle Attribute als Strings.
Error Handling
Development Mode
<!-- Invalid component -->
<x-unknown id="test" />
<!-- Error display -->
<div style="border:2px solid red;...">
<strong>XComponentProcessor Error:</strong>
<pre>
Unknown component: <x-unknown>
Available LiveComponents: datatable, counter, chart
Available HTML Components: button, card, badge
</pre>
</div>
Production Mode
- Component wird entfernt (silent fail)
- Error wird geloggt (optional)
- Kein Crash, Seite funktioniert weiter
Migration von alten Syntaxen
Von <include> zu <x-*>
Alt (LiveComponents)
<include template="livecomponent-datatable" data="{id: 'users', page: 1}" />
Neu
<x-datatable id="users" page="1" />
Von <x-button> (FrameworkComponentProcessor)
Keine Migration nötig! Der neue XComponentProcessor handelt das automatisch.
<!-- Works the same -->
<x-button variant="primary">Click</x-button>
Best Practices
LiveComponents
- Explizite IDs: Verwende aussagekräftige
idAttribute - Type Hints: Nutze ComponentMetadata für Prop-Validierung
- State Management: Halte State minimal und serialisierbar
- Actions: Präfixe Action-Methods mit Action-Verben
HTML Components
- Factory Methods: Nutze static factories für Variants
- Immutability: Komponenten sollten readonly sein
- Modifiers: Fluent API mit
withX()Methods - Type Safety: Return type
selffür Modifiers
Performance
LiveComponents
- First Render: ~5-10ms (inkl. ComponentRegistry + Rendering)
- Updates: ~2-5ms (nur State Update + Re-Render)
- Caching: Optional via
CacheableInterface
HTML Components
- Rendering: ~0.5-1ms (Pure PHP, kein I/O)
- No Overhead: Direkt zu HTML compiled
Testing
LiveComponent Test
it('renders datatable component via x-syntax', function() {
$html = '<x-datatable id="test" page="1" />';
$result = $this->processor->process($dom, $context);
expect($result)->toContain('data-component-id="datatable:test"');
expect($result)->toContain('data-component-state');
});
HTML Component Test
it('renders button component via x-syntax', function() {
$html = '<x-button variant="primary">Click</x-button>';
$result = $this->processor->process($dom, $context);
expect($result)->toBe('<button class="btn btn-primary">Click</button>');
});
Troubleshooting
Component nicht gefunden
Unknown component: <x-foo>
Available LiveComponents: datatable, counter
Available HTML Components: button, card
Lösung:
- Prüfe
#[LiveComponent]oder#[ComponentName]Attribute - Prüfe dass Component-Name korrekt ist
- Prüfe dass Discovery System läuft
Props werden nicht erkannt
LiveComponent 'datatable' has no property 'pagesize'
Available properties: page, pageSize, sortBy
Lösung:
- Prüfe Schreibweise (Case-Sensitive!)
- Prüfe ComponentMetadata
Type Coercion funktioniert nicht
<!-- Problem: "1" bleibt String -->
<x-datatable page="1" />
Lösung:
- Nur für LiveComponents!
- HTML Components erhalten Strings
- Prüfe dass Component LiveComponent ist
Zusammenfassung
| Feature | LiveComponents | HTML Components |
|---|---|---|
| Syntax | <x-name /> |
<x-name>content</x-name> |
| State | ✅ Stateful | ❌ Stateless |
| Interactivity | ✅ Actions | ❌ Static HTML |
| Type Coercion | ✅ Automatic | ❌ Strings only |
| Validation | ✅ Via Metadata | ❌ No validation |
| Performance | ~5-10ms | ~0.5-1ms |
| Use Case | Complex UI | Simple HTML |
Both use the same <x-*> syntax! 🎉