check in_array for nested array - php

I have an array in this format, and I want to check if a var is in the array from any of the keys link
$nav = array(
'Account Settings' => array(
'icon' => 'fa-cog',
'Account Settings' => array(
'link' => '/voip/settings?seq='.$seq,
'icon' => 'fa-cog',
),
'Provisioning' => array(
'link' => '/voip/provisioning?seq='.$seq,
'icon' => 'fa-wrench',
),
'E999 Data' => array(
'link' => '/voip/e999?seq='.$seq,
'icon' => 'fa-life-ring',
),
'Delete Account' => array(
'link' => '/voip/delete?seq='.$seq,
'icon' => 'fa-trash',
),
),
'Mailboxes' => array(
'link' => '/voip/mailboxes?seq='.$seq,
'icon' => 'fa-envelope',
),
'Telephone Numbers' => array(
'link' => '/voip/numbers?seq='.$seq,
'icon' => 'fa-hashtag',
),
);
I tried if(in_array($_GET["nav"], $nav) but it doesn't pick up the nested values
Is there a way to do this?

There's no readymade function to do that. Let's say you have:
$key = 'link';
$value = '/voip/e999?seq=' . $seq;
// and $nav your multidimensionnal array
You can write your own recursive function:
function contains_key_value_multi($arr, $key, $value) {
foreach ($arr as $k => $v) {
if ( is_array($v) && contains_key_value_multi($v, $key, $value) ||
$k === $key && $v === $value )
return true;
}
return false;
}
var_dump(contains_key_value_multi($nav, $key, $value));
You can use the spl classes to be able to loop over leafs of your multidimensionnal array. This time you don't need a recursive function:
$ri = new RecursiveIteratorIterator(new RecursiveArrayIterator($nav));
function contains_key_value($arr, $key, $value) {
foreach ($arr as $k => $v) {
if ( $k === $key && $v === $value )
return true;
}
return false;
}
var_dump(contains_key_value($ri, $key, $value));

Since you say the value is in link key then you can use array_column to isolate the link items.
if(in_array($_GET["nav"], array_column($nav['Account Settings'], "link")) || in_array($_GET["nav"], array_column(array_slice($nav, 1), "link"))){
This will first look at all link items in account settings, then slice out account settings and look at the other two subarrays for link items.
Test it here:
https://3v4l.org/pP2Nk

Related

php array how get in array value for using foreach

I have multiple array, I want particular value get using foreach below my code
Notice: Undefined index: transId in on line 52
$test = array(
'messages' => Array
(
'resultCode' => 'Ok',
'message' => Array
(
'code' => 'I00001',
'text' => 'Successful',
),
),
'transactionResponse' => Array
(
'responseCode' => '1',
'authCode' => 'Z7K31J',
'avsResultCode' => 'Y',
'cvvResultCode' => 'P',
'cavvResultCode' => '2',
'transId' => '40004672975',
'refTransID' => Array
(
),
'transHash' => '163382584395AB06470CF365AD6F7381',
'testRequest' => '0',
'accountNumber' => 'XXXX4242',
'accountType' => 'Visa',
'messages' => Array
(
'message' => Array
(
'code' => '1',
'description' => 'This transaction has been approved',
),
),
'transHashSha2' => Array
(
),
),
);
above my array, execute $test in foreach
I want display value of transid, response, transhash
foreach ($test as $key => $value) {
$response = $value['resultCode'];
$transId = $value['transId'];
$authCode = $value['authCode'];
$transHash = $value['transHash'];
}
use array_walk_recursive() where you don't have to go in each level of the array to echo your values like below:
<?php
array_walk_recursive($test, function ($item, $key){
if($key == 'transId' || $key == 'transHash' || $key == 'resultCode'){
echo $key." => ".$item."<br>";
}
});
You dont need foreach:
$response = $test['messages']['resultCode'];
$transId = $test['transactionResponse']['transId'];
$authCode = $test['transactionResponse']['authCode'];
$transHash = $test['transactionResponse']['transHash'];
you can use this
foreach ($test as $key => $value)
{
if(!empty($value['message']))
{
$response = $value['messages']['resultCode'];
}
elseif(!empty($value['transactionResponse']))
{
$transId = $value['transactionResponse']['transId'];
$authCode = $value['transactionResponse']['authCode'];
$transHash = $value['transactionResponse']['transHash'];
}
}
if you want proper then you have to take it to array and key as your transid

unable to delete array key from multidimensional array in cakephp

I want to delete array index which contain rating 0 here is my array
array(
(int) 0 => array(
'Gig' => array(
'id' => '1',
'rating' => (int) 5
)
),
(int) 1 => array(
'Gig' => array(
'id' => '3',
'rating' => (int) 9
)
),
(int) 2 => array(
'Gig' => array(
'id' => '4',
'rating' => '0'
)
)
)
and what I did
for($i = 0; $i<count($agetGigsItem); $i++)
{
if($agetGigsItem[$i]['Gig']['rating']==0)
{
unset($agetGigsItem[$i]);
}
$this->set('agetGigsItem', $agetGigsItem);
}
i also try foreach loop but unable to resolve this issue.
foreach ($agetGigsItem as $key => $value) {
if ($value["Gig"]["rating"] == 0) { unset($agetGigsItem[$key]); }
}
I think you need to reupdate your array.
foreach ($agetGigsItem as $key => $value) {
if ($value["Gig"]["rating"] != 0)
{
unset($agetGigsItem[$key]);
}
$this->set('agetGigsItem', $agetGigsItem);
}
I hope you are missing $this and so you cannot access the array in CakePHP.
So try this:
foreach ($this->$agetGigsItem as $key => $value) {
if ($value["Gig"]["rating"] == 0) {
unset($this->$agetGigsItem[$key]);
}
}
This code will unset arrey index with value 0.
<?php
$array=array(
array(
'Gig' => array(
'id' => '1',
'rating' =>5
)
),
array(
'Gig' => array(
'id' => '3',
'rating' =>9
)
),
array(
'Gig' => array(
'id' => '4',
'rating' =>0
)
)
);
foreach($array as $a){
if($a['Gig']['rating']==0){
unset($a['Gig']['rating']);
}
$array1[]=$a;
}
var_dump($array1);
Destroying occurances within an array you are actually processing over with a for or a foreach is always a bad idea. Each time you destroy an occurance the loop can easily get corrupted and get in a terrible mess.
If you want to remove items from an array it is better to create a copy of the array and process over that new array in the loop but remove the items from the original array.
So try this instead
$tmparray = $this->agetGigsItem; // will copy agetGigsItem into new array
foreach ($tmparray as $key => $value) {
if ($value["Gig"]["rating"] == 0) {
unset($this->agetGigsItem[$key]);
}
}
unset($tmparray);

Know the element level in multidimensional array

Well, I am here again dealing with arrays in php. I need your hand to guide me in the right direction. Suppose the following array:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
The - (hyphen) symbol only illustrates the deep level.
Well, I need to build another array (or whatever), because it should be printed as an HTML select as below:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
Looks that for each level element, it should add a space, or hyphen to determinate that it belongs to a particular parent.
EDIT
The have provide an answer provideng my final code. The html select element will display each level as string (repeating the "-" at the begging of the text instead multi-level elements.
Here's a simple recursive function to build a select dropdown given an array. Unfortunately I'm not able to test it, but let me know if it works. Usage would be as follows:
function generateDropdown($array, $level = 1)
{
if ($level == 1)
{
$menu = '<select>';
}
foreach ($array as $a)
{
if (is_array($a))
{
$menu .= generateDropdown($a, $level+1);
}
else
{
$menu .= '<option>'.str_pad('',$level,'-').$a.'</option>'."\n";
}
}
if ($level == 1)
{
$menu = '</select>';
}
return $menu;
}
OK, I got it with the help of #jmgardhn2.
The data
This is my array:
$temp = array(
array(
'name' => 'fruits',
'sons' => array(
array(
'name' => 'green',
'sons' => array(
array(
'name' => 'mango'
),
array(
'name' => 'banana',
)
)
)
)
),
array(
'name' => 'cars',
'sons' => array(
array(
'name' => 'italy',
'sons' => array(
array(
'name' => 'ferrari',
'sons' => array(
array(
'name' => 'red'
),
array(
'name' => 'black'
),
)
),
array(
'name' => 'fiat',
)
)
),
array(
'name' => 'germany',
'sons' => array(
array(
'name' => 'bmw',
)
)
),
)
)
);
Recursive function
Now, the following function will provide an array with items like [level] => [name]:
function createSelect($tree, $items, $level)
{
foreach ($tree as $key)
{
if (is_array($key))
{
$items = createSelect($key, $items, $level + 1);
}
else
{
$items[] = array('level' => $level, 'text' => $key);
}
}
return $items;
}
Calling the funcion
Now, call the function as below:
$items = createSelect($temp, array(), 0);
Output
If you iterate the final $items array it will look like:
1fruits
2green
3mango
3banana
1cars
2italy
3ferrari
4red
4black
3fiat
2germany
3bmw

Quick Recursive search of all indexes within an array

Ok, so say I have an array as follows:
$buttons = array(
'mlist' => array(
'title' => 'Members',
'href' => $scripturl . '?action=mlist',
'show' => $context['allow_memberlist'],
'sub_buttons' => array(
'mlist_view' => array(
'title' => 'View the Member List',
'href' => $scripturl . '?action=mlist',
'show' => true,
),
'mlist_search' => array(
'title' => 'Search for Members',
'href' => $scripturl . '?action=mlist;sa=search',
'show' => true,
'is_last' => true,
),
),
),
'home' => array(
'title' => 'Home',
'href' => $scripturl,
'show' => true,
'sub_buttons' => array(
),
'is_last' => $context['right_to_left'],
),
'help' => array(
'title' => 'Help',
'href' => $scripturl . '?action=help',
'show' => true,
'sub_buttons' => array(
),
),
);
I need to sort through this array and return all indexes of it in another array as an index, and the values of these arrays will be the title. So it should return an array as follows:
array(
'mlist' => 'Members',
'mlist_view' => 'View the Member List',
'mlist_search' => 'Search for Members',
'home' => 'Home',
'help' => 'Help',
);
How can this be achieved easily? Basically, need the key of each array if a title is specified and need to populate both within another array.
The following snippet loops over all of the arrays (recursively) to extract the key/title pairs.
$index = array();
$iterator = new RecursiveIteratorIterator(new ParentIterator(new RecursiveArrayIterator($buttons)), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $key => $value) {
if (array_key_exists('title', $value)) {
$index[$key] = $value['title'];
}
}
var_dump($index);
How can this be achieved easily?
initialize an empty, new array
foreach the $buttons array with key and value
extract title from value
set the key in the new array with the title
done.
Edit: In case a recursive array iterator catches too much (identifying elements as children while they are not - just being some other array), and you don't want to write an extension of the recursive iterator class, stepping through all children can be solved with some "hand written" iterator like this:
$index = array();
$childKey = 'sub_buttons';
$iterator = $buttons;
while(list($key, $item) = each($iterator))
{
array_shift($iterator);
$index[$key] = $item['title'];
$children = isset($item[$childKey]) ? $item[$childKey] : false;
if ($children) $iterator = $children + $iterator;
}
This iterator is aware of the child key, so it will only iterate over childs if there are some concrete. You can control the order (children first, children last) by changing the order:
if ($children) $iterator = $children + $iterator;
- or -
if ($children) $iterator += $children;
I'm sure my answer is not most efficient, but using many foreach loops and if checks, it can be done. However, with my solution if you nested another array inside of say 'mlist_view' that you needed to get a title from, it would not work. My solution works for a max of 2 arrays inside of arrays within buttons. A better (and more general purpose solution) would probably involve recursion.
$result = array();
foreach($buttons as $field => $value) {
foreach($value as $nF => $nV) {
if($nF === 'title') {
$result[$field] = $nV;
}
if(is_array($nV)) {
foreach($nV as $name => $comp) {
if(is_array($comp)) {
foreach($comp as $nnF => $nnV) {
if($nnF === 'title') {
$result[$name] = $nnV;
}
}
}
}
}
}
}
foreach($result as $f => $v) {
echo $f.": ".$v."<br/>";
}
This works for your value of $buttons, fairly simple:
function get_all_keys($arr) {
if (!is_array($arr)) return array();
$return = array();
foreach (array_keys($arr) as $key) {
if (is_array($arr[$key])
&& array_key_exists('title', $arr[$key]))
$return[$key] = $arr[$key]['title'];
$return = array_merge($return, get_all_keys($arr[$key]));
}
return $return;
}
echo "<pre>";
print_r(get_all_keys($buttons));
echo "</pre>";
Which returns:
Array
(
[mlist] => Members
[mlist_view] => View the Member List
[mlist_search] => Search for Members
[home] => Home
[help] => Help
)

PHP Recursively unset array keys if match

I have the following array that I need to recursively loop through and remove any child arrays that have the key 'fields'. I have tried array filter but I am having trouble getting any of it to work.
$myarray = array(
'Item' => array(
'fields' => array('id', 'name'),
'Part' => array(
'fields' => array('part_number', 'part_name')
)
),
'Owner' => array(
'fields' => array('id', 'name', 'active'),
'Company' => array(
'fields' => array('id', 'name',),
'Locations' => array(
'fields' => array('id', 'name', 'address', 'zip'),
'State' => array(
'fields' => array('id', 'name')
)
)
)
)
);
This is how I need it the result to look like:
$myarray = array(
'Item' => array(
'Part' => array(
)
),
'Owner' => array(
'Company' => array(
'Locations' => array(
'State' => array(
)
)
)
)
);
If you want to operate recursively, you need to pass the array as a reference, otherwise you do a lot of unnecessarily copying:
function recursive_unset(&$array, $unwanted_key) {
unset($array[$unwanted_key]);
foreach ($array as &$value) {
if (is_array($value)) {
recursive_unset($value, $unwanted_key);
}
}
}
you want array_walk
function remove_key(&$a) {
if(is_array($a)) {
unset($a['fields']);
array_walk($a, __FUNCTION__);
}
}
remove_key($myarray);
My suggestion:
function removeKey(&$array, $key)
{
if (is_array($array))
{
if (isset($array[$key]))
{
unset($array[$key]);
}
if (count($array) > 0)
{
foreach ($array as $k => $arr)
{
removeKey($array[$k], $key);
}
}
}
}
removeKey($myarray, 'Part');
function recursive_unset(&$array, $unwanted_key) {
if (!is_array($array) || empty($unwanted_key))
return false;
unset($array[$unwanted_key]);
foreach ($array as &$value) {
if (is_array($value)) {
recursive_unset($value, $unwanted_key);
}
}
}
function sanitize($arr) {
if (is_array($arr)) {
$out = array();
foreach ($arr as $key => $val) {
if ($key != 'fields') {
$out[$key] = sanitize($val);
}
}
} else {
return $arr;
}
return $out;
}
$myarray = sanitize($myarray);
Result:
array (
'Item' =>
array (
'Part' =>
array (
),
),
'Owner' =>
array (
'Company' =>
array (
'Locations' =>
array (
'State' =>
array (
),
),
),
),
)
function removeRecursive($haystack,$needle){
if(is_array($haystack)) {
unset($haystack[$needle]);
foreach ($haystack as $k=>$value) {
$haystack[$k] = removeRecursive($value,$needle);
}
}
return $haystack;
}
$new = removeRecursive($old,'key');
Code:
$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => $sweet);
function recursive_array_except(&$array, $except)
{
foreach($array as $key => $value){
if(in_array($key, $except, true)){
unset($array[$key]);
}else{
if(is_array($value)){
recursive_array_except($array[$key], $except);
}
}
}
return;
}
recursive_array_except($fruits, array('a'));
print_r($fruits);
Input:
Array
(
[sweet] => Array
(
[a] => apple
[b] => banana
)
[sour] => Array
(
[a] => apple
[b] => banana
)
)
Output:
Array
(
[sweet] => Array
(
[b] => banana
)
[sour] => Array
(
[b] => banana
)
)
I come up with a simple function that you can use to delete multiple array element based on multiple keys.
Detail example here.
Just a little change in code.
function removeRecursive($inputArray,$delKey){
if(is_array($inputArray)){
$moreKey = explode(",",$delKey);
foreach($moreKey as $nKey){
unset($inputArray[$nKey]);
foreach($inputArray as $k=>$value) {
$inputArray[$k] = removeRecursive($value,$nKey);
}
}
}
return $inputArray;
}
$inputNew = removeRecursive($input,'keyOne,keyTwo');
print"<pre>";
print_r($inputNew);
print"</pre>";
Give this function a shot. It will remove the keys with 'fields' and leave the rest of the array.
function unsetFields($myarray) {
if (isset($myarray['fields']))
unset($myarray['fields']);
foreach ($myarray as $key => $value)
$myarray[$key] = unsetFields($value);
return $myarray;
}
Recursively walk the array (by reference) and unset the relevant keys.
clear_fields($myarray);
print_r($myarray);
function clear_fields(&$parent) {
unset($parent['fields']);
foreach ($parent as $k => &$v) {
if (is_array($v)) {
clear_fields($v);
}
}
}
I needed to have a little more granularity in unsetting arrays and I came up with this - with the evil eval and other dirty tricks.
$post = array(); //some huge array
function array_unset(&$arr,$path){
$str = 'unset($arr[\''.implode('\'][\'',explode('/', $path)).'\']);';
eval($str);
}
$junk = array();
$junk[] = 'property_meta/_edit_lock';
$junk[] = 'property_terms/post_tag';
$junk[] = 'property_terms/property-type/0/term_id';
foreach($junk as $path){
array_unset($post,$path);
}
// unset($arr['property_meta']['_edit_lock']);
// unset($arr['property_terms']['post_tag']);
// unset($arr['property_terms']['property-type']['0']['term_id']);

Categories