Template covariance / Collection<int, Model>
/ Collection<int, *>
/ WHAT??
#2093
Replies: 3 comments 2 replies
-
Sometimes I even get this beauty of an error (when
Are you kidding me??? What is going on inside PhpStan?? |
Beta Was this translation helpful? Give feedback.
-
I fixed /** @return self<int, Model> */
public function relation(string $relationName) : self {
$loaded = $this->pluck($relationName);
if ($loaded->first() instanceof self) {
$loaded = $loaded->flatten(1);
}
if ($loaded->first() instanceof Model) {
return $loaded->first()->newCollection($loaded->all());
}
return new self();
} A custom PhpStan extension takes care of the real return type, eg. |
Beta Was this translation helpful? Give feedback.
-
Maybe I do understand https://phpstan.org/blog/whats-up-with-template-covariant That's actually pretty well explained. So I want to promise PhpStan that I won't mutate the collection, it's just for 'getting'. The article says:
and even though that doesn't seem logical to me, the explanation does, AND it works in my code. 👍 |
Beta Was this translation helpful? Give feedback.
-
I understand covariance and contravariance in PHP classes/methods/functions. I apparently do not understand it in generics.
#1
I have a class
OrderUpdater
that works for any model. It takes aModelCollection
of any model, and updates the models within. Constructor bit:(The smart people probably immediately see the problem with
ModelCollection<int, Model>
because it never takes literalModel
objects.)My controller makes an OrderUpdater:
And then PhpStan complains:
I've read that page 6 times now, and I definitely don't get it. Why doesn't it accept a
Tag
if it needs aModel
?? (That's probably not what it means, but that's what it looks like to me.)#2
So I thought, screw it, I'll just make
ModelCollection
'sTModel
covariant:but now PhpStan complains about that covariant template!
So that's also not how that works.
#3
I found out
ModelCollection<int, *>
is a thing earlier, so that's also an option I thought. Instead ofOrderUpdater
requiringModel
it could require*
:and then everything works for creating the
OrderUpdater
object, BUT not when the class actually acts on the object:because apparently
*
doesn't mean 'anyModel
':but
mixed
?? Really?? Then what is the point of*
? Of course it's aModel
, that's the requirement in the@template
!I'm losing my mind. Please save me, explain to me in little baby language what generic covariance is, and how I can make my ModelCollection AND
OrderUpdater
work.Beta Was this translation helpful? Give feedback.
All reactions