Larastan: getQuery() results in infering wrong type of result

Created on 21 Jul 2020  Â·  6Comments  Â·  Source: nunomaduro/larastan

  • Larastan Version: 0.6.1 / ^0.6-dev
  • --level used: 6

Description

I've code like this:

<?php
$result = SomeModel
    ::getQuery()
    ->select('some_model.created')
    ->where('some_model.some_column', '=', true)
    ->orderBy('some_model.created', 'desc')
    ->first();

return $result ? new CarbonImmutable($result->created) : null;

The model (ide-helper generated):

/**
 * …
 * @property \Carbon\CarbonImmutable $created
 * @mixin \Eloquent
 */
class SomeModel extends Model

The reason ide-helper generates is that is that created is part of SomeModel::$dates.

The reported error:

 ------ ----------------------------------------------------------------
  Line   App/Foo.php
 ------ ----------------------------------------------------------------
  415    Parameter #1 $time of class Carbon\CarbonImmutable constructor
         expects string|null, Carbon\CarbonImmutable given.
 ------ ----------------------------------------------------------------

Larastan thinks that the result after ::getQuery() is indeed a model => but in fact it isn't. Those results are not hydrated and are anonymous stdClass which raw properties, not casted etc.

So it thinks $result is SomeModel and thus ->created is a CarbonImmutable => but it isn't. It's a raw string (or could be null or literally anything).

(the code is deliberately written to not hydrate a model when not necessary as only a specific part is needed for a short duration)

bug

Most helpful comment

Larastan thinks getQuery returns Illuminate\Database\Eloquent\Builder and not Illuminate\Database\Query\Builder I think this is the problem. Will try to fix it.

All 6 comments

What is the result if you remove the ide-helper created @property?

In this case there's no error reported.

(wild guess: phpstan / larstan doesn't know anything about the type and assumes any/mixed and thus doesn't complain what's passed to the CarbonImmutable constructor?)

Larastan thinks getQuery returns Illuminate\Database\Eloquent\Builder and not Illuminate\Database\Query\Builder I think this is the problem. Will try to fix it.

Btw, when I change it to:

<?php
/** @var \Illuminate\Database\Query\Builder $result */
$result = SomeModel
    ::getQuery();
$result
    ->select('some_model.created')
    ->where('some_model.some_column', '=', true)
    ->orderBy('some_model.created', 'desc')
    ->first();

return $result ? new CarbonImmutable($result->created) : null;

I get:

  417    Access to an undefined property
         Illuminate\Database\Query\Builder::$created.

@mfn In that last example you forgot to reassign the result after fetching it with first I think that's the reason you got that error.

Anyway, this should be fixed with #617

@canvural lol, you're right #fail

But I can confirm #617 fixes it, tested it on the real project and error was not reported! 🙇

Was this page helpful?
0 / 5 - 0 ratings