-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bug: Model::find() returns incorrect type #7
Comments
Except for the last error, the errors are coming because PHPStan does not know what is the type of diff --git a/app/Models/ThreadModel.php b/app/Models/ThreadModel.php
index fac36b3..74d0dfc 100644
--- a/app/Models/ThreadModel.php
+++ b/app/Models/ThreadModel.php
@@ -172,6 +172,8 @@ class ThreadModel extends Model
$categoryModel = model(CategoryModel::class);
+ \PHPStan\dumpType($data['data']['category_id']);
+
// Update stats for new category
$newCategory = $categoryModel->allowCallbacks(false)->find($data['data']['category_id']);
$newCategory->thread_count++; will give It needs to know that the category_id index is either string or null. You can solve this by setting up an array shape to the parameter |
Assuming you did an assert call instead to is_int. diff --git a/app/Models/ThreadModel.php b/app/Models/ThreadModel.php
index fac36b3..e5b8711 100644
--- a/app/Models/ThreadModel.php
+++ b/app/Models/ThreadModel.php
@@ -171,6 +171,8 @@ class ThreadModel extends Model
}
$categoryModel = model(CategoryModel::class);
+
+ assert(is_int($data['data']['category_id']));
// Update stats for new category
$newCategory = $categoryModel->allowCallbacks(false)->find($data['data']['category_id']); The errors now would be:
At the moment, this extension does not yet understand the casts of Entities. |
Why does it assume |
Because of these lines: phpstan-codeigniter/src/Type/ModelFindReturnTypeExtension.php Lines 87 to 97 in d4f77ab
If the type is |
Why the casts of Entities that can be understood without specifying a type cannot be understood with specifying type with |
By default, PHPStan does not know what is the relation of |
Ah, by default PHPStan does not know the Entiy property types. I misunderstood it. |
The logic below is not correct after all in many cases. Because guessed phpstan-codeigniter/src/Type/ModelFindReturnTypeExtension.php Lines 87 to 97 in d4f77ab
The last line should be the second return, because finding single record is the most use cases for |
If we'll make the last line as an if check to array, then we still need to account for all other cases. Like, if passed id is not |
I mean like this. function (Type $idType, callable $traverse) use ($methodReflection, $methodCall, $scope): Type {
if ($idType instanceof UnionType || $idType instanceof IntersectionType) {
return $traverse($idType);
}
if ($idType->isNull()->yes() || $idType->isArray()->yes()) {
return $this->getTypeFromFindAll($methodReflection, $methodCall, $scope);
}
if ($idType->isInteger()->yes() || $idType->isString()->yes()) {
$classReflection = $this->getClassReflection($methodCall, $scope);
return TypeCombinator::addNull($this->modelFetchedReturnTypeHelper->getFetchedReturnType($classReflection, $methodCall, $scope));
}
// We don't know the correct type, we assume it is a int or string.
$classReflection = $this->getClassReflection($methodCall, $scope);
return TypeCombinator::addNull($this->modelFetchedReturnTypeHelper->getFetchedReturnType($classReflection, $methodCall, $scope));
} |
I think the current code is correct. Looking at the code of Model::doFind, the check is first see if id is array, or check if string or int, then it has an else encompassing all other cases which returns all records. |
See the product code. |
It's because at runtime the id resolves to either a string or null. However, phpstan does not run the code. Thus, it thinks that the id is mixed. |
Yes, but the |
I might be stating something stupidly obvious and not helpful but... wouldn't a conditional return on https://phpstan.org/blog/phpstan-1-6-0-with-conditional-return-types |
It wouldn't be easy. You would need to annotate that the each calling model returns a return type (array, Entity, custom object, stdClass). Maybe generics could do the job? Also, you need to note that when asArray() and asObject() is called the return type also changes. |
I already sent codeigniter4/CodeIgniter4#8187 |
Thanks you two. I think all of the work going into this is telling what a mess Model/BaseModel is. 😓 |
PHP Version
8.1
PHPStan CodeIgniter Version
v1.4.2.70400
PHPStan Version
1.10.39
What happened?
https://github.com/kenjis/forum-example/blob/37a339f050ee2c40ed452e6570cef188dc0f90a0/app/Models/ThreadModel.php#L173-L195
Minimum Reproduction Script
Expected Output
No errors on ThreadModel.
The text was updated successfully, but these errors were encountered: