"PHP Error: Call to a member function getKey() on string" from diff() method on Laravel Collection
Asked Answered
B

1

7

Here are the dumped collections:

//$collOne
Illuminate\Database\Eloquent\Collection {#3386
  #items: array:6 [
    4807 => "{"color_id":7,"size_id":4,"pack_id":null}"
    4808 => "{"color_id":7,"size_id":2,"pack_id":null}"
    4809 => "{"color_id":7,"size_id":6,"pack_id":null}"
    4840 => "{"color_id":44,"size_id":4,"pack_id":null}"
    4841 => "{"color_id":44,"size_id":6,"pack_id":null}"
    4842 => "{"color_id":44,"size_id":2,"pack_id":null}"
  ]
}
//$collTwo
Illuminate\Database\Eloquent\Collection {#3403
  #items: array:5 [
    430 => "{"color_id":7,"size_id":4,"pack_id":null}"
    431 => "{"color_id":7,"size_id":2,"pack_id":null}"
    433 => "{"color_id":44,"size_id":4,"pack_id":null}"
    434 => "{"color_id":44,"size_id":6,"pack_id":null}"
    435 => "{"color_id":44,"size_id":2,"pack_id":null}"
  ]
}

Here is the error:

{
    "message": "Call to a member function getKey() on string",
    "exception": "Symfony\\Component\\Debug\\Exception\\FatalThrowableError",
    "file": "[obfuscated]/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php",
    "line": 281,
    "trace": [
        {
            "file": "[obfuscated].php",
            "line": 174,
            "function": "diff",
            "class": "Illuminate\\Database\\Eloquent\\Collection",
            "type": "->"
        },

Here is the line 174 referenced in the above error:

$diff = $collOne->diff($collTwo);

The docs seem pretty straight forward:

The diff method compares the collection against another collection or a plain PHP array based on its values. This method will return the values in the original collection that are not present in the given collection:

Am I missing something obvious here?

Blunk answered 18/10, 2018 at 18:52 Comment(9)
Can you paste the entire stacktrace? Also, it would be interesting to understand how you got to the Eloquent collections - through a query or manually created?Marked
The collections were formed with a mapWithKeys call on eloquent collections where I returned only specific properties and json encoded them in order to make comparisons on the two collections.Blunk
oh dang, lol. It's the wheelmaker! small world eh?Marked
haha, refresh my memory... did I get into a late night argument with you on something? I've been working on a project non-stop, 10+ hours a day for too many months to count now.Blunk
Yea lol, techies I tell ya. Argue about everything from frameworks to approach to the "best" code :DMarked
hahahahah, I remember now, the superfluous comment guy, may we should finish parsing that out first? ; )Blunk
If you could post your stack trace, I'll try and help here :)Marked
Much appreciated, updated with what I can of the stacktrace, btw, turning the collections into arrays and using array_diff works perfectly fine.Blunk
Illuminate\Database\Eloquent\Collection must be a collection of Eloquent models. I suspect this isn't. Can you post the output of dump($collOne->first()) and dump($collTwo->first())Marked
M
13

I suspect when you called mapWithKeys you did not return a Model instance. That's what's causing the error. Illuminate\Database\Eloquent\Collection must be a collection of Eloquent models but in this case it isn't.

A workaround could be calling diff in the base collection rather than the Eloquent collection like so:

$diff = $collOne->toBase()->diff($collTwo->toBase());

Or alternatively, when you call mapWithKeys, call it on the base collection like so:

$eloqCollection->toBase()->mapWithKeys(function($...) {...}) for both the collections. Then you can use the same code: $diff = $collOne->diff($collTwo); to compute the diff because now both $collOne and $collTwo would be instances of Illuminate\Support\Collection

Marked answered 18/10, 2018 at 20:1 Comment(1)
nice catch @MarkedBlunk

© 2022 - 2024 — McMap. All rights reserved.