larastan: Undefined property UserResource::$pivot

  • Larastan Version: 0.5.5
  • --level used: 1

Description

The command larastan analyse throws an error on JsonResources that use $this->pivot. I’ve an User model with a m:m relationship to another table. UserResource will load some data of the pivot table if it is requested using the method whenPivotLoaded. The problem is that Larastan does not recognize the pivot as a valid property.

The error that Larastan throws is this:

 {
        "description": "Access to an undefined property App\\Http\\Resources\\UserResource::$pivot.",
        "fingerprint": "b910d56075e641d4c94e7412d3e499d7b832002568a667e1d5ee2ca0c888e18b",
        "location": {
            "path": "app/Http/Resources/UserResource.php",
            "lines": {
                "begin": 45
            }
        }
    },

Laravel code where the issue was found

/**
 * @extends JsonResource<\App\User>
*/
class UserResource extends JsonResource
{
    // Other parts of the resource omitted
    public function toArray($request)
    {
        return [
              "time_to_live" => $this->whenPivotLoaded("table", function () {
                return $this->pivot->time_to_live;  // This is the line 45
            })
         ];
      }
}

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 17 (3 by maintainers)

Most upvoted comments

UPDATE

Apparently you can easily fix this without any change to this package. Basically if you call getRelationValue("pivot") instead of relying to the magic property Larastan gets happy about it 🤣

@mr-feek @canvural

/**
 * @extends JsonResource<\App\User>
*/
class UserResource extends JsonResource
{
    // Other parts of the resource omitted
    public function toArray($request)
    {
        /** @var \App\User **/
        $user = $this;
        return [
              "time_to_live" => $this->whenPivotLoaded("table", function () use($user) {
                return $user->getRelationValue("pivot")->time_to_live;  // This is the line 45
            })
         ];
      }
}

thank you @ludo237 for the workaround I still tend to think Larastan should handle the magic method as it does with many other Laravel magic methods since it’s probably the very reason Larastan is wrapping PHPstan.

Speaking for myself I get used to avoid magic methods for Eloquent ORM because they produce more headaches that anything else so for instance instead of $model->colum_name I’d rather use $model->getAttributeValue("my_column_name"), same goes for relationships etc.

Magic methods seems to be a problem with almost every static analyser not only Larastan and, in my opinion, the code result is messier with them

The issue still exists. Using the workaround getRelationValue("pivot") proposed by @ludo237 we can bypass this error

Issue still present in Larastan v2.6.4.

Is the accepted solution to use getAttributeValue or getRelationValue then? I’m happy with either solution, but what @F-Yousri said in his last comment is correct.

One of the possible solutions is we can tell in ModelPropertiesExtension that pivot exists in Model. And also add \Illuminate\Database\Eloquent\Relations\Pivot to the universalObjectCrates Because we can’t tell which properties exist on the pivot table.

I’ve ran into this issue and using getAttributeValue seems to work on level: max (@amooij ) if you assign the Pivot to the property in a doc block of the model.

Model:

use Illuminate\Database\Eloquent\Relations\Pivot;

/**
 * @property ?Pivot $results
 */
class Competition extends Model {
    public function contenders(): BelongsToMany
    {
        return $this->belongsToMany(Contender::class)
            ->as('results')
            ->withPivot('pivot_data');
    }
}

And implemented like this:

$competition->results->getAttributeValue('pivot_data')