I need to print the below array structure as:
Node Title 1
topic 1
topic 2
topic 3
topic 4
asset title1
asset title2
asset title3
How can i do using foreach - PHP
What i have done is :
foreach($output['fields'] as $key => $value) {
if($key == 'title') {
echo $value;
}
if(count($value['main_topic'])) {
foreach($value['main_topic'] AS $mainkey => $main_topic) {
echo $main_topic['topic_title'];
}
}
}
The above syntax is printing the title. But not the main_topic array.
Array
(
[fields] => Array
(
[nid] => 136
[node_title] => Node title 1
[node_type] => curriculum
[title] => Node title 1
[main_topic] => Array
(
[0] => Array
(
[row_id] => 136
[topic_id] => 411847
[weight] => 10
[topic_title] => topic 1
)
[1] => Array
(
[row_id] => 136
[topic_id] => 411839
[weight] => 2
[topic_title] => topic 2
)
[2] => Array
(
[row_id] => 136
[topic_id] => 411840
[weight] => 3
[topic_title] => topic 3
)
[3] => Array
(
[row_id] => 136
[topic_id] => 411841
[weight] => 4
[topic_title] => topic 4
[subfield] => Array
(
[1] => Array
(
[asset_title] => asset title 1
)
[2] => Array
(
[asset_title] => asset title 2
)
[3] => Array
(
[asset_title] => asset title 3
)
)
)
)
)
)
That is because you are iterating over all $output['fields'].
There will never be a $value with key 'main_topic' because the key 'main_topic' is contained in the $output['fields'] array and thus exists only as $key in your foreach. The array you want is $value
Your code should be like:
foreach($output['fields'] as $key => $value) {
if($key == 'title') {
echo $value;
continue;
}
if($key == 'main_topic' && is_array($value)) {
foreach($value as $main_topic) {
echo $main_topic['topic_title'];
}
}
}
To complete this answer with a full solution (including asset titles), below is how I would write it.
Because $output['fields'] is the starting point and to make the code more readable, I create a reference to the starting node using the =& operator so the array is not copied in memory. I do the same with the inner foreachs. Since we are not modifying data, referencing the variables is sufficient and consumes less memory and CPU:
if (is_array($output['fields'])) {
$node =& $output['fields'];
echo $node['title'];
if(is_array($node['main_topic'])) {
foreach($node['main_topic'] as &$main) {
echo $main['topic_title'];
if(is_array($main['subfield'])) {
foreach($main['subfield'] as &$asset) {
echo $asset['asset_title'];
}
}
}
}
}
else {
echo "no menu";
}
$value is the array, not $key['main_topic']
foreach($output['fields'] as $key => $value) {
if($key == 'title') {
echo $value;
}
if($key == 'main_topic') {
foreach($value as $mainkey => $main_topic) {
echo $main_topic['topic_title'];
}
}
}
Try this, you need the additional key:
echo $value['main_topic'][$mainkey]['topic_title'];
You're getting your array sections confused.
Try (and I haven't tested this) :
echo $output['node_title']."\n";
foreach ($output['fields'] as $key=>$value)
{
switch ($key)
{
case 'title':
echo $value."\n";
break;
case 'main_topic':
if (count($value) > 0)
{
foreach ($value as $main_block)
{
echo "\t".$main_block['topic_title']."\n";
if (array_key_exists('subfield',$main_block)!==FALSE)
{
foreach ($main_block['subfield'] as $subfield_block)
{
echo "\t\t".$subfield_block['asset_title']."\n";
}
}
}
}
break;
default:
break;
}
}
Related
I'm struggling trying to break out of this nested foreach loop.
If you take a look at my data, I'm trying to go within the team info array, find out what the team ID number is and once I know that ID number, I want to break out of the team array and go into the stats array for that particular ID(team) so I can get each statistic.
The data I'm using updates every week according to each team's rank, so the ID is the only way to know for sure the team you are looking up.
I have the following code so far and can get the team ID number but like I said I want to break out of the team array with the ID number and go into the stats array for that particular ID. Also, this data is for every NFL team and is very long, so I only posted what I could for the array so you get the idea and my foreach loop is below.
Any help is very much appreciated!!!
Array:
Array(
[overallteamstandings] => Array
(
[lastUpdatedOn] => 2019-12-13 4:03:05 AM
[teamstandingsentry] => Array
(
[0] => Array
(
[team] => Array
(
[ID] => 56
[City] => Baltimore
[Name] => Ravens
[Abbreviation] => BAL
)
[rank] => 1
[stats] => Array
(
[GamesPlayed] => Array
(
[#abbreviation] => G
[#text] => 14
)
[PassAttempts] => Array
(
[#category] => Passing
[#abbreviation] => Att
[#text] => 384
)
[PassCompletions] => Array
(
[#category] => Passing
[#abbreviation] => Comp
[#text] => 255
)
[PassPct] => Array
(
[#category] => Passing
[#abbreviation] => Pct
[#text] => 66.4
)
[PassGrossYards] => Array
(
[#category] => Passing
[#abbreviation] => Yds
[#text] => 3016
)
Foreach Loop:
foreach ($response as $overallteamstandings => $b) {
foreach ($b['teamstandingsentry'] as $key => $d) {
//if ($key == '9'){
foreach ($d as $cat => $info) {
if ($cat == 'team') {
foreach ($info as $c => $v) {
if ($c == 'ID') {
echo $v;
if ($v == '59') {
//break 4;
}
}
}
}
if ($cat == 'stats') {
foreach ($info as $category => $stats) {
if ($category == 'Wins') {
foreach ($stats as $val => $value) {
if ($val == '#text') {
echo $value . "-";
}
}
}
if ($category == 'Losses') {
foreach ($stats as $val => $value) {
if ($val == '#text') {
echo $value;
}
}
}
}
}
}
//}
}
}
Here are some functions that might make your life easier. The first returns the ID value for a team based on its name or city. The second returns the stats array for team based on its ID value. All functions return false if they can't find a matching value.
// get a team's id based on its name or city
function get_team_id($response, $team, $type) {
$teams = array_column($response['overallteamstandings']['teamstandingsentry'], 'team');
switch ($type) {
case 'name':
$key = array_search($team, array_column($teams, 'Name'));
return ($key !== false) ? $teams[$key]['ID'] : false;
break;
case 'city':
$key = array_search($team, array_column($teams, 'City'));
return ($key !== false) ? $teams[$key]['ID'] : false;
break;
default:
return false;
}
}
// get a team's stats based on its ID
function get_stats($response, $team) {
$teams = array_column($response['overallteamstandings']['teamstandingsentry'], 'team');
$key = array_search($team, array_column($teams, 'ID'));
return ($key !== false) ? $response['overallteamstandings']['teamstandingsentry'][$key]['stats'] : false;
}
Example usage (based on your sample data):
echo "ID for city Baltimore is " . get_team_id($response, 'Baltimore', 'city') . "\n";
echo "ID for name Ravens is " . get_team_id($response, 'Ravens', 'name') . "\n";
Output:
ID for city Baltimore is 56
ID for name Ravens is 56
Getting the stats array:
print_r(get_stats($response, 56));
Output:
Array
(
[GamesPlayed] => Array
(
[#abbreviation] => G
[#text] => 14
)
[PassAttempts] => Array
(
[#category] => Passing
[#abbreviation] => Att
[#text] => 384
)
[PassCompletions] => Array
(
[#category] => Passing
[#abbreviation] => Comp
[#text] => 255
)
[PassPct] => Array
(
[#category] => Passing
[#abbreviation] => Pct
[#text] => 66.4
)
[PassGrossYards] => Array
(
[#category] => Passing
[#abbreviation] => Yds
[#text] => 3016
)
)
Demo on 3v4l.org
how to get the index of a children array for an array look like this:
Array
(
[1000] => Array
(
[firstName] => Ori
[lastName] => Smith
[children] => Array
(
[0] => 1001
[1] => 1002
[2] => 1003
[3] => 1004
[4] => 1005
[5] => 1006
[6] => 1007
[7] => 1008
[8] => 1009
[9] => 1010
)
)
)
so if I give 1009 as the search, it should return 1000.
It does not work with this code:
array_search($childrenId, array_column(myArray, 'children'));
Try this
$result = array(
'1000'=>array('children'=>array('1001','1002')),
'2000'=>array('children'=>array('2001','2002'))
);
$searchValue = 2001;
$keyName = '';
foreach ($result as $key => $row) {
foreach ($row['children'] as $child) {
if ($child == $searchValue) {
$keyName = $key;
break;
}
}
}
echo $keyName;
You can use this function found here:
function getParentStack($child, $stack) {
foreach ($stack as $k => $v) {
if (is_array($v)) {
// If the current element of the array is an array, recurse it and capture the return
$return = getParentStack($child, $v);
// If the return is an array, stack it and return it
if (is_array($return)) {
return array($k => $return);
}
} else {
// Since we are not on an array, compare directly
if ($v == $child) {
// And if we match, stack it and return it
return array($k => $child);
}
}
}
// Return false since there was nothing found
return false;
}
I guess you could get the key by key(getParentStack(1009, $myarr)) or modify the function.
Array
(
[updateCategories] => Array
(
[products] => Array
(
[0] => Array
(
[cat_id] => 3
[position] => 2
[product_id] => 8
)
[1] => Array
(
[cat_id] => 4
[position] => 11
[product_id] => 8
)
[2] => Array
(
[cat_id] => 3
[position] => 4
[product_id] => 39
)
[3] => Array
(
[cat_id] => 4
[position] => 9
[product_id] => 8
)
[4] => Array
(
[cat_id] => 3
[position] => 6
[product_id] => 41
)
[5] => Array
(
[cat_id] => 11
[position] => 7
[product_id] => 8
)
The above array is my output array but I need to get all cat_id of product_id=8. How can I do this?
$newarr = array();
foreach( $arr['updateCategories']['products'] as $myarr)
{
if($myarr['product_id'] == 8)
$newarr[] = $myarr['cat_id'];
}
The simpliest solution is
$result = array();
foreach($yourArray['updateCategories']['products'] as $product)
if($product['product_id] == 8)
$product[] = $product['cat_id'];
where $yourArray is the array which dump you have published.
Try something like this:
$arr = array();
foreach ($products as $key => $value)
{
if($value['product_id'] == 8)
{
$arr[] = $key;
}
}
print_r($arr); // <-- this should output the array of products with key as 8
Use this
foreach($array['updateCategories']['products'] as $product) {
if(isset($product['product_id']) && $product['product_id']==8) {
//do anything you want i am echoing
echo $product['cat_id'];
}
}
You can use array_filter.
function filterProducts($product) {
return ($product['product_id'] == 8);
}
$myProducts = array_filter(
$myArray['updateCategories']['products'],
'filterProducts'
);
Where $myArray is the array displayed in your post.
Can handle this by doing something like this
$matching_products = array();
foreach ($products as $key => $value) {
if($value['product_id'] == 8) {
$matching_products[] = $value['cat_id'];
}
}
which'll leave you with an array of cat ids that have a product id of 8
This should be able to retrieve all of the cat_id's from a given product_id. This function yields an object that can be iterated over to retrieve all the values it contains.
<?PHP
public function GetCatIdsByProductId($productId)
{
foreach($updateCategories=>products as $key=>$product)
{
if (isset($product=>product_id) && $product=>product_id == 8)
{
yield $product=>cat_id;
}
}
}
//Usage
$catIds = GetCatIdsByProductId(8);
var_dump($catIds);
A more generic version of this function can be constructed to retrieve a given key from a comparison on a given property value.
public function GetPropertyByPropertyComparison(array $list, $propRet, $propCompare, $compValue)
{
foreach($list as $key=>$product)
{
if (isset($product=>{$propCompare}) && $product=>{$propCompare} == $compValue)
{
yield $product=>{$propRet};
}
}
}
//usage
$cats = GetPropertyByPropertyComparison($updateCategories=>products, "cat_id", "product_id", 8);
var_dump($cats);
?>
I am trying to get the item id, and then all option_name/option_values within that item id. So I end up with, ID: 123, Color: Blue, Size: 6. ID: 456, Color: Yellow, Size: 8. However I am getting the correct item ID, but the option_name/option_value isn't coming through correctly, either blank or just one random letter.
Here's my code that doesn't work,
foreach($itemlist as $item)
{
echo $item['ID'];
foreach($item as $option)
{
echo $option['option_name'];
echo $option['option_value'];
}
}
Where $itemlist looks like this:
Array
(
[1] => Array
(
[ID] => 123
[QTY] => 1
[MODEL] => sdfsd
[IMAGE] =>
[1] => Array
(
[option_name] => Color
[option_value] => Blue
[option_price] => 0.0000
)
[2] => Array
(
[option_name] => Size
[option_value] => 6
[option_price] => 0.0000
)
[price] => 0
)
[2] => Array
(
[ID] => 456
[QTY] => 0
[MODEL] => gsdfgd
[IMAGE] =>
[1] => Array
(
[option_name] => Color
[option_value] => Yellow
[option_price] => 0.0000
)
[2] => Array
(
[option_name] => Size
[option_value] => 8
[option_price] => 0.0000
)
[price] => 0
)
)
Basically, you're looping over the $item array, which looks like this:
array(7) {
["ID"]=>string(6) "123"
["QTY"]=>string(1) "1"
["MODEL"]=>string(11) "sdfsd"
["IMAGE"]=>string(0) ""
[1]=>
array(3) {
["option_name"]=>string(8) "Color"
["option_value"]=>string(10) "Blue"
["option_price"]=>string(6) "0.0000"
}
So on the first iteration, $option will be 123, trying to access '123'['option_name'] will issue a warning. What you actually wanted to do is this:
foreach($item[1] as $key => $option)
{
if ($key !== 'option_price')
{
echo $option;
}
}
//or:
echo $item['ID'], $item[1]['option_name'], $item['option_value'];
That's why your code doesn't produce the desired result.
If the sub-array doesn't always have 1 as a key, try:
foreach($item as $foo)
{
if (is_array($foo))
{
echo $foo['option_name'], $foo['option_value'];
break;//we have what we needed, no need to continue looping.
}
}
Here's the most generic approach to get all options (irrespective of how many)
foreach($itemlist as $item)
{
echo $item['ID'];
foreach($item as $sub)
{
if (is_array($sub))
{
foreach($sub as $key => $option)
{
echo $key, ' => ', $option;
}
}
}
}
But seeing as your options arrays look like they all have numeric indexes, you could just as well try this:
foreach($itemlist as $item)
{
echo $item['ID'];
for ($i=1;isset($item[$i]);$i++)
{
foreach($item[$i] as $key => $option)
{
echo $key, ' => ', $option;
}
}
}
You could replace the for loop with:
$i=0;//or $i = 1
while(isset($item[++$i]))// or isset($item[$i++]), if $i is 1
This is because your array contains the POSSIBILITY of those keys existing, not guaranteed. There's a few different approaches you could take, such as checking if the key is numeric (seems only numeric keys have the correct array of keys set). But since i dont know your dataset, probably the best universal method is to change your code to check if the key's are set, before trying to use them. So..
foreach($itemlist as $item) {
foreach($item as $key => $value) {
if(is_array($value) && array_key_exists('option_name', $value) {
//--- Your option array is available in here via $value['option_x']
}
}
}
You could try something like:
array_walk_recursive($itemlist, function($value, $key) {
if (in_array($key, array("ID", "option_name", "option_value")))
echo "$key: $value\n";
});
I have tried to get my head around building a recursive function to handle formatting of a unknown depth multi-dimensional array to HTML and nested Divs. I thought that it should be a piece of cake, but no.
Here's what I have come up with this far:
function formatHtml($array) {
$var = '<div>';
foreach ($array as $k => $v) {
if (is_array($v['children']) && !empty($v['children'])) {
formatHtml($v['children']);
}
else {
$var .= $v['cid'];
}
}
$var.= '</div>';
return $var;
}
And here's my array:
Array
(
[1] => Array
(
[cid] => 1
[_parent] =>
[id] => 1
[name] => 'Root category'
[children] => Array
(
[2] => Array
(
[cid] => 2
[_parent] => 1
[id] => 3
[name] => 'Child category'
[children] => Array ()
)
)
)
)
You're missing only one important piece: when you make the recursive call to formatHtml() you're not actually including the returned content anywhere! Append it to $var and you should get much better results:
function formatHtml($array) {
$var = '<div>';
foreach ($array as $k => $v) {
if (is_array($v['children']) && !empty($v['children'])) {
$var .= formatHtml($v['children']);
}
else {
$var .= $v['cid'];
}
}
$var.= '</div>';
return $var;
}