Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

wonder95's avatar

Laravel 12 PHPStan error "Call to undefined method withTrashed()"

I'm working on upgrading a hige codebase to Laravel 12 from Laravel 11, and the corresponding updates of Larastan to v3 and PHPStan, and I'm getting a huge number of this error:

Call to an undefined method                                                                   
         Illuminate\Database\Eloquent\Relations\BelongsTo::withTrashed().  

on this relationship defined in a trait

use Illuminate\Database\Eloquent\Relations\BelongsTo;

public function pipeline(): BelongsTo
{
    return $this->belongsTo(PipelineModel::class, Constants::PIPELINE_REL_DB_FIELD)->withTrashed();
}

in this case, PipelineModel uses the MongoDB\Laravel\Eloquent\SoftDeletes trait (which in turn, uses the base Illuminate\Database\Eloquent\SoftDeletes trait).

As best I understand it, static analysis can't see that because it's dynamically added at runtime. I've tried a few different stub versions, such as

<?php
namespace Illuminate\Database\Eloquent\Relations;

/**
 * Base class for all Eloquent relations.
 *
 * The SoftDeletes service provider adds the dynamic **withTrashed()**
 * macro at runtime, so we advertise it here for static analysis.
 *
 * @template TRelatedModel of \Illuminate\Database\Eloquent\Model
 *
 * @method $this withTrashed(bool $withTrashed = true)
 */
abstract class Relation {}

and

<?php
namespace Illuminate\Database\Eloquent\Relations;

if (false) {
    /**
     * Declares the dynamic `withTrashed()` macro.
     *
     * @method $this withTrashed()
     */
    interface _WithTrashedRelation {}

    // The real classes “implement” the dummy interface –-
    // PHPStan merges the @method into the originals, but at
    // run-time these declarations are ignored because we are
    // inside `if (false) { … }`.

    class BelongsTo implements _WithTrashedRelation {}
    class HasOne   implements _WithTrashedRelation {}
    class HasMany  implements _WithTrashedRelation {}
    class MorphMany implements _WithTrashedRelation {}
}

with no luck. Short of just doing a bunch of ignore lines, how can I fix this error?

0 likes
2 replies
LaryAI's avatar

You're correct that this is a static analysis limitation: PHPStan (and Larastan) can't "see" dynamically added methods like withTrashed() on Eloquent relationships, because they're added at runtime via macros.

The cleanest solution is to use PHPStan's extension mechanism to teach it about these dynamic methods. Larastan already provides some support for Eloquent magic, but for custom macros or traits (like MongoDB's SoftDeletes), you may need to help it further.

Solution 1: Use Larastan's Helper Docblocks

Larastan reads PHPDoc @method annotations. For your case, you can add a docblock to your trait or model to inform PHPStan about withTrashed():

/**
 * @method static \Illuminate\Database\Eloquent\Builder|static withTrashed(bool $withTrashed = true)
 */
class PipelineModel extends Model
{
    use \MongoDB\Laravel\Eloquent\SoftDeletes;
    // ...
}

Or, if you want to annotate the relationship method:

/**
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo|\Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\PipelineModel>
 * @method \Illuminate\Database\Eloquent\Relations\BelongsTo withTrashed(bool $withTrashed = true)
 */
public function pipeline(): BelongsTo
{
    return $this->belongsTo(PipelineModel::class, Constants::PIPELINE_REL_DB_FIELD)->withTrashed();
}

But this can get verbose and repetitive.


Solution 2: Use PHPStan's phpstan.neon to Ignore the Error

If the above doesn't work or is too cumbersome, you can tell PHPStan to ignore this specific error pattern:

# phpstan.neon or phpstan.neon.dist
parameters:
    ignoreErrors:
        - '#Call to an undefined method Illuminate\\Database\\Eloquent\\Relations\\BelongsTo::withTrashed#'

This is pragmatic and safe, since you know the method exists at runtime.


Solution 3: Write a PHPStan Extension (Advanced)

If you want a robust, project-wide fix, you can write a PHPStan dynamic return type extension for Eloquent relationships, but this is more involved and usually overkill unless you have many such macros.


Summary

  • Recommended: Use @method PHPDoc on your models or relationships to inform static analysis.
  • Pragmatic: Use ignoreErrors in your phpstan.neon for this specific error.
  • Advanced: Write a PHPStan extension if you need full static analysis support for macros.

For most teams, the ignoreErrors approach is the most maintainable and least intrusive.

Let me know if you want a sample PHPStan extension for this!

RazIacob's avatar

I had to add a similar error to the ignoreErrors list. I don't like it though.

1 like

Please or to participate in this conversation.