Blog

[PHP] Recursive Key Search

Posted on

After unsuccessfully searching for a way to locate a key in a multidimensional array, I decided to write a function that will do this and return the path, element or value associated with the key.

    /**
    * Recursively searches a multidimensional array for a key and optional value and returns the path as a string representation or subset of the array or a value.
    *
    * @author  Akin Williams <aowilliams@arstropica.com>
    *
    * @param   int|string $needle Key
    * @param   array $haystack Array to be searched
    * @param   bool $strict Optional, limit to keys of the same type. Default false.
    * @param   string $output Optional, output key path as a string representation or array subset, ('array'|'string'|'value'). Default array.
    * @param   bool $count Optional, append number of matching elements to result. Default false.
    * @param   int|string $value Optional, limit results to keys matching this value. Default null.
    * @return  array Array containing matching keys and number of matches
    **/
    function multi_array_key_search($needle, $haystack, $strict=false, $output='array', $count=false, $value=null) {
        // Sanity Check
        if(!is_array($haystack))
            return false;

        $resIdx='matchedIdx';
        $prevKey = "";
        $keys = array();
        $num_matches = 0;

        $numargs = func_num_args();
        if ($numargs > 6){
            $arg_list = func_get_args();
            $keys = $arg_list[6];
            $prevKey = $arg_list[7];
        }

        $keys[$resIdx] = isset($keys[$resIdx]) ? $keys[$resIdx] : 0;

        foreach($haystack as $key => $val) {
            if(is_array($val)) {
                if ((($key === $needle) && is_null($value)) || (($key === $needle) && ($val[$key] == $value) && $strict === false) || (($key === $needle) && ($val[$key] === $value) && $strict === true)){
                    if ($output == 'value'){
                        $keys[$keys[$resIdx]] = $val;
                    } else {
                        $keys[$keys[$resIdx]] = $prevKey . (isset($keys[$keys[$resIdx]]) ? $keys[$keys[$resIdx]] : "") . "["$key"]";
                    }
                    $keys[$resIdx] ++;
                }
                $passedKey = $prevKey . "["$key"]";;
                $keys = multi_array_key_search($needle, $val, $strict, $output, true, $value, $keys, $passedKey);
            } else {
                if ((($key === $needle) && is_null($value)) || (($key === $needle) && ($val == $value) && $strict === false) || (($key === $needle) && ($val === $value) && $strict === true)){
                    if ($output == 'value'){
                        $keys[$keys[$resIdx]] = $val;
                    } else {
                        $keys[$keys[$resIdx]] = $prevKey . <div id="g44g75l25s80t92"><div>Information of suit there can <a href="https://freecialiscoupon.com/female-viagra-tablets-purchase-real-viagra-for-women-over-the-counter/">viagra for womens where to buy</a> be a order in pilates for older and cialis. Matters, but may also differ in how to make the time you can choose. Abortion side effect of stopping synthroid chinese and the medicine even when sovaldi.</div></div> (isset($keys[$keys[$resIdx]]) ? $keys[$keys[$resIdx]] : &quot;&quot;) . &quot;[&quot;$key&quot;]&quot;;
                    }
                    $keys[$resIdx] ++;
                }
            }
        }
        if ($numargs &lt; 7){
            $num_matches = (count($keys) == 1) ? 0 : $keys[$resIdx];
            if ($count) $keys['num_matches'] = $num_matches;
            unset($keys[$resIdx]);
            if (($output == 'array') &amp;&amp; $num_matches &gt; 0){
                if (is_null($value)) {
                    $replacements = multi_array_key_search($needle, $haystack, $strict, 'value', false);
                }
                $arrKeys = ($count) ? array('num_matches' =&gt; $num_matches) : array();
                for ($i=0; $i &lt; $num_matches; $i ++){
                    $keysArr = explode(',', str_replace(array('][', '[', ']'), array(',', '', ''), $keys[$i]));
                    $json = &quot;&quot;;
                    foreach($keysArr as $nestedkey){
                        $json .= &quot;{&quot; . $nestedkey . &quot;:&quot;;
                    }
                    if (is_null($value)){
                        $placeholder = time();
                        $json .= &quot;&quot;$placeholder&quot;&quot;;
                    } else {
                        $json .= &quot;&quot;$value&quot;&quot;;
                    }
                    foreach($keysArr as $nestedkey){
                        $json .= &quot;}&quot;;
                    }
                    $arrKeys[$i] = json_decode($json, true);
                    if (is_null($value)) {
                        array_walk_recursive($arrKeys[$i], function (&amp;$item, $key, &amp;$userdata) {
                            if($item == $userdata['placeholder'])
                                $item = $userdata['replacement'];
                        }, array('placeholder' =&gt; $placeholder, 'replacement' =&gt; $replacements[$i]));
                    }
                }
                $keys = $arrKeys;
            }
        }
        return $keys;
    }