v1.5.0 teaches the analyser about Eloquent primary keys, and relaxes the PHPStan constraint so you can pin around the 2.2.9 regression.
Model key inference
getKey() and modelKeys() used to come back as mixed and array<int, int|string> no matter how the model was configured. They now resolve against the model's own key type:
$model->getKey(); // int|string|null
$user->getKey(); // int|null
$uuidModel->getKey(); // string|null
$users->modelKeys(); // array<int, int|null>
$uuidModels->modelKeys(); // array<int, string|null>
User::query()->modelKeys(); // list<int> (Laravel 13)
UuidModel::query()->modelKeys(); // list<string> (Laravel 13)The key type is read from getKeyType() on an instantiated model rather than from the class, so it sees $keyType, HasUuids, HasUlids, and anything else a trait or the boot sequence contributes. A model whose key type cannot be determined falls back to int|string.
Three details worth knowing, since they are the reason the three results differ:
getKey()and collectionmodelKeys()includenull, because an in-memory model may be unsaved and have no key yet.- Builder
modelKeys()describes a query projection, so it stays non-null, and it is alistbecause the underlyingpluck()is unkeyed. - Collection
modelKeys()keeps the collection's own key type, matching thearray_map()the framework runs over its items.
Builder modelKeys() only exists on Laravel 13, so that inference applies there only.
PHPStan constraint relaxed
phpstan/phpstan is now ^2.2.8 rather than ^2.2.9 (#9).
PHPStan 2.2.9 has a regression affecting root-namespace facade aliases (\Log, \Cache, \Str, and friends) registered by Laravel's alias loader, and the old lower bound left no version combination that avoided it. Nothing here requires 2.2.9, so you can hold at 2.2.8 until PHPStan ships the fix. See phpstan/phpstan#15102.
If you would rather move off the aliases entirely, rector-laravel has a rule that rewrites global facades to their fully qualified equivalents.
Fixes
ModelHelperno longer attempts to instantiate a class that is not an Eloquent model. Key resolution walks the class reflections behind a receiver type, which can include non-models, and that path could otherwise construct an unrelated class during analysis.
Full Changelog: v1.4.0...v1.5.0