How can I do a foreach loop using php dictionaries? - php

I am trying to make a php navbar sort of thing. I have the html code and what I want to do is to use a php dictionary ("Home"=>"http://www.domain.com/") and turn it into html code.

<ul>
<?php foreach ($links as $title => $url): ?>
<li><?php echo htmlentities($title); ?></li>
<?php endforeach; ?>
</ul>

foreach($arr as $key=>$value) {
// your code here
}
I have no idea how you want to make your navbar, but with any knowledge of HTML you should be able to go from here.

foreach (dict as $key => $value){
echo "<a href='$value'>$key</a>";
}

Fastest
<?php
foreach($array as $name => $link){
echo '',$name,'\n';
}
?>
Easier to read and understand but slower
<?php
foreach($array as $name => $link){
echo "<a href='$link'>$name</a>\n";
}
?>

I don't know if i understand the question but you can use an hash like this:
<?php
$navBar = array(
"Home" => "http://www.domain.com/",
"Info" => "http://www.domain.com/info/",
);
foreach($navBar as $key => $val){
echo "<li>$key => $val<li>";
}
?>

Related

Loop with curly brackets causes wrong output

I created 2 simple examples:
First example:
<?php $arr = array(1,2,3,4,5); ?>
<?php foreach ($arr as $element) ?>
<?php { ?>
<?php echo $element; ?>
<?php } ?>
output:
5 //Is this result wrong?
Second example:
<?php $arr = array(1,2,3,4,5); ?>
<?php foreach ($arr as $element) { ?>
<?php echo $element; ?>
<?php } ?>
output:
12345
What did I miss about the PHP syntax?
I know that there is an alternative foreach syntax, but in my opinion both shown examples should result in the same output. (Code tested with PHP version: 5.6.12)
Edit:
I know the tags are not needed in every line.
To be more precise: I want to know why the two examples give me 2 different results?
Based on the output, my guess is that:
<?php $arr = array(1,2,3,4,5); ?>
<?php foreach ($arr as $element) ?>
<?php { ?>
<?php echo $element; ?>
<?php } ?>
is being interpreted as:
<?php
$arr = array(1,2,3,4,5);
foreach ($arr as $element);
{
echo $element;
}
?>
Looks like a bug in the interpreter? See comments by Rizier123:
Not a bug: stackoverflow.com/q/29284075/3933332
The brackets after the foreach()/Do nothing here/; is just a statement-group: php.net/manual/en/control-structures.intro.php
Anyways, the code looks atrocious with the way you have written it. Please opt for cleaner code.
Reading through the comments under the question I think Jon Stirling explain this symptom the best:
Just guessing, but perhaps the ?> in the first example is actually being taken as the statement end (loops can be used without braces). At that point, the loop has happened and $element is the last value. Then the braces are just take as a code block which you echo, which is 5.
Over using <? php> is your problem.
You are completing the foreach context before outputting the result and not doing that in the second.
Look at your examples carefully and you should see what you are doing differently.
I don't know why you use so many php tags, but that's why it doesn't work!
try this:
<?php $arr = array(1,2,3,4,5);
foreach ($arr as $element)
{
echo $element;
} ?>
You don't need to use <?php and ?> every single line simply do:
<?php
$arr = array(1,2,3,4,5);
foreach ($arr as $element) {
echo $element;
}
?>
Or alternative syntax:
<?php
$arr = array(1,2,3,4,5);
foreach ($arr as $element)
{
echo $element;
}
?>
Or
<?php
$arr = array(1,2,3,4,5);
foreach ($arr as $element):
echo $element;
endforeach;
?>
When you are doing this:
<?php foreach ($arr as $element) ?>
<?php { ?>
<?php echo $element; ?>
<?php } ?>
PHP loops nothing because it sees
foreach ($arr as $element)
{
}
echo $element;

Output All Currency Values using PHP

I am trying to utilize the Bitcoin Charts API to display bitcoin value in all currencies as list items.
Currently I am repeating this PHP snippet in each list item:
<li class="myClass">
<?php
foreach(json_decode(file_get_contents("http://api.bitcoincharts.com/v1/markets.json")) as $item)
if($item->symbol == 'localbtcPLN') break;
printf("\t%s\nPLN", $item->avg);
?>
</li>
How can I simplify this so that the code is only calling the JSON file once?
Thanks for your help.
As per Vishal's assistance, I tried this:
<?php $all_data = json_decode(file_get_contents("http://api.bitcoincharts.com/v1/markets.json"),true);
foreach ($all_data as $data)
{
?><li class="pure-menu-item pure-menu-disabled">
<?php
echo $data['ask'];//use the keyname to get the value
echo ' ';
echo $data['currency'];
?>
</li>
<?php
}
?>
However, it is outputting too much data, including empty values.
Using what I've learned from Florian and Vishal, I have attempted the following snippet, which outputted the data perfectly with the caveat of some duplicated currencies.
<?php $all_data = json_decode(file_get_contents("http://api.bitcoincharts.com/v1/markets.json"),true);
foreach ($all_data as $data)
{
if(trim($data['avg']) != "")//check if value not empty
{
?><li class="pure-menu-item pure-menu-disabled">
<?php
echo $data['avg']; //use the keyname to get the value
echo ' ';
echo $data['currency'];
?>
</li>
<?php
}
}
?>
you can run a foreach loop
<ol>
<?php $all_data = json_decode(file_get_contents("http://api.bitcoincharts.com/v1/markets.json"),true);
foreach ($all_data as $data)
{
if(trim($data['currency']) != "")//check if value not empty
{
?><li>
<?php echo $data['bid'];//use the keyname to get the value ?>
</li>
<?php
}
}
?>
</ol>
I think you want to show values in a certain order.
First, store the result of json_decode() in an array like #Vishal Wadhawan said.
$all_data = json_decode(file_get_contents("http://api.bitcoincharts.com/v1/markets.json"),true);
Next, make a new array where you will store only symbol and avg:
$myvalues = array();
foreach ($all_data as $data)
{
$myvalues[$data['symbol']] = $data['avg'];
}
After that, you can use $myvalues to display avg like that:
<li class="myClass">
<?php echo $myvalues['localbtcPLN'] . ' PLN'; ?>
</li>
You can also store the 'currency' value:
$myvalues[$data['symbol']] = array(
'avg' => $data['avg'],
'currency' => $data['currency'],
);
And access it with:
<li class="myClass">
<?php echo $myvalues['localbtcPLN']['avg'] . ' ' . $myvalues['localbtcPLN']['currency']; ?>
</li>

Format my JSON string into an <ol> ordered list in PHP

I'm working on a simple CMS for a pet project. I currently have a JSON string that contains a list of page ID's and Parent page ID's for a menu structure.
I want to now convert this string into a nested or hierarchical list (ordered list).
I've tried looking looping through but seem to have ended up with an overly complex range of sub classes. I'm struggling to find a suitable light-weight solution in PHP.
Here's the JSON:
**[{"id":3,"children":[{"id":4,"children":[{"id":5}]}]},{"id":6},{"id":2},{"id":4}]**
Here's the desired output:
<ol>
<li>3
<ol>
<li>4</li>
<ol>
<li>5</li>
</ol>
</ol>
</li>
<li>6</li>
<li>2</li>
<li>4</li>
</ol>
Is there anything built in to PHP that can simplify this process? Has anyone had any experience of this before?
I'm a newbie to PHP and SE. Looking forward to hearing from you.
Here's my current progress (it's not working too well)
<ol>
<?php
$json = '[{"id":3,"children":[{"id":4,"children":[{"id":5}]}]},{"id":6},{"id":2},{"id":4}]';
$decoded = json_decode($json);
$pages = $decoded;
foreach($pages as $page){
$subpages = $decoded->children;
echo "<li>".$page->id."</li>";
foreach($subpages as $subpage){
echo "<li>".$subpage->id."</li>";
}
}
?>
</ol>
You can use recursion to get deep inside the data. If the current value is an array then recursion again. Consider this example:
$json_string = '[{"id":3,"children":[{"id":4,"children":[{"id":5}]}]},{"id":6},{"id":2},{"id":4}]';
$array = json_decode($json_string, true);
function build_list($array) {
$list = '<ol>';
foreach($array as $key => $value) {
foreach($value as $key => $index) {
if(is_array($index)) {
$list .= build_list($index);
} else {
$list .= "<li>$index</li>";
}
}
}
$list .= '</ol>';
return $list;
}
echo build_list($array);
Using a function that can recursively go through your JSON, you can get the functionality you wish. Consider the following code: (this only accounts for an attribute of id as getting listed, as your desired code shows)
$json = '[{"id":3,"children":[{"id":4,"children":[{"id":5}]}]},{"id":6},{"id":2},{"id":4}]';
function createOLList($group) {
$output = (is_array($group)) ? "<ol>" : "";
foreach($group as $attr => $item) {
if(is_array($item) || is_object($item)) {
$output .= createOLList($item);
} else {
if($attr == "id") {
$output .= "<li>$item</li>";
}
}
}
$output .= (is_array($group)) ? "</ol>" : "";
return $output;
}
print(createOLList(json_decode($json)));
This will produce the following HTML output.
<ol>
<li>3</li>
<ol>
<li>4</li>
<ol>
<li>5</li>
</ol>
</ol>
<li>6</li>
<li>2</li>
<li>4</li>
</ol>
What you're looking for is called recursion, which can be done by a function calling itself.
If you solved once to list all nodes of the list in one function, you can then apply the same function for all child-lists. As then those child-lists will do the same on their children, too.
call_user_func(function ($array, $id = 'id', $list = 'children') {
$ul = function ($array) use (&$ul, $id, $list) {
echo '<ul>', !array_map(function ($child) use ($ul, $id, $list) {
echo '<li>', $child[$id], isset($child[$list]) && $ul($child[$list])
, '</li>';
}, $array), '</ul>';
};
$ul($array);
}, json_decode('[{"id":3,"children":[{"id":4,"children":[{"id":5}]}]},{"id":6},
{"id":2},{"id":4}]', TRUE));
As this example shows, the $ul function is called recursively over the list and all children. There are other solutions, but most often recursion is a simple method here to get the job done once you've wrapped your head around it.
Demo: https://eval.in/153471 ; Output (beautified):
<ul>
<li>3
<ul>
<li>4
<ul>
<li>5</li>
</ul>
</li>
</ul>
</li>
<li>6</li>
<li>2</li>
<li>4</li>
</ul>
<?php
$json_array = array();
array_push($json_array, array(
'id' => 3,
'children' => array(
'id' => 4,
'children' => array(
'id' => 5,
)
)
));
array_push($json_array, array('id' => 6));
array_push($json_array, array('id' => 2));
array_push($json_array, array('id' => 4));
//your json object
$json_object = json_encode($json_array);
//echo $json_object;
//here is where you decode your json object
$json_object_decoded = json_decode($json_object,true);
//for debug to see how your decoded json object looks as an array
/*
echo "<pre>";
print_r($json_object_decoded);
echo "</pre>";
*/
echo "<ol>";
foreach($json_object_decoded as $node){
if(isset($node['id'])){
echo "<li>" . $node['id'];
if(isset($node['children'])){
echo "<ol>";
echo "<li>" . $node['children']['id'] . "</li>";
if(isset($node['children'])){
echo "<ol>";
echo "<li>" . $node['children']['children']['id'] . "</li>";
echo "</ol>";
}
echo "</ol>";
}
echo "</li>";
}
}
echo "</ol>";
?>
I have found that i have to fix or simplify almost every of the functions above.
So here i came with something simple and working, still recursion.
function build_list($array) {
$list = '<ul>';
foreach($array as $key => $value) {
if (is_array($value)) {
$list .= "<strong>$key</strong>: " . build_list($value);
} else {
$list .= "<li><strong>$key</strong>: $value</li>";
}
}
$list .= '</ul>';
return $list;
}
build_list(json_encode($json_string),true);

Current menu item - foreach

Consider this:
$menuItems = array (
"page1" => "1.php",
"page2" => "2.php",
"page3" => "3.php",
"page4" => "4.php",
"page5" => "5.php",
);
and now I create the menu like this:
<ul class="menu">
<?php
foreach($menuItems as $name => $url) {
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
?>
</ul>
Works great. But now I need to add a class .current on the current page.
To get the current page I do this:
<?php
function curPageName() {
return substr($_SERVER["SCRIPT_NAME"],strrpos($_SERVER["SCRIPT_NAME"],"/")+1);
}
$curpage = curPageName();
?>
And it also works great.
SO I guess the question is how do I assign $curpage to the ... current page? :)
Thank you.
Alex
<ul class="menu">
<?php
foreach($menuItems as $name => $url) {
if ($url === $curpage){
$class.=' .current';
}
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
?>
</ul>
Easy, inside your loop, check if $url == $curpage, and append appropriately.
Example:
<?php
$menuItems = array(
"page1" => "1.php",
"page2" => "2.php",
"page3" => "3.php",
"page4" => "4.php",
"page5" => "5.php",
);
$current_item = "2.php"; //Assume we got this from the function
?>
<ul class="menu">
<?php
foreach ($menuItems as $name => $url) {
echo "<li><a href='$url'";
if ($url == $current_item) {
echo " class='current'";
}
echo ">$name</a></li>\n";
}
?>
</ul>
<ul class="menu">
<?php
foreach($menuItems as $name => $url) {
$class = 'default';
if (curPageName() == $name) {
$class.='.current';
}
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
?>
</ul>
So I made it work with your help! Thanks guys.
Special thanks for Adel - although you had a mistake there I fixed it like this:
foreach($menuItems as $name => $url) {
$class = 'default';
if (curPageName() == $url) {
$class.=' \. current';
}
echo "<li><a href='$url' class='$class'>$name</a></li>";
}
Awesome! Thanks again!
<?php
$menuItems = array(
'page1' => '1.php',
'page2' => '2.php',
'page3' => '3.php',
'page4' => '4.php',
'page5' => '5.php',
);
$current_page = curPageName();
?>
<ul class="menu">
<?php
foreach ($menuItems as $name => $url) {
?>
<li><a href="<?php=$url?>"
<?php
if ($url == $current_page) {
?>
class="current"
<?php
}
?>
><?php=$name?></a></li>
<?php
}
?>
</ul>
Why use the curPageName () at each iteration?
You can use a ternary syntax to solve your problem. It consists in this syntax:
(if condition ? true : false)
So we can use this way on your answer comparing the curPageName with the url inside the foreach loop.
$url == curPageName() ? 'current' : 'notCurrent'
Now you just need to use this in your favor.
I like the syntax of printf. So the code is more clean. Try this:
<?php
/**
* curPageName() is defined in question
* my_links() is a shortcut to array defined in question
*/
$template = "<li%s>%s</li>";
$links = my_links();
$current = curPageName();
print '<ul class="menu">';
foreach ($likns as $name => $url) {
$class = $current == $url ? ' class="current"' : '';
printf($template, $class, $url, $name);
}
print '</ul>';
Each %s item in $template will be changed by sequential variable. So, if you need to change the template the code is clean and easyest to give a maintance.
Or, if you want another easiest template way, use the php template syntax. Note the use of : after the foreach statement and the use of endforeach. You can see that I am using the short code of echo <?=$var?> that is more compreensible than <?php echo $var ?>.
<?php
/**
* curPageName() is defined in question
* my_links() is a shortcut to array defined in question
*/
$links = my_links();
$current = curPageName();
?>
<ul class="menu">
<?php foreach ($links as $name => $url): ?>
<li<?=($current == $url ? ' class="current"' : '')?>>
<?=$name?>
</li>
<?php endforeach ?>
</ul>

PHP Array to List

How do I go from this multidimensional array:
Array (
[Camden Town] => Array (
[0] => La Dominican
[1] => A Lounge
),
[Coastal] => Array (
[0] => Royal Hotel
),
[Como] => Array (
[0] => Casa Producto
[1] => Casa Wow
),
[Florence] => Array (
[0] => Florenciana Hotel
)
)
to this:
<ul>
<li>Camden Town</li>
<ul>
<li>La Dominican</li>
<li>A Lounge</li>
</ul>
<li>Coastal</li>
<ul>
<li>Royal Hotel</li>
</ul>
...
</ul>
above is in html...
//code by acmol
function array2ul($array) {
$out = "<ul>";
foreach($array as $key => $elem){
if(!is_array($elem)){
$out .= "<li><span>$key:[$elem]</span></li>";
}
else $out .= "<li><span>$key</span>".array2ul($elem)."</li>";
}
$out .= "</ul>";
return $out;
}
I think you are looking for this.
Here's a much more maintainable way to do it than to echo html...
<ul>
<?php foreach( $array as $city => $hotels ): ?>
<li><?= $city ?>
<ul>
<?php foreach( $hotels as $hotel ): ?>
<li><?= $hotel ?></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
Here's another way using h2s for the cities and not nested lists
<?php foreach( $array as $city => $hotels ): ?>
<h2><?= $city ?></h2>
<ul>
<?php foreach( $hotels as $hotel ): ?>
<li><?= $hotel ?></li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
The outputted html isn't in the prettiest format but you can fix that. It's all about whether you want pretty html or easier to read code. I'm all for easier to read code =)
Refactored acmol's funciton
/**
* Converts a multi-level array to UL list.
*/
function array2ul($array) {
$output = '<ul>';
foreach ($array as $key => $value) {
$function = is_array($value) ? __FUNCTION__ : 'htmlspecialchars';
$output .= '<li><b>' . $key . ':</b> <i>' . $function($value) . '</i></li>';
}
return $output . '</ul>';
}
Assume your data is in $array.
echo '<ul>';
foreach ($array as $city => $hotels)
{
echo "<li>$city</li>\n<ul>\n";
foreach ($hotels as $hotel)
{
echo " <li>$hotel</li>\n";
}
echo "</ul>\n\n";
}
echo '</ul>';
Haven't tested it, but I'm pretty sure it's right.

Categories