1616use PHPStan \Type \IterableType ;
1717use PHPStan \Type \MixedType ;
1818use PHPStan \Type \NullType ;
19+ use PHPStan \Type \ObjectWithoutClassType ;
1920use PHPStan \Type \Type ;
2021use PHPStan \Type \TypeCombinator ;
22+ use PHPStan \Type \TypeTraverser ;
2123use PHPStan \Type \VoidType ;
2224
2325final class QueryResultDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
@@ -109,12 +111,20 @@ private function getMethodReturnTypeForHydrationMode(
109111 return $ this ->originalReturnType ($ methodReflection );
110112 }
111113
112- if (!$ this ->isObjectHydrationMode ($ hydrationMode )) {
113- // We support only HYDRATE_OBJECT. For other hydration modes, we
114- // return the declared return type of the method.
114+ if (!$ hydrationMode instanceof ConstantIntegerType) {
115115 return $ this ->originalReturnType ($ methodReflection );
116116 }
117117
118+ switch ($ hydrationMode ->getValue ()) {
119+ case AbstractQuery::HYDRATE_OBJECT ;
120+ break ;
121+ case AbstractQuery::HYDRATE_ARRAY ;
122+ $ queryResultType = $ this ->getArrayHydratedReturnType ($ queryResultType );
123+ break ;
124+ default :
125+ return $ this ->originalReturnType ($ methodReflection );
126+ }
127+
118128 switch ($ methodReflection ->getName ()) {
119129 case 'getSingleResult ' :
120130 return $ queryResultType ;
@@ -133,13 +143,22 @@ private function getMethodReturnTypeForHydrationMode(
133143 }
134144 }
135145
136- private function isObjectHydrationMode (Type $ type ): bool
146+ private function getArrayHydratedReturnType (Type $ queryResultType ): Type
137147 {
138- if (!$ type instanceof ConstantIntegerType) {
139- return false ;
140- }
141-
142- return $ type ->getValue () === AbstractQuery::HYDRATE_OBJECT ;
148+ return TypeTraverser::map (
149+ $ queryResultType ,
150+ static function (Type $ type , callable $ traverse ): Type {
151+ $ isObject = (new ObjectWithoutClassType ())->isSuperTypeOf ($ type );
152+ if ($ isObject ->yes ()) {
153+ return new ArrayType (new MixedType (), new MixedType ());
154+ }
155+ if ($ isObject ->maybe ()) {
156+ return new MixedType ();
157+ }
158+
159+ return $ traverse ($ type );
160+ }
161+ );
143162 }
144163
145164 private function originalReturnType (MethodReflection $ methodReflection ): Type
0 commit comments