mongodb / laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)
https://www.mongodb.com/docs/drivers/php/laravel-mongodb/
MIT License
7k stars 1.43k forks source link

[BUG] hasMany and hasOne relation not working with ObjectId #2788

Open florianJacques opened 7 months ago

florianJacques commented 7 months ago

Hello The _id autocast is a problem on HasOne and HasMany relations, as it prevents comparisons with ObjectId

public function getIdAttribute($value = null)
{
    // If we don't have a value for 'id', we will use the MongoDB '_id' value.
    // This allows us to work with models in a more sql-like way.
    if (! $value && array_key_exists('_id', $this->attributes)) {
        $value = $this->attributes['_id'];
    }

    // Convert ObjectID to string.
    if ($value instanceof ObjectID) {
        return (string) $value;
    }

    if ($value instanceof Binary) {
        return (string) $value->getData();
    }

    return $value;
}

Indeed, this relationship always returns me null

public function accessToken(): HasOne
{
    return $this->hasOne(AccessToken::class, 'userId', '_id');
}

But if I remove the line

// Convert ObjectID to string.
if ($value instanceof ObjectID) {
    return (string) $value;
}

The relation working

florianJacques commented 7 months ago

I propose this solution to get around the problem without breaking the existing system. What do you think?

protected bool $castKey = true;

public function getIdAttribute($value = null): mixed
{
    return $this->castKey ? parent::getIdAttribute($value) : $value;
}

public function accessTokens(): HasMany
  {
      $this->castKey = false;
      $hasMany =  $this->hasMany(AccessToken::class, 'userId', '_id');
      $this->castKey = true;

      return $hasMany;
  }

Unfortunately does not work with method....

I don't know why you put a default attribute mutator on the id, I wonder if it shouldn't be removed.

masterbater commented 6 months ago

https://github.com/mongodb/laravel-mongodb/issues/2753#issuecomment-2016523397

I have a simple replication for this issue