Skip to content

How do you work with complex documents returned as arrays? #78

@crazycodr

Description

@crazycodr

I'm trying out your library with a simple model that contains arrays of values such as:

public function __construct()
{
    $this['night'] = null;
    $this['received'] = array(
        'date' => date('Y-m-d G:i'),
        'by' => null
    );
    $this['client'] = array(
        'name' => null,
        'givenname' => null
    );
}

Which works fine in itself, if i can place values in the object, i'm able to save them correctly to Mongodb and it looks something like the following and it's perfect.

{
    "_id" : ObjectId("529f905b45f3b0203f90b053"),
    "night" : "529f8a6645f3b0293f979d28",
    "received" : {
        "date" : "2013-12-04 21:22",
        "by" : "Mathieu Dumoulin"
    },
    "client" : {
        "name" : "Champoux",
        "givenname" : "Valérie"
    }
}

But the problem is, when i comes back, i have arrays instead of objects. This forces me to redraw the code to use arrays instead of objects and the resulting issue is i keep getting "Indirect modification of overloaded element of Transport has no effect" exceptions because i'm trying to change a value of a returned array with is not a reference type, so the assign just ends up in the void and doesn't change anything.

Used to be and worked fine in the beginning:

$transport = new Transport();
$transport->received->date = Input::get('received_date');
$transport->received->by = Input::get('received_by');
$transport->client->name = Input::get('client_name');
$transport->client->givenname = Input::get('client_givenname');

Currently needs to be because mongo returns arrays in eloquent model:

$transport = new Transport();
$transport['received']['date'] = Input::get('received_date');
$transport['received']['by'] = Input::get('received_by');
$transport['client']['name'] = Input::get('client_name');
$transport['client']['givenname'] = Input::get('client_givenname');

Needs to be if i want to not get the exception:

$transport = new Transport();
$transport['received'] = array(
    'date' => Input::get('received_date'),
    'by' => Input::get('received_by'),
);
$transport['client'] = array(
    'name' => Input::get('client_name'),
    'givenname' => Input::get('client_givenname'),
);

I hope you agree that this last code i pasted smells a lot, it's ugly, hard to manage and hard to upgrade in the future. I'm used to doing my own repository classes and hydrators, but i want to take advantage of Eloquent in this project even though i'm using MongoDB.

So my question is, what is your approach to this problem?

Activity

jenssegers

jenssegers commented on Dec 4, 2013

@jenssegers
Contributor

This is a known issue with PHP's mongo driver. I can't really do anything about it without a big impact on the performance. This was also mentioned in #65.

But this should be possible:

$transport = new Transport();
$transport->received = array(
    'date' => Input::get('received_date'),
    'by' => Input::get('received_by'),
);
$transport->client = array(
    'name' => Input::get('client_name'),
    'givenname' => Input::get('client_givenname'),
);
crazycodr

crazycodr commented on Dec 4, 2013

@crazycodr
Author

I'll see if it could be simple to actually scan the arrays and transform them in objects but put an option in the driver to achieve so. Would you agree on accepting a PR if i found how to do it?

jenssegers

jenssegers commented on Dec 4, 2013

@jenssegers
Contributor

I have been thinking about the same thing, but I fear it would be bad for performance on big collections because you would have to recursively scan each document.

crazycodr

crazycodr commented on Dec 4, 2013

@crazycodr
Author

As long as it's toggleable as an option, i don't see an issue, else i'll just have to move away from the laravel querybuilder and make my own data access layer. Not that hard, but just annoying to have to do so!

jenssegers

jenssegers commented on Dec 4, 2013

@jenssegers
Contributor

You map always send me possible solutions, preferably with benchmark results :)

m-nel

m-nel commented on Feb 20, 2014

@m-nel

Disclaimer: just started looking into MongoDB, have not used either Laravel-MongoDB or Mongolid.

That said, have you had a look at https://github.com/Zizaco/mongolid-laravel ?
Specifically, the relationships:
Docs - https://github.com/Zizaco/mongolid-laravel#relationships
Code - https://github.com/Zizaco/mongolid/blob/master/src/Zizaco/Mongolid/Model.php#L580

jenssegers

jenssegers commented on Mar 1, 2014

@jenssegers
Contributor
ifeltsweet

ifeltsweet commented on Nov 4, 2014

@ifeltsweet

Would really like to have this implemented as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @jenssegers@m-nel@ifeltsweet@crazycodr

        Issue actions

          How do you work with complex documents returned as arrays? · Issue #78 · mongodb/laravel-mongodb