4

After upgrading to Laravel 10 I'm having hard times with Larastan errors.

The following code which was perfectly fine until 1 hour ago:

return $this->articleRepository->getDefaultArticles($organizationId)
    ->toBase()
    ->map(function (Article $article) {
        return new Content(
            $article->id,
            $article->title,
            $article->language,
        );
    })
    ->toArray();

now gives me the following error:

Parameter #1 $callback of method Illuminate\Support\Collection<(int|string),Illuminate\Database\Eloquent\Model>::map() expects callable(Illuminate\Database\Eloquent\Model, int|string): App\Academy\Content,
Closure(App\Models\Article): App\Academy\Content given

The repository method has the correct hint:

/**
 * @return Collection<Article>
 */
public function getDefaultArticles(OrganizationId $organizationId): Collection
{
    /** @var Collection<Article> */
    return Article::query()
        ->where('organization_id', $organizationId)
        ->get()
        ->keyBy('id')
        ->values();
}

It gives me 115 new errors and most of them are similar to this, related to collection methods like map and reduce.

The quick solution would be using a temporary variable and add a type hinting:

/** @var Collection<Article> $articles */
$articles = $this->articleRepository
    ->getDefaultArticles($organizationId)
    ->toBase();

but I don't want to do it 100 times and even the IDE is complaining that's unnecessary

enter image description here

Thanks in advance for you help!

matiaslauriti
  • 7,065
  • 4
  • 31
  • 43
Fabio Sasso
  • 145
  • 1
  • 12

5 Answers5

1

The only work around I found so far is to make it in 2 steps with type hinting.

/** @var \Illuminate\Support\Collection $result */
$result = $this->articleRepository->getDefaultArticles($organizationId);

return $result->map(function (Article $article) {
    return new Content(
        $article->id,
        $article->title,
        $article->language,
    );
})
->toArray();

it does not really help to deal with 115 new errors. But if you would have couple errors, it would help.

Yevgeniy Afanasyev
  • 37,872
  • 26
  • 173
  • 191
0

the solution that worked for me was downgrading phpstan:

$ composer require phpstan/phpstan:1.10.11 --dev
Yevgeniy Afanasyev
  • 37,872
  • 26
  • 173
  • 191
0

try

/**
* @return Collection<int,Article>
*/

for getDefaultArticles php doc type

see this: https://github.com/nunomaduro/larastan/blob/master/UPGRADE.md#eloquent-collection-now-requires-2-generic-types

Christian
  • 426
  • 1
  • 5
  • 17
0

Try removing the Article type from the callback of map :

...
->map(function ($article) {
        return new Content(
            $article->id,
            $article->title,
            $article->language,
        );
    })
...
Yevgeniy Afanasyev
  • 37,872
  • 26
  • 173
  • 191
HichemTech
  • 389
  • 2
  • 6
0

Static code analysis tools have the possibility to create a baseline file, which contains existing and known errors to be fixed later - either fixed in the code, or with a corresponding update of the parser & inference tools. This baseline is for instance supported in PhpStan/LaraStan or PsalmPHP.

This way you can acknowledge the described inference flaws and continue with focussing again on the actual application logic.

Baseline file

In older codebases it might be hard to spend the time fixing all the code to pass a high PHPStan Level.

To get around this a baseline file can be generated. The baseline file will create a configuration file with all of the current errors, so new code can be written following a higher standard than the old code. (PHPStan Docs)

vendor/bin/phpstan analyse --generate-baseline

source: https://github.com/nunomaduro/larastan#baseline-file

Find more details in PhpStan's The Baseline section.

Oliver Hader
  • 4,093
  • 1
  • 25
  • 47