laravel-mongodb icon indicating copy to clipboard operation
laravel-mongodb copied to clipboard

BelongsToMany relationships not working properly on embedded models

Open foron23 opened this issue 3 years ago • 4 comments

  • Laravel-mongodb Version: 3.8.4
  • PHP Version: 7.4.28
  • Database Driver & Version: 1.12

Description:

My use case conforms the relationship between 3 entities/models:

  • Post: This entity acts as the main container of information:
    • post_type => text(1), photo(2) or video(3)
    • location => (lat,lng)
    • created_at
    • updated_at
  • PostLanguage: This entity is embedded into the Post entity and contains the following attributes:
    • name
    • description
  • Content: This entity represents the multimedia content each post language has:
    • url
    • type

The intention is to embed every Post with as many translations as needed, being these defined by the PostLanguage entity. The Content might be dependant on the language selected, therefore it needs to be related to the PostLanguage.

The Content is uploaded to the backend separately, and later related to the according posts, which means a Content document might be related to many PostLanguage, as well as a PostLanguage might have many Contents related to it. As a consequence, the relationship between both of them is belongsToMany for each of them.

Steps to reproduce

  1. Having defined the following models:

namespace Modules\Project\Entities;

use Jenssegers\Mongodb\Eloquent\Model;

class Post extends Model
{
    protected $connection = 'mongodb';

    protected $collection ='post'; 

    public function languages(){
        return $this->embedsMany("Modules\Project\Entities\PostLanguages");
    }

}
namespace Modules\Project\Entities;

use Jenssegers\Mongodb\Eloquent\Model;

class PostLanguages extends Model
{
    public $timestamps = false;

    protected $connection = 'mongodb';

    protected $collection ='post_languages'; 

    public function contents(){
        return $this->belongsToMany(Content::class, null, 'posts', 'contents');
    }

}
namespace Modules\Project\Entities;

use Jenssegers\Mongodb\Eloquent\Model;

class Content extends Model
{
    public $timestamps = false;

    protected $connection = 'mongodb';

    protected $collection ='content'; 

    public function posts(){
        return $this->belongsToMany(PostLanguages::class, null, 'contents', 'posts');
    }

}
  1. The following code is executed when creating a new post:
$newPost = new Post([
        "post_type" => 1,
        "location "=> [
            "lat"=> 0,
            "lng"=> 0
        ];
    ])

$new_post_langs = new PostLanguages([
    "name"=> "example name",
    "description"=> "example description",
])
$new_post_langs->save();

$content = Content::find($content_id);
$content->posts()->attach($new_post_langs->_id);

$newPost->associate($new_post_langs);
$newPost->save();
  1. Accessing the relations
$content = Content::find("627a68ba1fb961387100c34f")
$posts = $content->posts()

$post = Post::find("627a15b31fb961387100c345")
$languages = $post->languages()

Expected behaviour

When accessing the relationship from PostLanguages, the result acts as expected:

$post = Post::find("627a15b31fb961387100c345");

=> {
    "_id": ObjectId("627a15b31fb961387100c345")
    "post_type ": "1",
    "location ": {
      "lat": 0,
      "lng": 0
    },
    "created_at":ISODate("2016-01-03T21:21:38.032Z"),
    "updated_at":ISODate("2016-01-03T21:21:38.032Z"),
    "languages":[
      {
        "_id" : ObjectId("627a15b31fb961387100c344")
        "name": "example name",
        "description": "example description",
        "contents" : ["625420319af6b94ab40e7087"]
      }
    ]
  }


$languages = $post->languages()
  => array(
    {
        "_id" : ObjectId("627a15b31fb961387100c344")
        "name": "example name",
        "description": "example description",
        "contents" : ["627a68ba1fb961387100c34f"]  
    }
)

foreach($languages as $lang){
    $contents = $lang->contents()
}
=> array(
   {
        "_id" : ObjectId("627a68ba1fb961387100c34f")
        "url ": "https://www.example.com/",
        "type":  1,
        "posts": ["627a15b31fb961387100c344"]
   }
)


Actual behaviour

When accessing the relationship from Content, the result is empty:

$content = Content::find("627a68ba1fb961387100c34f")

=> {
    "_id" : ObjectId("627a68ba1fb961387100c34f")
    "url ": "https://www.example.com/",
    "type": "1",
    "posts": ["627a15b31fb961387100c344"]
  }

$posts = $content->posts()

  => array(
    )

Thanks in advance,

Logs: Insert log.txt here (if necessary)

foron23 avatar May 10 '22 14:05 foron23

Try this library: Laravel mongo auto sync. It handles relationship on embedded models

SanaviaNicolas avatar May 10 '22 14:05 SanaviaNicolas

I tried installing the package, unfortunately, it seems it does not have support for Laravel 8

foron23 avatar May 11 '22 07:05 foron23

My result is empty too

mongobird avatar May 13 '22 14:05 mongobird

Hi guys @foron23 @mongobird, we have just released a new version compatible with L8. Check it out version 2 and let me know.

SanaviaNicolas avatar May 21 '22 13:05 SanaviaNicolas