PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, December 31, 2021

[FIXED] Get a collection item by it's key

 December 31, 2021     cakephp, cakephp-3.0     No comments   

Issue

I have a Cake\Collection\Collection:

object(Cake\Collection\Collection) {

    'count' => (int) 5

}

When I debug its toArray() output, I can see it contains an item with a specific key (say, 123). So what if I want to get the item by that key directly, without converting the collection to an array?

  • I looked through /3.7/class-Cake.Collection.Collection.html and couldn't find anything that looks like a plain getter.
  • $collection[1234] (of course) throws Fatal error: Cannot use object of type Cake\Collection\Collection as array
  • $collection->get(123) throws Fatal error: Call to undefined method ArrayIterator::get()

So I then searched for CakePHP ArrayIterator, found the built-in PHP ArrayIterator class; it has ArrayIterator::offsetGet( mixed $index ), which actually works as $collection->offsetGet(123).

However, the above collection doc page has no mention of ArrayIterator, so this feels like undocumented CakePHP usage. Am I doing it right? Otherwise, how do I get a collection item by its key?


Solution

Given how collections work you can't just access a key as you would in an array, the collection with all its filters, aggregators and stuff has to be evaluated first, and then a key can be looked up.

I don't know why exactly there is no shorthand method for fetching an item via its key, maybe because every collection is different, and the interface shouldn't be cluttered too much, but there's methods to filter the collection by key:

$value = $collection
    ->filter(function ($value, $key) {
        return $key === 123;
    })
    ->first();

That would return the first item in the collection with the key 123.

Using offsetGet() (or any other inner iterator methods for that matter) is discouraged, as it will not evaluate the collection! Say for example there's a filter on your collection that reduces it so that there is no 123 key anymore, using offsetGet() it would still return a value:

$collection = collection([123 => 'foo', 'abc' => 'baz']);

$filtered = $collection
    ->filter(function ($value, $key) {
        return $key === 'abc';
    });

$value = $filtered->offsetGet(123);
debug($value);

$values = $filtered->toArray();
debug($values);

One would expect $value to be null, given that the collection has a filter that only includes keys named abc, but offsetGet(123) would operate on the unfiltered data and still return the value of the 123 key.

########## DEBUG ##########
'foo'
###########################

########## DEBUG ##########
[
    'abc' => 'baz'
]
###########################


Answered By - ndm
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing