I have an array with data that is nested as per the below (just a simplified example as it has to be "endless" since each family tree can go over X generations):
Array
(
[id] => 121
[name] => Very Important Dogs Bowey Showey
[gen] => 0
[mother] => Array
(
[id] => 128
[name] => Veridique Of Winners
[gen] => 1
[mother] =>
[father] =>
)
[father] => Array
(
[id] => 124
[name] => Rosickys Robocopico
[gen] => 1
[mother] => Array
(
[id] => 75
[name] => Astro Spice
[gen] => 2
[mother] =>
[father] =>
)
[father] => Array
(
[id] => 62
[name] => Your King of the World
[gen] => 2
[mother] =>
[father] =>
)
)
)
And I tried with this PHP function but without success because it indeed goes through each array and creates a bullet point, but I cannot isolate "name" and "ID" as they all come together.
function recurseTree($var){
$out = '<li>';
foreach($var as $v){
if(is_array($v)){
$out .= '<ul>'.recurseTree($v).'</ul>';
}else{
$out .= $v;
}
}
return $out.'</li>';
}
echo '<ul>'.recurseTree($familytree).'</ul>';
And this is what it gives me:
- 121Very Important Dogs' Bowey Showey0
- 128Veridique Of Winners1
- 124Rosicky's Robocopico1
- 75Astra's Spice2
- 62Lazhar's King of the World2
It gives me an unusable string. Instead, I want to use something like $v['id'] to get the id (and create an a href link) and the name with something like $v['name']... But how?!
The format I am after:
<ul>
<li><span>Mother</a></span>
<ul>
<li><span>Grandmother</span>
<ul>
<li><span>Grand-Grandmother</span></li>
<li><span>Grand-Grandfather</span></li>
</ul>
</li>
<li><span>Grandfather</span>
</ul>
</li>
<li><span>Father</a></span>
<ul>
<li><span>Grandmother</span>
<li><span>Grandfather</span>
</ul>
</li>
</ul>
Here is what you could do:
function recurseTree($var)
{
$out = '<li>';
foreach($var as $k => $v)
{
if(is_array($v))
{
$out .= '<ul>'.recurseTree($v).'</ul>';
}
else
{
switch($k)
{
case 'id':
$out .= 'id='.$v;
break;
case 'name':
$out .= 'name='.$v;
break;
}
}
}
return $out.'</li>';
}
echo '<ul>'.recurseTree($familytree).'</ul>';
Because your array is associative and appears to follow a consistent format, I think you can actually do this without using a loop at all. This should make the formatting much easier.
function recurseTree($var) {
if ($var) {
$link = '<span>'. $var['name']. '</span>';
$parents = '';
if ($var['mother'] || $var['father']) {
$parents = '<ul>'. recurseTree($var['mother']). recurseTree($var['father']). '</ul>';
}
return "<li>$link$parents</li>";
}
}
echo '<ul>' . recurseTree($familytree) . '</ul>';
Related
I need to search the following array for the sub-arrays that start with "prod_", then loop through those sub-arrays to get all the values. The amount of sub-arrays can vary depending on how many products in the cart.
Array
(
[address] => clayton85
[prod_0] => Array
(
[qty] => 2
[style] => American Apparel T-Shirt
[color] => Royal
[size] => Medium
[price] => 33.90
)
[prod_1] => Array
(
[qty] => 1
[style] => Bella Womens T-Shirt
[color] => Teal
[size] => Large
[price] => 17.95
)
[prod_2] => Array
(
[qty] => 1
[style] => Canvas Long Sleeve
[color] => Red
[size] => Large
[price] => 19.95
)
[prod_3] => Array
(
[qty] => 1
[style] => Canvas Long Sleeve
[color] => Red
[size] => Medium
[price] => 19.95
)
[cartTotal] => 91.75
)
I was able to come up with a very messy solution that returns the values by count, but there must be a better, more efficient way. Using PHP 5.5 this is what I came up with.
<?php
$cartArray = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
$item_cnt = 0;
foreach ($cartArray as $prod => $option) {
if (strpos($prod, "prod_") === 0) {
echo '<div class="row"><div class="col-xs-12"><div class="co-product">';
$i = 0;
foreach ($cartArray[$prod] as $key => $value) {
if ($i === 0) {echo '<span class="label">' . $value . '</span>'; $item_cnt = $item_cnt + intval($value);}
elseif ($i === 1) {echo '<span class="co-desc">' . $value . '<br>';}
elseif ($i === 2) {echo '<span class="co-subtext"><strong>Color:</strong> ' . $value . ' </span>';}
elseif ($i === 3) {echo '<span class="co-subtext"><strong>Size:</strong> ' . $value . '</span></span>';}
else {echo '<span class="co-price pull-right">$' . $value . '</span>';}
$i++;
}
echo '</div></div></div>';
}
}
?>
Loop through the main array and then just use the keys of the inner array:
foreach ($cartArray as $prod => $option) {
if (strpos($prod, "prod_") === 0) {
echo $option["qty"];
//etc...
}
}
I'm trying to loop over each object and show the team name on a website... however I want to skip the $variable->active key.
The number of teams varies...How can I skip the 'active' key?
I tried this but it doesn't seem to work:
$active = $team->active;
if (isset($team->active)) {
foreach ($team as $data) {
if (isset($data->idteam) != $active) {
print_r($data);
$return .= '<li><i class="fa fa-power-off"></i> ' . $data->nameteam . '</li>';
} else {
$return .= "No Teams!";
}
}
}
Here is my object:
teamAccess Object
(
[2] => Team Object
(
[nameteam] => Team 1
[idteam] => 2
[enabled] => 1
[last_access_stamp] => 1399603014
[create_stamp] => 4
[update_stamp] => 1399167351
)
[1] => Team Object
(
[nameteam] => Test Team
[idteam] => 1
[enabled] => 0
[last_access_stamp] => 1399603014
[create_stamp] => 0
[update_stamp] => 0
)
[3] => Team Object
(
[nameteam] => Team 3
[idteam] => 3
[enabled] => 1
[last_access_stamp] => 1399603014
[create_stamp] => 0
[update_stamp] => 0
)
[active] => 3
[alerts] => Array
(
)
)
In the foreach, you can capture the key, and check it in a condition to skip it:
foreach ($team as $key => $data) {
if ($key != 'active') {
$return .= '<li><i class="fa fa-power-off"></i> ' . $data->nameteam . '</li>';
}
}
Observation: it seems that the teamAccess object should have a teams property, which could be an array of team objects. This might be a better structure than having all of the data mixed together as root properties.
I have an object which looks like this
zen_categories_ul_generator Object
(
[root_category_id] => 0
[max_level] => 6
[data] => Array
(
[0] => Array
(
[19] => Array
(
[name] => Brushes
[count] => 0
)
[29] => Array
(
[name] => Clips
[count] => 0
)
[2] => Array
(
[name] => Combs
[count] => 0
)
[27] => Array
(
[name] => Jewellery
[count] => 0
)
)
[1] => Array
(
[57] => Array
(
[name] => Testing
[count] => 0
)
)
And I want to loop through all the information at the level $this->data[0], I'm using
foreach($this->data[0] as $category_id => $category) {
$result .= $category_id.' - '.$category['name'];
}
return $result;
but this will just the last item in the array. so in this case it would only have 27 - Jewellery but none of the other array item would be returned.
What am I doing wrong?
thanks
NB I only need to loop through the data[0] - not data[1] as well!
EDIT - here's a paste bin with a more code to make easier to understand what I'm trying to do and how I'm doing it. Any help gratefully received
http://pastebin.com/Vrw9f7Xh
Question:
Ok, so you want to loop through all the information $this->data[0], to render a menu.
Actually, you were pretty close to the solution, yourself.
The line used for rendering the product items, is:
$result .= ''.$category['name'] . ' (' . $category['count'] . ')';
The following is working example, which works standalone.
You might save it as menu.php and test it.
I had to comment the zen_* function out, but i think the relevant part is the rendering, right?
class zen_categories_ul_generator
{
function setTestData($data) { $this->data = $data; }
function buildMenu() {
$result = '';
// removed home link, unchanged and not important in this example
// submenu
$result .= '<li class="submenu">';
$result .= 'Products';
$count = 0;
foreach($this->data[0] as $category_id => $category) {
$count++;
$result .= '<ul class="level2">';
$result .= '<li class="submenu">';
//$result .= ''.$category['name'].''.$count;
$result .= ''.$category['name'] . ' (' . $category['count'] . ')';
$result .= '</li>';
$result .= '</ul>';
}
$result .= '</li> Items:' . $count;
return $result;
}
}
$object = new zen_categories_ul_generator;
// ok, lets add your example data from outside to the object, in order to test the rendering
$data = array(
0 => array(
19 => array('name' => 'Brushes', 'count' => 5),
29 => array('name' => 'Clips', 'count' => 2),
2 => array('name' => 'Combs', 'count' => 1),
27 => array('name' => 'Jewellery', 'count' => 3)
)
);
$object->setTestData($data);
// render the menu
echo $object->buildMenu();
Result
Count is the number of iterations = the number of Products in a Category.
And the counter behind the product name is from the array, the key "count".
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;
}
}
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;
}