2

I'm trying to iterate over every element of an array recursively to get the values where the key is equal to page_id or content_id.

The problem is that in callback function, in a switch statement I get completely weird behaviour, where case is matched but value is different.

This was driving me nuts for quite some time. I even tried to use strict comparison like if($key === 'component_id') print $key; die();. I'm expecting to get 'component_id' as the output but get '0'. How is that possible?

While writing this question, I also noticed this happens when there is indexed array at some point, but I'm not sure if that is the problem.

Here is an example code from full solution.

Thanks.

<?php class Arr { public static function map($array, $callback, $recursive = false) { foreach ($array as $key => $value) { $array[$key] = $callback($key, $value); if($recursive && is_array($array[$key])) { $array[$key] = static::map($array[$key], $callback, true); } } return $array; } } $data = [ 'id' => 12, 'data' => [ 'terms' => [ [ 'href' => null, 'icon' => 'lock', 'target' => '_blank' ], [ 'href' => 'http://example.com', 'icon' => 'lock', 'target' => '_blank' ] ], 'license_info' => [ 'content_id' => 6 ] ] ]; $contents = []; $pages = []; Arr::map($data, function ($key, $value) use (&$contents, &$pages) { switch ($key) { case 'content_id': print $key; die(); // 0 ????? $contents[] = $value; break; case 'page_id': $pages[] = $value; break; } return $value; }, true); 

I expected the output to be component_id, but I got 0.

Also I know I could use array_walk or array_walk_recursive, but I prefer this approach as it's more elegant and readable in my opinion.

1 Answer 1

1

Your code looks ok. The problem is that 0 == 'content_id' is True. And switch in PHP is using loose (==) comparison. And because in terms you have two values without string keys, they are automatically indexed starting at 0. So what you get is not when your function finds

'content_id' => 6 

but when it finds

/* 0 => */ [ 'href' => null, 'icon' => 'lock', 'target' => '_blank' ], 

EDIT: Bottom line is - you have to use if with strict comparison === in this case (or use string keys everywhere).

Sign up to request clarification or add additional context in comments.

2 Comments

@rms Thank you ;), I could not imagine if 0 == 'content_id' was True. Plus when using strict comparison I left the switch statement intact, so that's why I thought something was wrong.
@GiorgiBotsvadze I know, it's crazy :) To make it even better 1 == 'content_id' is False :DD

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.