larastan / larastan

⚗️ Adds code analysis to Laravel improving developer productivity and code quality.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Call to an undefined method Database\Factories\<MyModel>::trashed()

darfijt opened this issue · comments

  • Larastan Version: 2.6.4
  • --level used: 6

Description

I got warning about using the trashed state method, that is defined in Illuminate\Database\Eloquent\Factories\Factory

Laravel code where the issue was found

$user = \App\Models\User::factory()->trashed()->create();

I even tried to annotate the method in my UserFactory but this does not solve the issue. The only way I figurate out to solve the issue (without ignoring the line) is to define a custom state that calls parent trashed, but of course is not that cool

@darfijt, this works for me and the base factory class has the proper annotation:

https://github.com/laravel/framework/blob/e574ffa03436a85d0aefccca9d8127746b3032aa/src/Illuminate/Database/Eloquent/Factories/Factory.php#L21-L26

Your user factory might need the proper generics:

/** @extends Factory<User> */
class UserFactory extends Factory

Still not working.
UserFactory
image
Terminal
image

laravel: v10.33.0
laratan: 2.6.4

@ednar28, can you provide a minimum reproducible example? I am not seeing this error:

https://phpstan.org/r/6146e0f3-0358-4188-92d5-267754a55a78

That's not an MRE...and the phpstan link I posted above is running on level 9

example my code:

/** DummyUserSeeder */
namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class DummyUserSeeder extends Seeder {
  /**
   * Run the database seeds.
   */
  public function run(): void
  {
      User::factory()
        ->count(10)
        ->trashed()
        ->create();
  }
}
/** UserFactory */
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
 */
class UserFactory extends Factory
{
  protected static ?string $password;

  /**
   * Define the model's default state.
   *
   * @return array<string, mixed>
   */
  public function definition(): array
  {
      return [
          'name' => fake()->name(),
          'username' => fake()->unique()->userName(),
          'email' => fake()->unique()->safeEmail(),
          'email_verified_at' => now(),
          'password' => static::$password ??= Hash::make('password'),
          'remember_token' => Str::random(10),
      ];
  }
}

Thanks, and the user model?

I thought it was a problem of my User model (since it extends another class) but I did the same on another model (that extends the lavarel base model) Factory and still the same issue.

So the following passes on Larastan 2.4.6 level 9:

<?php

namespace Tests\Larastan;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Seeder;

class User extends Model
{
    use HasFactory;
    use SoftDeletes;

    protected $guarded = [];

    protected $hidden = ['password'];

    protected $table = 'users';

    protected static function newFactory(): UserFactory
    {
        return UserFactory::new();
    }
}

/** @extends Factory<User> */
class UserFactory extends Factory
{
    protected $model = User::class;

    /** @return array<string, mixed> */
    public function definition(): array
    {
        return [
            'name'     => fake()->name(),
            'email'    => fake()->email(),
            'password' => 'password', // set unencrypted
        ];
    }
}

class UserSeeder extends Seeder
{
    public function run(): void
    {
        User::factory()
            ->count(10)
            ->trashed()
            ->create();
    }
}

I have the same issue as darfijt, but only in the context of my Pest tests. PHPStan picks up on the ->trashed() method just fine in other contexts like seeders, etc.

I don't have time to make a full reproduction, but I can say that I'm on larastan 2.7.0, and more or less have the same key elements as your passing code, namely:

    use HasFactory;
    use SoftDeletes;

in the model and

/** @extends Factory<MyModel> */

in the factory.

I originally didn't have a definition for protected static function newFactory set at first, but even when I added it, it didn't change the outcome inside Pest tests.