How can I show array in PHP? - php

I have this source to show array
foreach ($menu_items as $item=>$value) {
if($item != 'about-me'){
echo ''.$item.'';
}else if($item == 'about-me'){
echo 'about';
}
And this is my array:
$menu_items = array(
"disabled" => array (
"contact" => "Contact",
),
"enabled" => array (
"services" => "Services",
"process" => "Process",
"portfolio" => "My Portfolio",
"about-me" => "Abouuuuut",
"contact" => "Contact",
),
);
Now it shows me (when it is enabled):
services
process
portfolio
about
contact
I want to show:
Services
Process
My Portfolio
about
Contact

You need to do this:
foreach ($menu_items as $item=>$value) {
if($item != 'about-me'){
echo ''.$value.''; //change here
}else if($item == 'about-me'){
echo 'about';
}
}
You are using $item, use the $value instead of $item.

Related

Unset is not unsetting Array values

I am trying to build a dynamic Menu from data I generate from jstree.
Jstree values will stored in database as follows:
Id | Name | Parent | Icon | Link
So I've made a method to read each row from database(propel) and store it in array, so Smarty can build a menu dynamically.
That's my function:
$menu_content = array();
foreach($result as $key => $r) {
if($r['Id'] != 1) {
$Id = $r['Id'];
$menu_content[$r['Id']] = array(
"name" => $r['Name'],
"link" => $r['Link'],
"icon" => $r['Icon']
);
unset($result[$key]);
foreach($result as $key_children => $c) {
if($c['Parent'] == $r['Id']) {
$menu_content[$r['Id']]['children'][] = array(
"name" => $c['Name'],
"link" => $c['Link'],
"icon" => $c['Icon']
);
unset($result[$key_children]);
$Idc = $c['Id'];
foreach($result as $key_grandchild => $cc) {
if($cc['Parent'] == $c['Id']) {
$menu_content[$r['Id']]['children']['grandchild'][] = array(
"name" => $cc['Name'],
"link" => $cc['Link'],
"icon" => $cc['Icon']
);
unset($result[$key_grandchild]);
}
}
}
}
}
So it should store values like this:
$menu_content[parent][children][grandchildren].
This part of code is working fine, but it's not unsetting the children and grandchildren values, so I get them twiche. First time in correct order and after that as parent children.
Thanks in advance.

3d nested array foreach statement issue

I have this array written below, and I know it isnt pretty, sorry. I come to this array structure as it is the only way I could think of when dealing with my post request.
$_POST = array("person" => array(
[1] => array("id" => 1, "name" => "bob"),
[2] => array("id" => 2, "name" => "jim")
)
);
I want to be able to pick "name" from certain "id", so below code is what I came up with. In the example below, if person["id"] is equal to 1, retrieve its "name" which is "bob".
foreach ($_POST as $dataSet) {
foreach ($dataSet as $person) {
foreach ($person as $field => $value) {
if ($person["id"] == 1) {
echo $person["name"];
}
}
}
}
The problem I am having is as I execute the code.
the result is bobbob,
it seems like the code looped the if statement twice (same as the number of elements in the person array). I know if I put break into the code, then it will solve it, but anyone know why it looped twice? Maybe this will deepen my foreach and array understanding.
There is no need to have third nested loop. Hope this one will be helpful.
Problem: In the third loop you were iterating over Persons: array("id" => 1, "name" => "bob") which have two keys. and you are checking only single static key $person["id"], that's why it was printing twice.
Solution 1:
Try this code snippet here
<?php
ini_set('display_errors', 1);
$POSTData = array("person" => array(
1 => array("id" => 1, "name" => "bob"),
2 => array("id" => 2, "name" => "jim")
)
);
foreach ($POSTData as $dataSet)
{
foreach ($dataSet as $person)
{
if ($person["id"] == 1)
{
echo $person["name"];
}
}
}
Solution 2:
Alternatively you can try this single line solution.
Try this code snippet here
echo array_column($POSTData["person"],"name","id")[1];//here 1 is the `id` you want.
You must have seen the other answers, and they have already said that you dont need the 3rd loop. but still if you want to keep the third loop.
you can use this code.
foreach ($_POST as $dataSet) {
foreach ($dataSet as $person) {
foreach ($person as $field => $value) {
if($value == 1){
echo $person['name'];
}
}
}
}
No need of third foreach
<?php
$mainArr = array("person" => array(
1 => array("id" => 1, "name" => "bob"),
2 => array("id" => 2, "name" => "jim")
)
);
foreach ($mainArr as $dataSet) {
foreach ($dataSet as $person) {
if ($person["id"] == 1) {
echo $person["name"];
break;
}
}
}
?>
Live demo : https://eval.in/855386
Although it's unclear why you need to do a POST in this fashion, here's how to get "bob" only once:
<?php
$_POST = array("person" => array(
1 => array("id" => 1, "name" => "bob"),
2 => array("id" => 2, "name" => "jim")
)
);
$arr = array_pop($_POST);
foreach($arr as $a) {
if ($a["id"] == 1) {
echo $a["name"];
}
}
Array_pop() is useful for removing the first element of the array whose value is an array itself which looks like this:
array(2) {
[1]=>
array(2) {
["id"]=>
int(1)
["name"]=>
string(3) "bob"
}
[2]=>
array(2) {
["id"]=>
int(2)
["name"]=>
string(3) "jim"
}
}
When the if conditional evaluates as true which occurs only once then the name "bob" displays.
See live code.
Alternatively, you could use a couple of loops as follows:
foreach ($_POST["person"] as $data) {
foreach ($data as $value) {
if ( $value == 1) {
echo $data["name"],"\n";
}
}
}
See demo
As you mentioned, I want to be able to pick name from certain id, : No need of nested looping for that. You can do like this using array_column and array_search :
$data = array("person" => array(
1 => array("id" => 1, "name" => "bob"),
2 => array("id" => 2, "name" => "jim")
)
);
// 1 is id you want to search for
$key = array_search(1, array_column($data['person'], 'id'));
echo $data['person'][$key + 1]['name']; // $key + 1 as you have started array with 1
Output:
bob
with foreach:
foreach ($data as $dataValue) {
foreach ($dataValue as $person) {
if ($person['id'] === 1) {
echo $person["name"];
}
}
}

Third level of sub navigation php

I have the following code which works perfectly for producing a two tier navigation system, the problem is I have a requirement where one section has a third level of pages below it.
Edit: The code produces a two tier side navigation item that lists the pages in this section along with the parent item detailed at the top like so:
Page Title
Sub Page 1
Sub Page 2
Another Sub Page 1
Further Sub Page 1
Another Sub Page 1
Sub Page 3
There isn't any abnormal behaviour or error messages, it fails to display the further sub page 1 items in the list.
function insection_make_ul($tree, $level=0) {
$indent = str_repeat(" ", $level);
$result = "\n".$indent."<ul>\n";
foreach($tree as $id => $item) {
$result .= $indent."<li><a href=\"".$item['permalink']."\" class=\""
.($item['selected'] == true ? 'selected' : '')
.($level == 0 ? ' root' : '')."\" >" . $item['title']."</a>";
if(count(#$item['items'])) {
$result .= insection_make_ul($item['items'], ($level+1));
$result .= $indent."</li>\n";
}else{
$result .= "</li>\n";
}
}
$result .= $indent."</ul>\n";
return $result;
}
function insection($structure_id,$custom_selected=false){
$tree = insection_array($structure_id,$custom_selected);
return insection_make_ul($tree);
}
and the code to build the array
function insection_array($data,$custom_selected=false){
global $link;
if(is_numeric($data))
$data = fetch_row('SELECT * FROM content_structure WHERE id = '.$data);
$selected_id = $data['id'];
if($custom_selected) // dynamic item of 'real' parent
$selected_id .= '_'.$custom_selected;
$insection = array();
if($data['parent_id'] > 0){
if(HIDE_EMPTY_STRUCTURE){
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$data['id'].' AND visible = 1 AND in_menu = 1
AND (item_id > 0 OR redirect <> "")';
}else{
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$data['id'].' AND visible = 1 AND in_menu = 1';
}
$result = mysqli_query($link, $sql);
if(mysqli_num_rows($result) > 0 || $data['children_php'] != ''){
$parent_id = $data['id'];
}else{
$parent_id = $data['parent_id'];
}
}else{
$parent_id = $data['id'];
}
while($parent_id > 0){
$data = fetch_row('SELECT * FROM content_structure WHERE id = '.$parent_id);
$insection[$parent_id] = array('id' => $data['id'],
'title' => $data['menu_title'],
'permalink' => navlink($data),
'selected' => ($data['id'] == $selected_id ? true : false) );
if(HIDE_EMPTY_STRUCTURE){
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$parent_id.' AND visible = 1 AND in_menu = 1
AND (item_id > 0 OR redirect <> "") ORDER BY '
.($data['sort_auto'] == 1 ? 'menu_title' : 'sort_order');
}else{
$sql = 'SELECT * FROM content_structure WHERE parent_id = '.$parent_id.' AND visible = 1 AND in_menu = 1 ORDER BY '
.($data['sort_auto'] == 1 ? 'menu_title' : 'sort_order');
}
$result = mysqli_query($link, $sql);
if(!$result){ die('error: '.mysqli_error($link)); }
while($row = mysqli_fetch_assoc($result)){
$insection[$parent_id]['items'][$row['id']] = array('id' => $row['id'],
'title' => $row['menu_title'],
'permalink' => navlink($row),
'selected' => ($row['id'] == $selected_id ? true : false) );
}
// custom start
if($data['children_php'] != ''){ // custom sub items?
$sub_item_result = custom_navigation_array($data['children_php']);
foreach($sub_item_result as $sub_item){
$id = $data['id'].'_'.$sub_item['id']; // realparent_customid
$insection[$parent_id]['items'][$id] = array('id' => $id,
'title' => $sub_item['menu_title'],
'permalink' => $sub_item['href'],
'selected' => ($id == $selected_id ? true : false) );
}
}
//custom end
$parent_id = $data['parent_id'];
}
$insection = array_reverse($insection,true);
$temp = current($insection);
$root_id = #$temp['id'];
$insection_tree[$root_id] = current($insection);
$found_selected = false;
if(is_array(#$insection_tree[$root_id]['items'])){
foreach($insection_tree[$root_id]['items'] as $id => $item){
if(!empty($insection[$id])){
if($insection_tree[$root_id]['items'][$id]['selected'] == true)
$found_selected = true;
$insection_tree[$root_id]['items'][$id] = $insection[$id];
}
}
}
//if(!$found_selected){
// while(!$found_selected){
//
// }
//}
return $insection_tree;
}
Any pointers where I might get this working.
thanks
Personally I'd advise re-looking at your code. There is a lot of code there doing the same thing. Repetition is bad. As a helping hand, here's something to get you going.
Take this menu structure as an example but It's really upto you to produce this array yourself the main thing to notice is the function which will build the array into a <ul><li> string.
$menuItems = array(
array(// Top level items
"name" => "item1",
"subs" => array(// Second Level items
array(
"name" => "1a",
"href" => "something"
),
array(
"name" => "1b",
"subs" => array(// Third Level Items
array("name" => "1ba", "href" => "something"),
array("name" => "1bb", array(
array("name" => "1cca", "href" => "something"),
)
)
)
)
)
),
array(// Top level items
"name" => "item2",
"subs" => array(// Second Level items
array(
"name" => "2a",
"href" => "something"
),
array(
"name" => "2b",
"subs" => array(// Third Level Items
array("name" => "2ba", "href" => "something"),
array("name" => "2bb", array(
array("name" => "2cca", "href" => "something"),
)
)
)
)
)
)
);
$this->menuIterator($menuItems);
die();
The following logic is the important bit, it'll mean your menu could be any levels deep you want and it'll still produce the same result:
public function menuIterator($items) {
print "<ul>";
foreach ($items as $item) {
print "<li>";
print "<a>{$item['name']}</a>";
if (isset($item['subs'])) {
$this->menuIterator($item['subs']);
}
print "</li>";
}
print "</ul>";
return;
}
And the result is:
<ul><li><a>item1</a><ul><li><a>1a</a></li><li><a>1b</a><ul><li><a>1ba</a></li><li><a>1bb</a></li></ul></li></ul></li><li><a>item2</a><ul><li><a>2a</a></li><li><a>2b</a><ul><li><a>2ba</a></li><li><a>2bb</a></li></ul></li></ul></li></ul>

Multidimensional Array for() with different numbered elements levels

How would I write a foreach loop that would print off all information with the following multidimensional array without using any functions:
$workers = array(
"Natalie" => array
("First term" => array(
"Subworker" => "Susan",
"Length" => '1900-2000',
"Notes" => "Finished all tasks"),
"Second term" => array(
"Subworker" => "Laura",
"Length" => '1985-1986'),
),
"Laura" => array(
"First term" => array(
"Subworker" => "Sarah",
"Length" => '1999-1992'),
),
"Carolyn" => array(
"First term" => array(
"Subworker" => "Jenny",
"Length" => '1900 -1945',
"Notes" => array
("Finished all tasks",
"Did not finish all tasks",
"Completed partial tasks" )
),
),
"Jacob" => array(
"First term" => array(
"Subworker" => "Danielle",
"Length" => '1993-1994',
"Notes" => "Finished all tasks"),
),
"Jenny" => array(
"First term" => array(
"Subworker" => "Angela",
"Length" => '1999 - 2001'),
"Second term" => array(
"Subworker" => array(
"Paula" => "Let Go",
"Steve" => "Hired"),
"Length" => '1987 - 1999',
"Notes" => "Hired"),
)
);
/****So far I've done the following, but it is not printing out everything. For example, it is not printing out under Jenny, Second term, Subworker Paula and Steve./*****
foreach($workers as $worker => $value) {
foreach ($value as $newkey => $info) {
echo $worker.':<br>'.$newkey.':<br>';
foreach ($value as $newkey) {
echo 'Subworker: '.$newkey["Subkey"].'<BR>';
foreach ($value as $newkey) {
echo 'Length: '.$newkey["Length"].'<BR>';
foreach ($value as $newkey) {
echo 'Notes: '.$newkey["Notes"].'<BR>';
}
}
}
}
}
It is necessary to cross by a function and to make small tests upstream, it is always useful to avoid the return of error in environment of dev. :)
I have to add lists (ul, li) for better one reading
if (is_array($workers) && !empty($workers)) {
echo loopArray($workers);
} else {
echo "<ul><li>".$workers."</li></ul>";
}
function loopArray($array)
{
$result = "";
$result .= "<ul>";
foreach ($array as $item => $value) {
if (is_array($value) && !empty($value)) {
$result .= "<li>".$item;
$result .= loopArray($value)."</li>";
} else {
$result .= "<ul><li>".$item.': '.$value."</li></ul>";
}
}
$result .= "</ul>";
return $result;
}
To print the particular array you've provided, without using functions:
// workers
foreach($workers as $worker => $workerarr) {
echo $worker.":<ul>\n";
// worker terms
foreach ($workerarr as $term => $terminfo) {
echo "<li>$term:<ul>\n";
// term info
foreach ($terminfo as $type => $typevalue) {
echo "<li>$type: ";
// is type value an array?
if ( is_array($typevalue) ) {
// if so, put in list
echo "<ul>\n";
foreach ($typevalue as $label => $value) {
$label = is_int($label)? '': "$label: "; // only print text
echo "<li>$label$value</li>\n";
}
echo "</ul>";
}
// if not...
else {
echo $typevalue;
}
echo "</li>\n";
}
echo "</ul></li>\n";
}
echo "</ul>";
}
Using unordered lists to help display the information in a readable manner. To see with only break tags as in the question, see PHP Sandbox - Original
PHP Sandbox - Unordered Lists

How can I loop over this multi dimensional array?

So Im trying to loop over an array of categories and sub-categories but Im having trouble with the foreach loop. Once I've got the array working Im going to create a menu where if you hover over a category, sub categories appear.
Put it this way, Im hopeless at the logic side of things :|
This is my array along with the loops I've tried:
$categories = array(
'arr' => array(
'cat'=>'sport',
'subcats'=> array(
"surfing", "basketball", "nfl", "afl"
)
),
'arr' => array(
'cat'=>'Automotive',
'subcats'=> array(
"cars", "f1", "bikes", "etc"
)
),
'arr' => array(
'cat'=>'comedy',
'subcats'=> array(
"stand up", "pranks", "...", "test"
)
)
);
//Loop1
foreach ($categories as $key => $value) {
if($key == "arr"){
foreach ($key as $key => $value) {
echo $value;
if($key == "cat"){
echo "cat";
}
else{
echo $value;
}
}
// echo $key . "<br />";
// if($key == 'subcats'){
// echo "________".$key."<br />";
// }
}
}
//Attempt number 2
foreach ($categories as $key => $value) {
if($key == "arr"){
while($key){
echo $value;
if($key == "cat"){
echo $value;
}
if($key == "subcats"){
while($key){
echo $value[$key];
}
}
}
}
}
Updated code that I tried after this
This works okay but only problem is that it will only loop through the last arr=>array() and not any of the ones before.
$i=0;
foreach ($categories as $key => $value) {
if($key == "arr"){
foreach ($categories['arr'] as $sub => $val) {
if($sub == "cat"){
echo $val . " => ";
}
else if($sub == "subcats"){
for($i=0; $i<4; $i++){
echo $val[$i] . ", ";
}
}
}
}
}
If you can reorganize your array, you can stick the categories as keys, subcategories as values:
$categories = array(
'sport' => array(
"surfing", "basketball", "nfl", "afl"
),
'Automotive' => array(
"cars", "f1", "bikes", "etc"
),
'comedy' => array(
"stand up", "pranks", "...", "test"
)
);
// Here is an imploded list, you don't need a second loop then
foreach($categories as $cat => $subcat) {
echo "<h1>".$cat."</h1>";
echo '<ul>';
echo '<li>'.implode('</li>'.PHP_EOL.'<li>',$subcat).'</li>';
echo '</ul>';
}

Categories