Skip to content

Instantly share code, notes, and snippets.

@rsky
Created April 4, 2024 06:58
Show Gist options
  • Save rsky/1fcd7eef42cb71272113e610d8bcfcd9 to your computer and use it in GitHub Desktop.
Save rsky/1fcd7eef42cb71272113e610d8bcfcd9 to your computer and use it in GitHub Desktop.
PHP名前付き引数を配列から展開してみる
<?php
interface Instantiatable
{
}
class Instantiator
{
/**
* @template T
* @param class-string<T> $class_name
* @param Parameter[] $params
* @return T
*/
public function instantiate(string $class_name, array $params): object
{
if (!is_a($class_name, Instantiatable::class, true)) {
throw new \InvalidArgumentException("$class_name does not implement Instantiatable");
}
return new $class_name(...array_reduce($params, function ($kwargs, $param) {
$kwargs[$param->getName()] = $param->getValue();
return $kwargs;
}, []));
}
}
class Parameter
{
public function __construct(
private readonly string $name,
private readonly string $type,
private readonly string $value,
) {
}
public function getName(): string
{
return $this->name;
}
public function getValue(): mixed
{
return match ($this->type) {
'string' => $this->value,
'int' => intval($this->value),
'float' => floatval($this->value),
'bool' => boolval($this->value),
default => throw new \UnexpectedValueException("Unexpected type: {$this->type}"),
};
}
}
class Hoge implements Instantiatable
{
public function __construct(private readonly int $a, private readonly int $b)
{
}
public function __toString(): string
{
return "a={$this->a}, b={$this->b}";
}
}
$paramSets = [
[
new Parameter(name: 'a', type: 'int', value: '100'),
new Parameter(name: 'b', type: 'int', value: '200'),
],
[
new Parameter(name: 'b', type: 'int', value: '2'),
new Parameter(name: 'a', type: 'int', value: '3'),
],
];
$instantiator = new Instantiator();
foreach ($paramSets as $params) {
$hoge = $instantiator->instantiate(Hoge::class, $params);
echo $hoge, "\n";
}
__halt_compiler();
This will outputs:
$ php ctor_named_args.php
a=100, b=200
a=3, b=2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment