parent
4c806c8e16
commit
67d795a506
5 changed files with 184 additions and 0 deletions
@ -0,0 +1,35 @@ |
||||
--TEST-- |
||||
Symfony pattern: attribute array arguments |
||||
--SKIPIF-- |
||||
<?php |
||||
exit('skip Array arguments to attributes are not supported by the AOT compiler'); |
||||
?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS)] |
||||
final class SymfonyLikeRoute |
||||
{ |
||||
public function __construct(public array $methods = []) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
#[SymfonyLikeRoute(methods: ['GET', 'POST'])] |
||||
class SymfonyLikeController |
||||
{ |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$route = (new ReflectionClass(SymfonyLikeController::class))->getAttributes(SymfonyLikeRoute::class)[0]->newInstance(); |
||||
var_dump($route->methods); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
array(2) { |
||||
[0]=> |
||||
string(3) "GET" |
||||
[1]=> |
||||
string(4) "POST" |
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
--TEST-- |
||||
Symfony pattern: class attribute with named arguments and constructor normalization |
||||
--FILE-- |
||||
<?php |
||||
|
||||
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] |
||||
final class SymfonyLikeCommand |
||||
{ |
||||
public function __construct( |
||||
public string $name, |
||||
public ?string $description = null, |
||||
array $aliases = [], |
||||
bool $hidden = false, |
||||
public ?string $help = null, |
||||
public array $usages = [], |
||||
) { |
||||
if (!$hidden && !$aliases) { |
||||
return; |
||||
} |
||||
|
||||
$names = explode('|', $name); |
||||
$names = array_merge($names, $aliases); |
||||
|
||||
if ($hidden && '' !== $names[0]) { |
||||
array_unshift($names, ''); |
||||
} |
||||
|
||||
$this->name = implode('|', $names); |
||||
} |
||||
} |
||||
|
||||
#[SymfonyLikeCommand(name: 'cache:clear', description: 'Clear cache', hidden: true, help: 'Clears generated cache')] |
||||
class SymfonyLikeClearCacheCommand |
||||
{ |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$attribute = (new ReflectionClass(SymfonyLikeClearCacheCommand::class))->getAttributes(SymfonyLikeCommand::class)[0]; |
||||
$command = $attribute->newInstance(); |
||||
|
||||
var_dump($command->name); |
||||
var_dump($command->description); |
||||
var_dump($command->usages); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(12) "|cache:clear" |
||||
string(11) "Clear cache" |
||||
array(0) { |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
--TEST-- |
||||
Symfony pattern: container caches first-class method callable with ??= |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeContainer |
||||
{ |
||||
public array $services = []; |
||||
|
||||
public function getService(string $id): string |
||||
{ |
||||
return 'service:'.$id; |
||||
} |
||||
|
||||
public function locator(): array |
||||
{ |
||||
return [ |
||||
$this->getService ??= $this->getService(...), |
||||
['foo', 'bar'], |
||||
]; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$container = new SymfonyLikeContainer(); |
||||
[$factory, $ids] = $container->locator(); |
||||
|
||||
foreach ($ids as $id) { |
||||
var_dump($factory($id)); |
||||
} |
||||
|
||||
var_dump($container->getService instanceof Closure); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(11) "service:foo" |
||||
string(11) "service:bar" |
||||
bool(true) |
||||
@ -0,0 +1,33 @@ |
||||
--TEST-- |
||||
Symfony pattern: dynamic method forwarding with unpacked arguments |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeInnerSerializer |
||||
{ |
||||
public function format(string $value, string $prefix = '', string $suffix = ''): string |
||||
{ |
||||
return $prefix.strtoupper($value).$suffix; |
||||
} |
||||
} |
||||
|
||||
class SymfonyLikeTraceableSerializer |
||||
{ |
||||
public function __construct(private SymfonyLikeInnerSerializer $serializer) |
||||
{ |
||||
} |
||||
|
||||
public function __call(string $method, array $arguments): mixed |
||||
{ |
||||
return $this->serializer->{$method}(...$arguments); |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
$serializer = new SymfonyLikeTraceableSerializer(new SymfonyLikeInnerSerializer()); |
||||
var_dump($serializer->format('symfony', '[', ']')); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(9) "[SYMFONY]" |
||||
@ -0,0 +1,26 @@ |
||||
--TEST-- |
||||
Symfony pattern: local variable reassigns from string to array in constructor |
||||
--SKIPIF-- |
||||
<?php |
||||
exit('skip Known AOT compile bug: local variable cannot widen from string to array'); |
||||
?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class SymfonyLikeCommandNameNormalizer |
||||
{ |
||||
public function __construct(public string $name, array $aliases = []) |
||||
{ |
||||
$name = explode('|', $name); |
||||
$name = array_merge($name, $aliases); |
||||
$this->name = implode('|', $name); |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump((new SymfonyLikeCommandNameNormalizer('cache:clear', ['cache:clean']))->name); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(23) "cache:clear|cache:clean" |
||||
Loading…
Reference in new issue