using messenger HandleTrait as QueryBus with appropriate result typing#423
using messenger HandleTrait as QueryBus with appropriate result typing#423bnowak wants to merge 7 commits intophpstan:1.4.xfrom
Conversation
| use HandleTrait; | ||
|
|
||
| public function dispatch(object $query): mixed | ||
| { | ||
| return $this->handle($query); | ||
| } |
There was a problem hiding this comment.
We could also add this test case with changed function name.
| use HandleTrait; | |
| public function dispatch(object $query): mixed | |
| { | |
| return $this->handle($query); | |
| } | |
| use HandleTrait { | |
| handle as private handleQuery; | |
| } | |
| public function handle(object $query): mixed | |
| { | |
| return $this->handleQuery($query); | |
| } |
|
@ondrejmirtes Sorry to disturb you, but I think this is one of the pieces that is missing in this whole puzzle to support. Can we move forward ? |
|
Hi @michaljusiega, thanks for your reply. I think we can add it - no problem. However, from my perspective it's more important to address the root issue (missing feature) of the topic (described here). My reasoning is without having this result interpreted on bus class level - this is much less useful in general. |
|
So this QueryBus class is something in your codebase and you want the same type inference that classes using HandleTrait and calling the You can simply write a dynamic return type extension for |
cc1869e to
9b62bd8
Compare
|
@ondrejmirtes It's ready for review now. You were right about my intentions, however I wanted to make it working for any class that uses It's likely to be conflicted with my another PR about splitting tests, so once first of these PR will be merged I can resolve conflicts on another one. 😉 |
|
@ondrejmirtes any chances to review & merge it soon, please? :) |
| { | ||
| public function __invoke(GetProductQuery $query): Product | ||
| { | ||
| return $this->productRepository->get($query->productId); |
There was a problem hiding this comment.
Can you please add comments to the code in README about the inferred types with and without the extension? I'm still not sure what it does.
There was a problem hiding this comment.
Thanks for reply.
So it's about inferring types of query bus classes (from CQRS pattern) or any custom class which internally use messenger's HandleTrait to get and return result of any dispatched message. Without the extension phpstan is not able to recognize that and gives generic return type of bus class (which in fact is some more specified query result).
So the main difference is calling query bus classes, where based on passed/dispatched message we're getting its correct result type.
I've updated README a bit and the the direct outcome is shown in the end of it - it shows that we're getting Product type instead of generic mixed. If that's still not precised and unclear, please advice me what else I could add/adjust. Maybe my describing skills are not so good 😅
There was a problem hiding this comment.
@ondrejmirtes any chances to re-look on this please?
There was a problem hiding this comment.
@ondrejmirtes please, could you take a look on this again? and sorry for bothering you so many times
cdcaab5 to
a9f07aa
Compare
|
@ondrejmirtes could you review it again please? |
| $arg = $args[0]->value; | ||
| $argClassNames = $scope->getType($arg)->getObjectClassNames(); | ||
|
|
||
| if (count($argClassNames) === 1) { |
There was a problem hiding this comment.
Instead of a check count === 1.
Can't you do
if (count($argClassNames) === 0) {
return null;
}
$returnTypes = [];
foreach ($argClassNames as $argClassName) {
$messageMap = $this->getMessageMap();
$returnType = $messageMap->getTypeForClass($argClassNames[0]);
if ($returnType === null) {
return null;
}
$returnTypes[] = $returnType;
}
return TypeCombinator::union(...$returnTypes);
?
The goal would be to support union like
$queryBus = rand(0, 1) ? $productBus : $itemBus;
$productOrItem = $queryBus->dispatch($query); // Returns: Product|Item
| $varType = $scope->getType($expr->var); | ||
| $classNames = $varType->getObjectClassNames(); | ||
|
|
||
| if (count($classNames) !== 1) { |
There was a problem hiding this comment.
Can't you do something like
if (count($classNames) === 0) {
return false;
}
foreach ($classNames as $className) {
if (!$this->isClassNameSupported($className)) {
return false;
}
}
return true;
In order to support
$query = rand(0, 1) ? $query1 : $query2;
$product = $queryBus->dispatch($query);
This PR goal is to determine correct result typing for QueryBus kind of classes which uses SF messenger HandleTrait internally and simply return its results.