#!/usr/bin/env php $count]); } public function withName(string $name): self { return clone($this, ['name' => $name]); } } try { $state1 = new TestState(count: 5, name: 'Test'); echo "Original: count={$state1->count}, name={$state1->name}\n"; $state2 = $state1->withCount(10); echo "Nach withCount(10): count={$state2->count}, name={$state2->name}\n"; echo "Original unverändert: count={$state1->count}, name={$state1->name}\n"; if ($state2->count === 10 && $state2->name === 'Test' && $state1->count === 5) { echo "✅ Test 1 erfolgreich\n\n"; } else { echo "❌ Test 1 fehlgeschlagen\n\n"; } } catch (\Throwable $e) { echo "❌ Test 1 fehlgeschlagen: " . $e->getMessage() . "\n\n"; } // Test 2: Mehrere Properties ändern echo "Test 2: Mehrere Properties ändern\n"; final readonly class CounterState { public function __construct( public int $count = 0, public string $lastUpdate = '', public int $renderCount = 0 ) { } public function increment(): self { return clone($this, [ 'count' => $this->count + 1, 'lastUpdate' => date('H:i:s') ]); } } try { $counter1 = new CounterState(count: 5, lastUpdate: '10:00:00', renderCount: 3); echo "Original: count={$counter1->count}, lastUpdate={$counter1->lastUpdate}, renderCount={$counter1->renderCount}\n"; $counter2 = $counter1->increment(); echo "Nach increment(): count={$counter2->count}, lastUpdate={$counter2->lastUpdate}, renderCount={$counter2->renderCount}\n"; echo "Original unverändert: count={$counter1->count}, renderCount={$counter1->renderCount}\n"; if ($counter2->count === 6 && $counter2->renderCount === 3 && $counter1->count === 5) { echo "✅ Test 2 erfolgreich\n\n"; } else { echo "❌ Test 2 fehlgeschlagen\n\n"; } } catch (\Throwable $e) { echo "❌ Test 2 fehlgeschlagen: " . $e->getMessage() . "\n\n"; } // Test 3: Komplexere Transformation mit berechneten Werten echo "Test 3: Komplexere Transformation\n"; final readonly class SearchState { public function __construct( public string $query = '', public array $results = [], public int $resultCount = 0 ) { } public function clear(): self { return clone($this, [ 'query' => '', 'results' => [], 'resultCount' => 0 ]); } } try { $search1 = new SearchState(query: 'test', results: ['item1', 'item2'], resultCount: 2); echo "Original: query={$search1->query}, resultCount={$search1->resultCount}\n"; $search2 = $search1->clear(); echo "Nach clear(): query={$search2->query}, resultCount={$search2->resultCount}\n"; echo "Original unverändert: query={$search1->query}, resultCount={$search1->resultCount}\n"; if ($search2->query === '' && $search2->resultCount === 0 && $search1->query === 'test') { echo "✅ Test 3 erfolgreich\n\n"; } else { echo "❌ Test 3 fehlgeschlagen\n\n"; } } catch (\Throwable $e) { echo "❌ Test 3 fehlgeschlagen: " . $e->getMessage() . "\n\n"; } // Test 4: Nullable Properties echo "Test 4: Nullable Properties\n"; final readonly class AssetState { public function __construct( public ?string $selectedAssetId = null, public bool $isOpen = false ) { } public function withSelectedAsset(?string $assetId): self { return clone($this, ['selectedAssetId' => $assetId]); } } try { $asset1 = new AssetState(selectedAssetId: 'asset-123', isOpen: true); echo "Original: selectedAssetId={$asset1->selectedAssetId}, isOpen=" . ($asset1->isOpen ? 'true' : 'false') . "\n"; $asset2 = $asset1->withSelectedAsset(null); echo "Nach withSelectedAsset(null): selectedAssetId=" . ($asset2->selectedAssetId ?? 'null') . ", isOpen=" . ($asset2->isOpen ? 'true' : 'false') . "\n"; if ($asset2->selectedAssetId === null && $asset2->isOpen === true && $asset1->selectedAssetId === 'asset-123') { echo "✅ Test 4 erfolgreich\n\n"; } else { echo "❌ Test 4 fehlgeschlagen\n\n"; } } catch (\Throwable $e) { echo "❌ Test 4 fehlgeschlagen: " . $e->getMessage() . "\n\n"; } echo "=== Test Complete ===\n"; echo "PHP Version: " . PHP_VERSION . "\n";