I am trying to extract the constructor parameters from an object so I can pass them as arguments to a different function.
$args = $object->getConstructorParams();
some_func(...$args);
I don't have access to the definition of some_func
.
I can define the object class myself, I would prefer it to be and abstract class.
The core of the problem is that child classes might have different construct arguments.
I was thinking something along the lines of
abstract class mom
{
private $args;
public function __construct(...$args)
{
$this->args = $args;
}
public function getConstructorParams()
{
return $this->args;
}
}
class child extends mom
{
public $name;
public function __construct($name)
{
parent::__construct($name);
$this->name = $name;
}
}
But that puts a lot of pressure on the right implementation of the constructor in the daughter classes. Is there a more elegant way to achieve something similar?
I have looked at get_object_vars
, but the object can have a ton of parameters that are not necessarily all passed to the constructor. I Have also looked at ReflectionClass::getConstructor()
and ReflectionFunctionAbstract::getParameters()
but this only seems to be able to get the names of parameters and not the actual values.
Combining both get_object_vars
and the relfections comes a long way, but would miss passed arguments if they are not stored directly in the object.
I am trying to extract the constructor parameters from an object so I can pass them as arguments to a different function.
$args = $object->getConstructorParams();
some_func(...$args);
I don't have access to the definition of some_func
.
I can define the object class myself, I would prefer it to be and abstract class.
The core of the problem is that child classes might have different construct arguments.
I was thinking something along the lines of
abstract class mom
{
private $args;
public function __construct(...$args)
{
$this->args = $args;
}
public function getConstructorParams()
{
return $this->args;
}
}
class child extends mom
{
public $name;
public function __construct($name)
{
parent::__construct($name);
$this->name = $name;
}
}
But that puts a lot of pressure on the right implementation of the constructor in the daughter classes. Is there a more elegant way to achieve something similar?
I have looked at get_object_vars
, but the object can have a ton of parameters that are not necessarily all passed to the constructor. I Have also looked at ReflectionClass::getConstructor()
and ReflectionFunctionAbstract::getParameters()
but this only seems to be able to get the names of parameters and not the actual values.
Combining both get_object_vars
and the relfections comes a long way, but would miss passed arguments if they are not stored directly in the object.
Asking for the constructor parameters is a key thing here. You are actually looking for parameters.
Make the class representing those parameters and delegate the relationship to actual objects.
Example:
readonly class person
{
public function __construct(private string $name, private ?person $parent) {}
}
$mom = new person('mom', null);
assert($mom instanceof person);
$child = new person('child', $mom);
assert($child instanceof person);
Not every mum is a child, well, actually they are all persons (or whatever, humans love simplification and object orientation is just an example of that, a box for everything and the world is alright).
Demo
You only benefit from an abstraction if it is really abstract (leaving things out, defer the details), otherwise you have to implement everything and for that you would use code-generation (and then traits).
And then:
I don't have access to the definition of
some_func
[but to the classes]
Again, we can inject the function as well, as if it would be a parameter.
Some made-up example, but often calling a functions mean we want to (or can) switch context/category (similar as in math):
readonly class person
{
// ...
public function export(closure $replacer)
{
return $replacer(random_int(-21, 20), ucfirst($this->name));
}
}
And that in the action:
// the following three dots "..." dot-dot-dot are NOT an omission
$result = $child->export(some_func(...));
assert(is_some_from_func($result));
Don't ask for things (parameters), just inject and implement. The things continue to compute without much break. And it remains easy to refactor and test.