larastan: Errors on HasMany relationship methods

  • Larastan Version: 0.7.5+
  • --level used: 6

Description

Hi, I get errors on some method calls for HasMany relationships, from version 0.7.5 onwards:

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------
  Line   Apis/Main/V1/GlobalActivities/Policies/Delete.php
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------
  32     Call to private method count() of parent class Illuminate\Database\Eloquent\Relations\HasOneOrMany<TRelatedModel of Illuminate\Database\Eloquent\Model>.
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------

Laravel code where the issue was found

Here is the definition of the timeEntries method, defined on the GlobalActivity model, on which count() is called:

    /**
     * The model's time entries.
     *
     * @return HasMany<TimeEntry>
     */
    public function timeEntries(): HasMany
    {
        return $this->hasMany(TimeEntry::class, 'activity_id', 'id');
    }

As you can see I specified the model in the docblock, like mentioned here, for instance.

And here is the actual call of the count() method, causing the error:

<?php

namespace App\Apis\Main\V1\GlobalActivities\Policies;

use App\Apis\Policy;
use App\Models\Contractor\Activity\GlobalActivity;
use App\Models\User\User;

class Delete extends Policy
{
    /**
     * {@inheritdoc}
     *
     * @param  User           $user
     * @param  GlobalActivity $activity
     * @return void
     */
    public function __construct(
        protected User $user,
        protected GlobalActivity $activity,
    ) {
    }

    /**
     * {@inheritdoc}
     *
     * @return bool
     */
    public function granted(): bool
    {
        if ($this->activity->timeEntries()->count()) {
            return false;
        }

        // ... other irrelevant code ...
    }
}

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 24

Most upvoted comments

I can’t reproduce this.

Please try to prepare a small repository that can reproduce this. Or a failing test case in a PR.

Thank you.

@szepeviktor just did that and not only the errors are still there, I’ve got a slew of new errors too 😅

Might not be a good lead to follow.

@szepeviktor err yeah, I know. Old habits die hard 😅

@canvural here’s the dump with the @return statement:

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------
  Line   Apis/Main/V1/GlobalActivities/Policies/Delete.php
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------
  31     Dumped type: Illuminate\Database\Eloquent\Relations\HasMany<App\Models\Contractor\Activity\TimeEntry>
  33     Call to private method count() of parent class Illuminate\Database\Eloquent\Relations\HasOneOrMany<TRelatedModel of Illuminate\Database\Eloquent\Model>.
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------

And after removing the statement:

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------
  Line   Apis/Main/V1/GlobalActivities/Policies/Delete.php
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------
  31     Dumped type: Illuminate\Database\Eloquent\Relations\HasMany<App\Models\Contractor\Activity\TimeEntry>
  33     Call to private method count() of parent class Illuminate\Database\Eloquent\Relations\HasOneOrMany<TRelatedModel of Illuminate\Database\Eloquent\Model>.
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------

They’re the same.

@szepeviktor I don’t use it in the context of PHPStan specifically, if that’s your point?

Ah ok. I see.

Can you try and write the output of \PHPStan\dumpType($this->activity->timeEntries()); And try once again with @return HasMany<TimeEntry> removed from the PHPDocs.