laravel-mongodb: EmbedsOne doesn't allow eager Loading

I have two models, one embed in the other likes this:

class Media extends Moloquent {

    public function user()
    {
        return $this->belongsTo('User');
    }

    public function comments()
    {
        return $this->embedsMany('Comment');
    }

    public function video()
    {
        return $this->embedsOne('Video');
    }

}
class Video extends Moloquent {

    ...

}

And I want to get a Media with the Video embedded with some getters mutators.

$media = Media::with(['comments', 'user', 'video'])->find($id);

The load of comments and user is working great, but when I add the video loading it crashes showing the next error:

[2015-01-20 09:50:42] alpha.ERROR: exception 'ErrorException' with message 'Argument 2 passed to Jenssegers\Mongodb\Relations\EmbedsOneOrMany::match() must be an instance of Illuminate\Database\Eloquent\Collection, null given, called in /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php on line 478 and defined' in /home/vagrant/sites/media/vendor/jenssegers/mongodb/src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php:112
Stack trace:
#0 /home/vagrant/sites/media/vendor/jenssegers/mongodb/src/Jenssegers/Mongodb/Relations/EmbedsOneOrMany.php(112): Illuminate\Exception\Handler->handleError(4096, 'Argument 2 pass...', '/home/vagrant/s...', 112, Array)
#1 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(478): Jenssegers\Mongodb\Relations\EmbedsOneOrMany->match(Array, NULL, 'video')
#2 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(445): Illuminate\Database\Eloquent\Builder->loadRelation(Array, 'video', Object(Closure))
#3 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(158): Illuminate\Database\Eloquent\Builder->eagerLoadRelations(Array)
#4 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(125): Illuminate\Database\Eloquent\Builder->get(Array)
#5 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(82): Illuminate\Database\Eloquent\Builder->first(Array)
#6 /home/vagrant/sites/media/app/controllers/Api2Controller.php(41): Illuminate\Database\Eloquent\Builder->find('54bcf9dc0390693...')
#7 [internal function]: Api2Controller->getMedia('54bcf9dc0390693...')
#8 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(231): call_user_func_array(Array, Array)
#9 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(93): Illuminate\Routing\Controller->callAction('getMedia', Array)
#10 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(62): Illuminate\Routing\ControllerDispatcher->call(Object(Api2Controller), Object(Illuminate\Routing\Route), 'getMedia')
#11 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/Router.php(962): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request), 'Api2Controller', 'getMedia')
#12 [internal function]: Illuminate\Routing\Router->Illuminate\Routing\{closure}('54bcf9dc0390693...')
#13 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/Route.php(109): call_user_func_array(Object(Closure), Array)
#14 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/Router.php(1028): Illuminate\Routing\Route->run(Object(Illuminate\Http\Request))
#15 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Routing/Router.php(996): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#16 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(775): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
#17 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(745): Illuminate\Foundation\Application->dispatch(Object(Illuminate\Http\Request))
#18 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Session/Middleware.php(72): Illuminate\Foundation\Application->handle(Object(Illuminate\Http\Request), 1, true)
#19 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Cookie/Queue.php(47): Illuminate\Session\Middleware->handle(Object(Illuminate\Http\Request), 1, true)
#20 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Cookie/Guard.php(51): Illuminate\Cookie\Queue->handle(Object(Illuminate\Http\Request), 1, true)
#21 /home/vagrant/sites/media/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Illuminate\Cookie\Guard->handle(Object(Illuminate\Http\Request), 1, true)
#22 /home/vagrant/sites/media/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(641): Stack\StackedHttpKernel->handle(Object(Illuminate\Http\Request))
#23 /home/vagrant/sites/media/public/index.php(73): Illuminate\Foundation\Application->run()
#24 {main} [] []

I guess that the eager loading is only allowing Collections and no individual Models?

Thanks for any help!

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 15 (2 by maintainers)

Most upvoted comments

Is there an accepted fix for this? I understand that the embedsOne relationship is directly included on the original object, but I’ve found that in the latest Lumen that without eager loading the relationship on the model, you end up with missing keys…e.g.

{
"_id": "574cfeb79a89200be60018b3",
"updated_at": "2016-05-31 03:02:15",
"created_at": "2016-05-31 03:02:15",
"embededDocument": {
    "updated_at": {},
    "created_at": {},
    "_id": {}
},

@jenssegers is this intended functionality?

for embedOne problem i think i solved it already so ill share my fix in the file \Jenssegers\Mongodb\Relation\EmbedOne.php add the function i write below to the file EmbedOne.php then you will be able to use eagerLoading

class EmbedsOne extends EmbedsOneOrMany {

    /**
     * Shorthand to get the results of the relationship.
     *
     * @return Jenssegers\Mongodb\Eloquent\Collection
     */
    public function get()
    {
        return new Collection($this->getResults());
    }
    /**
     * Get the embedded records array.
     * dn additional because null will failed on match function
     * @return array
     */
    protected function getEmbedded()
    {
        return parent::getEmbedded() ?: [];
    }
}

but to be able use silent save feature please see issue #488 i explain how to fix it too

@Alexandre, thanks, and yes, I know your suggestions.

I’m wondering why embedded references to other collections is not default supported. Now, I’m obliged to save emails in difference (sub)collections. The second option is using linking tables. The third option is to create a custom relationship.

I consider to downshift MySQL.

2015-03-09 18:40 GMT+01:00 Alexandre Butynski notifications@github.com:

@Henri85 https://github.com/Henri85 look how the many to many relationship work : https://github.com/jenssegers/laravel-mongodb#relations. Try it.

Also, you can build a kind of custom relationship by defining a custom schema and custom getters and setters like this ones :

class User { public function getEmailsAttribute(); public function attachEmail($email, $pivot = array()); public function removeEmail($emailId);}

— Reply to this email directly or view it on GitHub https://github.com/jenssegers/laravel-mongodb/issues/397#issuecomment-77903719 .