- 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.
336 lines
7.9 KiB
Markdown
336 lines
7.9 KiB
Markdown
# 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)
|
|
```html
|
|
<x-datatable id="users" page="1" pageSize="25" />
|
|
<x-counter id="demo" initialValue="0" />
|
|
```
|
|
|
|
### **HTML Components** (Static)
|
|
```html
|
|
<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
|
|
```php
|
|
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
|
|
```html
|
|
<!-- 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
|
|
```php
|
|
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
|
|
```html
|
|
<!-- 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:
|
|
|
|
```html
|
|
<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
|
|
```html
|
|
<!-- 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)
|
|
```html
|
|
<include template="livecomponent-datatable" data="{id: 'users', page: 1}" />
|
|
```
|
|
|
|
#### Neu
|
|
```html
|
|
<x-datatable id="users" page="1" />
|
|
```
|
|
|
|
### Von `<x-button>` (FrameworkComponentProcessor)
|
|
|
|
**Keine Migration nötig!** Der neue XComponentProcessor handelt das automatisch.
|
|
|
|
```html
|
|
<!-- Works the same -->
|
|
<x-button variant="primary">Click</x-button>
|
|
```
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
### LiveComponents
|
|
1. **Explizite IDs**: Verwende aussagekräftige `id` Attribute
|
|
2. **Type Hints**: Nutze ComponentMetadata für Prop-Validierung
|
|
3. **State Management**: Halte State minimal und serialisierbar
|
|
4. **Actions**: Präfixe Action-Methods mit Action-Verben
|
|
|
|
### HTML Components
|
|
1. **Factory Methods**: Nutze static factories für Variants
|
|
2. **Immutability**: Komponenten sollten readonly sein
|
|
3. **Modifiers**: Fluent API mit `withX()` Methods
|
|
4. **Type Safety**: Return type `self` für Modifiers
|
|
|
|
---
|
|
|
|
## Performance
|
|
|
|
### LiveComponents
|
|
- **First Render**: ~5-10ms (inkl. ComponentRegistry + Rendering)
|
|
- **Updates**: ~2-5ms (nur State Update + Re-Render)
|
|
- **Caching**: Optional via `Cacheable` Interface
|
|
|
|
### HTML Components
|
|
- **Rendering**: ~0.5-1ms (Pure PHP, kein I/O)
|
|
- **No Overhead**: Direkt zu HTML compiled
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
### LiveComponent Test
|
|
```php
|
|
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
|
|
```php
|
|
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**:
|
|
1. Prüfe `#[LiveComponent]` oder `#[ComponentName]` Attribute
|
|
2. Prüfe dass Component-Name korrekt ist
|
|
3. 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
|
|
```html
|
|
<!-- 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!** 🎉
|