framework icon indicating copy to clipboard operation
framework copied to clipboard

BelongsTo Relations break when using custom collections

Open SlimGee opened this issue 4 months ago • 1 comments

Laravel Version

11.28.1

PHP Version

8.3.12

Database Driver & Version

MariaDB 11.5.2

Description

When using a custom collection on an eloquent model as suggested in the docs here, if that model is referenced as a belongsTo by other other models, it throws a TypeError because \Illuminate\Database\Eloquent\Relations\BelongsTo::match() expects an instance an Illuminate\Database\Eloquent\Collection instead of a custom collection

My suggestion is to introduce a Collection contract which Illuminate\Support\Collection must implement and that is used as the expected types on all other internal models instead of expecting a specific implementation. I think this would be best since collections are a big part of the Laravel framework.

Steps To Reproduce

Tell eloquent to use a custom collection on a model

class User extends Model
{
    /**
     * Create a new Eloquent Collection instance.
     *
     * @param  array<int, \Illuminate\Database\Eloquent\Model>  $models
     * @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>
     */
    public function newCollection(array $models = []): Collection
    {
        return new UserCollection($models);
    }
}

On another model reference that model as the belongsTo relation

class Profile extends Model
{
  public function user()
  {
   return $this->belongsTo(User::class);
  }
}

Expected behaviour

Just works

Actual Behavior

TypeError: Illuminate\Database\Eloquent\Relations\BelongsTo::match(): Argument #2 ($results) must be of type Illuminate\Database\Eloquent\Collection, Illuminate\Support\LazyCollection given, called in...

SlimGee avatar Oct 19 '24 17:10 SlimGee