array_walk_recursive return value - php

I am using array_walk_recursive with a callback function to search within a nested array for specified key:
array_walk_recursive($array, array($this, 'walk_array'), $key);
Here is the callback function:
function walk_array($value, $key, $userdata = '')
{
if ($key === $userdata)
{
self::$items_array[$key] = $value;
echo $value . "<br />\n";
}
}
The problem is that I can not find a way to store/return the found elements from the callback function even though I am using static variable $items_array but it always contains the last item processed by the array_walk_recursive. On the other hand, if I echo the found elements from callback function:
echo $value . "<br />\n";
All found elements are echoed fine.
How do I return or store the found elements from the callback function?

If $key is going to correspond to multiple values in the nested arrays that you walk through, your $item_arrays should have its own array for that key. Otherwise, all you're really doing is overwriting self::$items_array[$key] with every value that comes by.
Try this:
self::$items_array[$key][] = $value;

Related

array_walk_recursive can't work when I use function htmlspecialchars?

I use array_walk_recursive to apply htmlspecialchars on my array value, but it didn't work, htmlspecialchars works when I use it manully;
Here is my code:
$new[] = "<a href='test'>Test</a><li><div>";
var_dump(array_walk_recursive($new,'htmlspecialchars')); // true
var_dump($new) ; // no change
That is because the original array is not modified unless you modify it yourself in the callback function.
Your callback function is basically:
function($item, $key) {
htmlspecialchars($item);
}
So while the function is called, nothing is stored and the original array is not changed.
If you want to modify the value in the function, you can pass it by reference:
function(&$item, $key) {
$item = htmlspecialchars($item);
}
So the result would look like:
$new[] = "<a href='test'>Test</a><li><div>";
array_walk_recursive($new, function(&$item, $key) {
$item = htmlspecialchars($item);
});
var_dump($new) ; // change!
You can of course define a separate function if you would prefer that.
In the definition of array_walk_recursive:
array_walk_recursive — Apply a user function recursively to every
member of an array
So you need to create a user defined function that uses htmlspecialchars like this:
$new[] = "<a href='test'>Test</a><li><div>";
array_walk_recursive($new, "specialChars");
var_dump($new);
function specialChars(&$value) {
$value = htmlspecialchars($value);
}
And this will print:
array (size=1)
0 => string '<a href='test'>Test</a><li><div>' (length=56)

function stored inside array

i want to call function store inside array but before i do it i want to check if it is function,string or any other type.
please take a look at my code
$a=new stdClass();
$array = array(function() {
return "Bhavik Patel";
}, "1213",$a);
foreach ($array as $key => $value) {
if (is_object($value)) {
echo $value() . "<br/>";
} else {
echo $value . "<br/>";
}
}
by doing this i can check if value is object then i call it but if i pass object it gives (pf course this will give error)
my intention is to find if value is function then call it.
To check specifically for anonymous functions you can test the value against \Closure like so:
if ($value instanceof \Closure) {
echo $value(), "\n";
} else {
echo $value;
}
The problem with is_callable() is that if your value is "explode", it will return true which is obviously not what you want.
is_callable() will help you, but notice that if you pass an array like this
array('object or class','method')
is_callable() return true, so you'd better to check it isn't an array
if (is_callable($value) && !is_array($value)) {.....}
see is_callable
Try [is_callable][1] in PHP. I have tested it, it works for me.

Passing location in subarray as string

I have a function that searches a multidimensional array for a key, and returns the path
inside the array to my desired key as a string.
Is there any way I can use this string in php to reach this place in my original array, not to get to the value but to make changes to this specific bracnch of the array?
An example:
$array = array('first_level'=>array(
'second_level'=>array(
'desired_key'=>'value')));
in this example the function will return the string:
'first_level=>second_level=>desired_key'
Is there a way to use this output, or format it differently in order to use it in the following or a similar way?
$res = find_deep_key($array,'needle');
$array[$res]['newkey'] = 'injected value';
Thanks
If the keys path is safe (e.g. not given by the user), you can use eval and do something like:
$k = 'first_level=>second_level=>desired_key';
$k = explode('=>', $k);
$keys = '[\'' . implode('\'][\'', $k) . '\']';
eval('$key = &$array' . $keys . ';');
var_dump($key);
I think you want to do a recursive search in the array for your key? Correct me if i am wrong.
Try this
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
Taken from here http://in3.php.net/manual/en/function.array-search.php#91365
You need something like:
find_key_in_array($key, $array, function($foundValue){
// do stuff here with found value, e.g.
return $foundValue * 2;
});
and the implementation would be something like:
function find_key_in_array($key, $array, $callback){
// iterate over array fields recursively till you find desired field, then:
...
$array[$key] = $callback($array[$key]);
}
If you need to append some new sub-array into multidimensional complex array and you know where exactly it should be appended (you have path as a string), this might work (another approach without eval()):
function append_to_subarray_by_path($newkey, $newvalue, $path, $pathDelimiter, &$array) {
$destinationArray = &$array;
foreach (explode($pathDelimiter, $path) as $key) {
if (isset($destinationArray[$key])) {
$destinationArray = &$destinationArray[$key];
} else {
$destinationArray[$newkey] = $newvalue;
}
}
}
$res = find_deep_key($array,'needle');
append_to_subarray_by_path('newkey', 'injected value', $res, '=>', $array);
Of course, it will work only if all keys in path already exist. Otherwise it will append new sub-array into wrong place.
just write a function that takes the string and the array. The function will take the key for each array level and then returns the found object.
such as:
void object FindArray(Array[] array,String key)
{
if(key.Length == 0) return array;
var currentKey = key.Split('=>')[0];
return FindArray(array[currentKey], key.Remove(currentKey));
}

abs of an array

Which is the easy way of getting the abs of an array in php? It has to be a better way. This works, but in multidimensional array it has some limitations
function make_abs($numbers) {
$abs_array = array();
foreach($numbers as $key=>$value)
$abs_array[$key] = abs($value);
return $abs_array;
}
Use a map function:
array_map("abs", $numbers)
http://php.net/manual/en/function.array-map.php
Your variant using references (this does not solve your recursion problem, just FYI):
function make_abs(&$numbers)
{
foreach($numbers as &$value)
$value = abs($value)
;
}
For the recursion problem, you need to step into each array:
function make_abs(&$numbers)
{
foreach($numbers as &$value)
is_array($value) ? make_abs($value) : $value = abs($value)
;
}
PHP itself has a somewhat handy function for that, array_walk_recursiveDocs. The problem with that function is, it expects the callback to have two parameters, value (by reference) and key. Many PHP functions do not fit those requirements. You can work around that by creating yourself a helper function to use any function that only takes one parameter and returns the modified value. You pass the function as with array_mapDocs:
function array_walk_recursive_map(array &$array, $callback)
{
$byRef = function(&$item, $key) use ($callback)
{
$item = $callback($item);
};
array_walk_recursive($array, $byRef);
}
# Usage:
array_walk_recursive_map($numbers, 'abs');
Hope this is helpful.
You could do array_walk_recursive($numbers, 'make_abs');
http://php.net/manual/en/function.array-walk-recursive.php
Edit
$numbers = array(1, 35, 107);
function make_abs(&$item,$key) { // use with reference
$item = abs($item);
}
array_walk_recursive($numbers, 'make_abs');
This example works with multidimensional arrays.

user input - testing array for empty values *

check::empty_user()
below will test an array for 'empty' values -
NULL, FALSE, 0, or ' '
/*check*/
class check
{
static function empty_user($a)
{
return (int)!in_array('',$a);
}
}
function test_empty(array $array) {
foreach($array as $elem) {
if (!empty($elem)) return false;
}
return true; // no element, or no non-empty element
}
in_array('', $array);
I think that is what you're after?
Your function isn't going to test anything other than the first element of your array. Return causes the function to cease execution.
PHP has empty and isset functions, either of those should be suitable testing array elements. To test the entire array you can use in_array and look for empty values. However you'll have to implement your own method for processing nested arrays.
You test empty could also be the folowing:
// if the array has at least one empty value
function test_empty(array $array) {
foreach($array as $elem) {
if (empty($elem)) return true;
}
return false;
}
In summary use
empty() or in_array()
and make note that:
$value=='' tests for null, false, 0, and ''

Categories