mongodb / laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)

Home Page:https://www.mongodb.com/compatibility/mongodb-laravel-integration

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

hasMany or hasOne doesnt work without getIdAttribute

masterbater opened this issue · comments

This issue has been around, can you guys provide a documentation how to properly make sure things work in hasMany and hasOne

for now using this to make sure hasMany and hasOne work

  public function getIdAttribute($value = null)
    {
        return $value;
    }

Hi @masterbater, we have a test suite that cover relationships, including hasMany and hasOne. Could you be more precise about what is the issue: steps to reproduce, expected result and observed result.

Hi @masterbater, we have a test suite that cover relationships, including hasMany and hasOne. Could you be more precise about what is the issue: steps to reproduce, expected result and observed result.

I found the workaround because of this issue #1902 (comment)

I believe the cause of the issue since I am using an existing db that is saved base on mongoose or prisma, foreign keys also get converted into snake_case instead of camelCase.

This are the gist of my collection

rulesauditlogs
{
  "_id": {
    "$oid": "65e74b683d61600fe666d04f"
  },
  "usersId": {
    "$oid": "5be9ce7b3de6dd77db832950"
  },
  "rulesId": {
    "$oid": "65e74addda6dfa40dd5ff39f"
  },
  "createdAt": {
    "$date": "2024-03-05T16:42:16.962Z"
  },
  "updatedAt": {
    "$date": "2024-03-05T16:42:16.962Z"
  },
  "processed": true,
  "isReviewed": true,
  "reviewedAt": {
    "$date": "2024-03-07T10:52:36.027Z"
  },
  "reviewedTimeSpentSeconds": 0
}
rules
{
  "_id": {
    "$oid": "65e74addda6dfa40dd5ff39f"
  },

  "ruleType": "Adherence",
}

@masterbater They're the same as the Eloquent's hasMany or hasOne. You can pass your custom keys as parameters.

For hasOne:

public function hasOne($related, $foreignKey = null, $localKey = null)

For hasMany:

public function hasMany($related, $foreignKey = null, $localKey = null)

The issue that you referred to, is solved by now and no longer exists. I think you are using an older version of this package. Please specify the version you are using.

@masterbater They're the same as the Eloquent's hasMany or hasOne. You can pass your custom keys as parameters.

For hasOne:

public function hasOne($related, $foreignKey = null, $localKey = null)

For hasMany:

public function hasMany($related, $foreignKey = null, $localKey = null)

The issue that you referred to, is solved by now and no longer exists. I think you are using an older version of this package. Please specify the version you are using.

version 4.1.3, I did it work but needs to add getIdAttribute to each models. I pass in custom keys since it convert camelCase keys into snake_keys

 "name": "laravel/laravel",
    "type": "project",
    "description": "The skeleton application for the Laravel framework.",
    "keywords": [
        "laravel",
        "framework"
    ],
    "license": "MIT",
    "require": {
        "php": "^8.1",
        "guzzlehttp/guzzle": "^7.2",
        "laravel/framework": "^10.10",
        "laravel/octane": "^2.3",
        "laravel/sanctum": "^3.3",
        "laravel/tinker": "^2.8",
        "mongodb/laravel-mongodb": "^4.1",
        "mongodb/mongodb": "^1.17"
    },

Could you please share your models and their relationships?

Could you please share your models and their relationships?

Ill try to provide a fresh laravel project and mongodump file later. I will close this if I cant replicate it thanks for replying appreciate it

No sweat buddy❤️

Hi @masterbater, we have a test suite that cover relationships, including hasMany and hasOne. Could you be more precise about what is the issue: steps to reproduce, expected result and observed result.

I think you dont have a test for this. For data consistency we always save the real objectid not a string representation on the collection.

This Fails hasMany

   $user = new User;
    $user->name = 'Test';
    $user->email = 'test@gmail';
    $user->save();
    $readings = new Reading;
    $readings->patientId = new ObjectId($user->id);
    $readings->value = 120;
    $readings->unit = 'mmHg';
    $readings->save();
    return $user->readings;

This make the relationship hasMany work

   $user = new User;
    $user->name = 'Test';
    $user->email = 'test@gmail';
    $user->save();
    $readings = new Reading;
    $readings->patientId = $user->id;
    $readings->value = 120;
    $readings->unit = 'mmHg';
    $readings->save();
    return $user->readings;

User.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use MongoDB\Laravel\Eloquent\Model;

class User extends Model
{
    use HasFactory, Notifiable;
    protected $connection = 'mongodb';
    protected $collection = 'users';
    const CREATED_AT = 'createdAt';
    const UPDATED_AT = 'updatedAt';
    public static $snakeAttributes = false;

    public function readings()
    {
        return $this->hasMany(Reading::class, 'patientId');
    }
}

Hopefully it could be fix, this I think should be important especially for some people having different codebases.

I don't understand why there is a default attribute mutator on the id key. 👨‍💻

Sorry for the delay. I will work on this whenever I find some free time.

commented

Hi @masterbater, we have a test suite that cover relationships, including hasMany and hasOne. Could you be more precise about what is the issue: steps to reproduce, expected result and observed result.

I think you dont have a test for this. For data consistency we always save the real objectid not a string representation on the collection.

This Fails hasMany

   $user = new User;
    $user->name = 'Test';
    $user->email = 'test@gmail';
    $user->save();
    $readings = new Reading;
    $readings->patientId = new ObjectId($user->id);
    $readings->value = 120;
    $readings->unit = 'mmHg';
    $readings->save();
    return $user->readings;

This make the relationship hasMany work

   $user = new User;
    $user->name = 'Test';
    $user->email = 'test@gmail';
    $user->save();
    $readings = new Reading;
    $readings->patientId = $user->id;
    $readings->value = 120;
    $readings->unit = 'mmHg';
    $readings->save();
    return $user->readings;

User.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use MongoDB\Laravel\Eloquent\Model;

class User extends Model
{
    use HasFactory, Notifiable;
    protected $connection = 'mongodb';
    protected $collection = 'users';
    const CREATED_AT = 'createdAt';
    const UPDATED_AT = 'updatedAt';
    public static $snakeAttributes = false;

    public function readings()
    {
        return $this->hasMany(Reading::class, 'patientId');
    }
}

Hopefully it could be fix, this I think should be important especially for some people having different codebases.

@GromNaN Sorry for pinging you directly is there any chance you can support relationship that is natively an objectid? Was this already been resolved?

I agree that using ObjectIds is a good practice for foreign keys.
I tried to implement it, but found issues with how the parent Eloquent classes work with foreign keys. They assume every primary/foreign key can be represented as a string. This need in-deep investigation to find how we can implement it in a way that we can maintain in a long-term, without breaking existing application that rely on string foreign keys.