Open rela589n opened 6 months ago
In some distant future, if PHP has single-parameter Closure unpacking, it would be possible to make following calls:
private function getCommand(
UpdateFamilyProfileCommandDto $commandDto,
): UpdateFamilyProfileCommand {
/** @var Closure(): Uuid $id */
$id = $this->getId($commandDto);
/** @var Closure(): Family $family */
$family = $this->getFamily($commandDto);
return new UpdateFamilyProfileCommand($id, $family);
}
final class UpdateFamilyProfileCommand
{
public function __construct(
private Uuid $id,
private Family $family,
) {
}
}
Where single-parameter Closure is reduced to the actual value behind the scenes during the method call.
Most likely the problem is more generic than closures - it is all about code evaluation.
If PHP had lazy evaluation, I guess there would be no need to pack everything up with closures.
Also, interaction combinators evaluation is much more powerful than sequential code evaluation
It seems that in latest version of PHP lazy objects are going to be introduced.
I think it's a good thing to consider.
One could use amphp/amp to create a future for the needed value and then use it in place of lazy object.
TODO: check this point in the PHP email list
In most applications it makes sense to show full list of validation errors, not just the first one (as with the case of exception).
Technically it seems to be possible to implement this feature, though with somewhat oddish syntax.
The converter should throw as much details regarding what is wrong with given command as possible.
When combined with https://github.com/phphd/exceptional-validation-bundle/ this could give a strong foundation for enterprise applications.
The key idea is to use one-level indirection during command conversion:
Here function is returned, and both
$id
and$family
variables are functions.This way it would be possible to change the execution flow from DFS into BFS, and therefore catch all the exceptions from given closures.
As a simple convention to introduce - when closure uses closure variables with no parameters, - then we could call it separately.
The rest of thoughs are in the code: