Skip to content

Commit dcc72ed

Browse files
committed
Type getResult() from its constant $type argument
1 parent 157aaae commit dcc72ed

3 files changed

Lines changed: 40 additions & 0 deletions

File tree

docs/type-inference.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ framework declares as a bare `array` or a loose object union at the interface le
125125
126126
- `getResultArray()`: `list<array<string, mixed>>`
127127
- `getResultObject()`: `list<stdClass>`
128+
- `getResult($type)`: a list keyed off the constant `$type`, namely `list<array<string, mixed>>` for
129+
`'array'`, `list<stdClass>` for `'object'` (the default), and `list<T>` for a `class-string`.
128130
- `getRowArray()`: `array<string, mixed>|null`
129131
- `getRowObject()`: `stdClass|null`
130132
- `getCustomResultObject($className)`: `list<T>` when `$className` is a constant `class-string`, or a

src/Type/ResultMethodReturnTypeExtension.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public function getClass(): string
4848
public function isMethodSupported(MethodReflection $methodReflection): bool
4949
{
5050
return in_array($methodReflection->getName(), [
51+
'getResult',
5152
'getResultArray',
5253
'getResultObject',
5354
'getRowArray',
@@ -59,6 +60,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool
5960
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): ?Type
6061
{
6162
return match ($methodReflection->getName()) {
63+
'getResult' => $this->resultType($methodCall, $scope),
6264
'getResultArray' => $this->listOf(new ArrayType(new StringType(), new MixedType())),
6365
'getResultObject' => $this->listOf(new ObjectType(stdClass::class)),
6466
'getRowArray' => TypeCombinator::addNull(new ArrayType(new StringType(), new MixedType())),
@@ -68,6 +70,33 @@ public function getTypeFromMethodCall(MethodReflection $methodReflection, Method
6870
};
6971
}
7072

73+
/**
74+
* Types `getResult($type)` from its constant `$type`: `'array'`, `'object'` (the default), or a
75+
* class name. A non-constant `$type` leaves the framework's declared `array`.
76+
*/
77+
private function resultType(MethodCall $methodCall, Scope $scope): ?Type
78+
{
79+
$args = $methodCall->getArgs();
80+
81+
if (! isset($args[0])) {
82+
return $this->listOf(new ObjectType(stdClass::class));
83+
}
84+
85+
$strings = $scope->getType($args[0]->value)->getConstantStrings();
86+
87+
if (count($strings) !== 1) {
88+
return null;
89+
}
90+
91+
$value = $strings[0]->getValue();
92+
93+
return match ($value) {
94+
'array' => $this->listOf(new ArrayType(new StringType(), new MixedType())),
95+
'object' => $this->listOf(new ObjectType(stdClass::class)),
96+
default => $this->listOf($this->reflectionProvider->hasClass($value) ? new ObjectType($value) : new ObjectWithoutClassType()),
97+
};
98+
}
99+
71100
private function customObjectType(MethodCall $methodCall, Scope $scope): Type
72101
{
73102
$args = $methodCall->getArgs();

tests/data/type-inference/database-result-methods.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,13 @@ function resultAccessors(ResultInterface $result, string $dynamic): void
3434

3535
// Already precise on the interface via a conditional @return, so the extension leaves it untouched.
3636
assertType('stdClass|null', $result->getRow(0));
37+
38+
// getResult($type) is typed from its constant $type argument.
39+
assertType('list<stdClass>', $result->getResult());
40+
assertType('list<stdClass>', $result->getResult('object'));
41+
assertType('list<array<string, mixed>>', $result->getResult('array'));
42+
assertType('list<CodeIgniter\PHPStan\Tests\Fixtures\Entity\BlogComment>', $result->getResult(BlogComment::class));
43+
44+
// A non-constant $type leaves the framework's declared array.
45+
assertType('array', $result->getResult($dynamic));
3746
}

0 commit comments

Comments
 (0)