I have a weather json from where I get a wether forecast for 8 days. My problem is that I want to show the result in a table of 2 rows of 4 days each.
I managed to do it but in a very odd way that was pure begginer's luck during a trial-error-trial attempt :-) I don't even understand quite well why it is splitting the result in 2 rows... but it works!!! The only thing I could not do was to include a "hr" line between the 2 rows, to make the table easier to read.
You can see the result here http://www.meteocaldas.com/previsao_ds.php
With current code I am displaying each day forecasted values inside the same "td" in different lines using "br". I have been reading that it is not correct to use "br" inside "td" so I am not sure that I am doing the righ thing. Wouldn't it be better to use a table with 4 columns (one for each day) and have different rows for each of the values?
Is there any way to rewrite this code to make it more efficient and look less "childish"? :-) Thanks in advance!
<?php
(...)
$decoded = json_decode($rawData, true);
?>
<table>
<?php for($k=0;$k<8;$k++){
$dailyvalue = $decoded['daily']['data'][$k];
$dailyTime = $dailyvalue['time'];
$dailyIcon = $dailyvalue['icon'];
$dailyTempMax = round($dailyvalue['temperatureMax'],0);
$dailyTempMin = round($dailyvalue['temperatureMin'],0);
(...)
?>
<!-- table for 8 day's forecast (2 rows/4 days each) -->
<td>
<?php echo strftime("%a %d",$dailyTime) ?>
<br>
<?php echo '<img src="path/'.$dailyIcon.'.png">' ?>
<br>
<?php echo $dailyTempMin.'º' ?> </span>
<br>
<?php echo $dailyTempMax.'º' ?></span>
<br>
(...)
<?php if ($k == 3) {
echo '</td></tr>';
} ?>
<?php
}
?>
</td></tr><table>
As per your comment-request, here's some sample-pseudo code, based on your code above:
<?php
(...)
$decoded = json_decode($rawData, true);
for($k=0;$k<8;$k++){
$dailyvalue = $decoded['daily']['data'][$k];
$dailyTime[$k] = $dailyvalue['time'];
$dailyIcon[$k] = $dailyvalue['icon'];
$dailyTempMax[$k] = round($dailyvalue['temperatureMax'],0);
$dailyTempMin[$k] = round($dailyvalue['temperatureMin'],0);
}
?>
<table>
<?php
echo "<tr>";
for($k = 0; $k <= 3; $k++){
echo "<td>".strftime("%a %d",$dailyTime[$k])."</td>"; // this will make the "datetime" row
}
echo "</tr><tr>";
for($k = 0; $k <= 3; $k++){
echo "<td><img src=path/".$dailyIcon[$k].".png></td>"; // this will make the "icon" row
}
echo "</tr><tr>";
for($k = 0; $k <= 3; $k++){
echo "<td>".$dailyTempMin[$k]."º</td>"; // this will make the "MinTemp" row
}
echo "</tr><tr>";
for($k = 0; $k <= 3; $k++){
echo "<td>".$dailyTempMax[$k]."º</td>"; // this will make the "MaxTemp" row
}
echo "</tr>";
// put stuff you want between the tables here
echo "<tr>";
for($k = 4; $k <= 7; $k++){
// proceed to do the same as above
Mind you, there are further ways you can reduce the screen clutter (like moving the table-drawing for loops into a function), but this is the general gist of it
Why don't you simply stack two different table on each other ?
What I want is the first loop iterating from 1 to 4 and the second loop from 5 to 6.
Here is my code:
<?php
for ($i = 1 ; $i <= 4 ; $i++)
{
echo $i . "<br>";
}
?>
<hr>
<?php
for ($i = 1 ; $i <= 2 ; $i++)
{
echo $i . "<br>";
}
?>
The loops you've given are:
1st loop: from 1 to 4
2nd loop: from 1 to 2
First loop is ok, but seconds needs to be modified. Use $i<=6 and don't initialize $i variable.
This will give you:
1st loop: from 1 to 4
2nd loop: from (value that 1st loop have ended)+1 to 6, so (4+1) to 6, 5 to 6
<?php
$i = 0; // be sure 'i' is visible in both loops
for ($i=1; $i<=4; $i++) // form 1 to 4
{
echo $i . "<br>";
}
?>
<hr>
<?php
$i++; // start from 5, not 4
for (; $i<=6; $i++) // from the previous value to 6
{
echo $i . "<br>";
}
?>
Your problem
The second for loop resets your $i variable to 1:
for ($i = 1 ; $i <= 2 ; $i++)
Solution
You can use a while loop instead of your second for loop:
<?php
for ($i = 1; $i <= 4; $i++)
{
echo $i . "<br>";
}
?>
<hr>
<?php
while ($i <= 6) // `<= 6` instead of `<= 2`, since we keep $1's value
{
echo $i . "<br>";
$i++;
}
?>
Rather than using two loops for this, why not just output the <hr> tag at the appropriate point within the same one? If you carry on with adding extra loops, first of all you'll run into confusing problems like this about (re-)initialising variables, and you'll also quickly end up with a lot of unnecessary duplicated code.
You can use the PHP modulo operator (%) to output the <hr> tag after every fourth element, which will both reduce the complexity and be a lot more extensible if you later add more elements:
for ($i=1; $i<=6; $i++) {
echo $i . "<br>";
if ($i % 4 === 0) {
echo "<hr>";
}
}
See https://eval.in/976102
I am stuck with this php loop. Then n = 3, k = 5, s = 21.
Can anyone help me please ?
Rows 3. In the first row 5 chairs:
1 row: ⑁⑁⑁⑁⑁ (5 chairs)
2 row: ⑁⑁⑁⑁⑁⑁⑁ (7 chairs)
3 row: ⑁⑁⑁⑁⑁⑁⑁⑁⑁ (9 chairs)
Chairs in total: 21
<?php
for ($i=0; $i<=6; $i++) {
for ($j=0; $j<$i; $j++) {
if($i == 1) {
echo '';
}else{
echo '⑁';
}
} echo ' ';
}
?>
If I understand correctly what you want,
$n is number of row you needed,
$k number of chair at row 1.
Each row chair is added by two.
<?php
$n = 3;
$k = 5;
for($i = 0; $i < $n; $i++) {
if($i >= 1) {
echo PHP_EOL;
}
echo str_repeat('-', $k + ($i * 2));
}
Example: When n = 3 and k = 8, it must be obtained that order s = 30 chairs.
Create a PHP solution that specifies the N-row queue in the variables, K-how many chairs should be in the first row.
For example: N = 3; K = 5;
After loading the page (after performing the program actions with the variables available) the following should be displayed:
Rows 3. First row 5 chairs:
Queue 1: ⑁⑁⑁⑁⑁ (5 chairs)
Queue 2: ⑁⑁⑁⑁⑁⑁⑁ (7 chairs)
Queue 3: ⑁⑁⑁⑁⑁⑁⑁⑁⑁ (9 chairs)
Total required chairs: 21
I think you want to use 'if' syntax. Is it right?
If it's not correct, You should describe your work more detail
<?php
// ...
for($i = 0; $i< sizeof($rows); $i++ ){
if ($i % 2 == 0) {
print "It's even";
}
}
// ... If a row is an Array, use this one.
for($i = 0; $i< sizeof($rows); $i++ ){
for($j = 0; $j< sizeof($rows[$i]); $j++ ){
if ($j % 2 == 0) {
print "It's even index of a row";
//do Something.
}
}
}
?>
I have a MySQL query that I am saving to a variable to output on the page. I have the data in an unordered list, but I am trying to split the data into three columns using 3 unordered lists floated left. Here is my current code:
$sqlCommand =
"SELECT list_specialty.id, list_specialty.specialty FROM list_specialty
ORDER BY list_specialty.specialty ASC";
$query = mysqli_query($myConnection,$sqlCommand) or die (mysqli_error($myConnection));
$specialtyDisplay = '';
$num = mysqli_num_rows($query);
$split = intval($num/3); //number of items in every column
$i = 0;
while ($row = mysqli_fetch_array($query)) {
$specialtyid = $row["id"];
$specialtyname = $row["specialty"];
$specialtyDisplay .=
'<li>' . $specialtyname . '</li>';
$i++;
if ($i == $split) {
$specialtyDisplay .= '</ul> <ul>';
$i = 0;
}
}
This code works GREAT as long as my data is exactly divisible by 3 (equal columns).
However, when my total number of rows is not divisible by 3, the above code won't work.
I need a solution that will balance the columns, so I can have either 3 equal columns, one extra element in the first column, or one extra element in the first and second column.
What do I need to change in my code to account for that?
This will work:
set $split to the length of the longest column
rows have 0, 1 or 2 columns that are longer by one element. -> $longcols = $num % 3
substract 1 from $split when column number $longcols is printed (unless all columns have equal length)
Implemented in the code:
$num = mysqli_num_rows($query);
$split = ceil($num/3); // 1.
$i = 0;
$col = 1; //for counting columns
$longcols = $num % 3; // 2.
while ($row = mysqli_fetch_array($query)) {
$specialtyid = $row["id"];
$specialtyname = $row["specialty"];
$specialtyDisplay .=
'<li>' . $specialtyname . '</li>';
$i++;
if ($i == $split) {
$specialtyDisplay .= '</ul> <ul>';
if( $longcols != 0 && $longcols == $col ) { $split--; } // 3.
$i = 0;
$col++; //increase columns count
}
}
The lines with comments are those that I have changed/inserted.
If you are going to support better browsers, you can use CSS 3 Multicolumns. It doesn't require you to split. Just CSS does the magic.
div#multicolumn {
-moz-column-count: 3;
-moz-column-gap: 20px;
-webkit-column-count: 3;
-webkit-column-gap: 20px;
column-count: 3;
column-gap: 20px;
}
Screenshot:
CSS3 MultiColumn http://css.flepstudio.org/images/css3/css3-multi-column.jpg
I have the following arrays:
$artist = array("the roots", "michael jackson", "billy idol", "more", "and more", "and_YET_MORE");
$count = array(5, 3, 9, 1, 1, 3);
I want to generate a tag cloud that will have artists with a higher number in $count enclosed in h6 tags and the lowest enclosed h1 tags.
You will want to add a logarithmic function to it too. (taken from tagadelic, my Drupal module to create tag clouds http://drupal.org/project/tagadelic):
db_query('SELECT COUNT(*) AS count, id, name FROM ... ORDER BY count DESC');
$steps = 6;
$tags = array();
$min = 1e9;
$max = -1e9;
while ($tag = db_fetch_object($result)) {
$tag->number_of_posts = $tag->count; #sets the amount of items a certain tag has attached to it
$tag->count = log($tag->count);
$min = min($min, $tag->count);
$max = max($max, $tag->count);
$tags[$tag->tid] = $tag;
}
// Note: we need to ensure the range is slightly too large to make sure even
// the largest element is rounded down.
$range = max(.01, $max - $min) * 1.0001;
foreach ($tags as $key => $value) {
$tags[$key]->weight = 1 + floor($steps * ($value->count - $min) / $range);
}
Then in your view or template:
foreach ($tags as $tag) {
$output .= "<h$tag->weight>$tag->name</h$tag->weight>"
}
Off the top of my head...
$artist = array("the roots","michael jackson","billy idol","more","and more","and_YET_MORE");
$count = array(5,3,9,1,1,3);
$highest = max($count);
for (int $x = 0; $x < count($artist); $x++)
{
$normalized = $count[$x] / $highest;
$heading = ceil($normalized * 6); // 6 heading types
echo "<h".$heading.">".$artist[$x]."</h".$heading.">";
}
Perhaps this is a little academic and off topic but hX tags are probably not the best choice for a tag cloud for reasons of document structure and all that sort of thing.
Maybe spans or an ol with appropriate class attributes (plus some CSS)?
Have used this snippet for a while, credit is prism-perfect.net. Doesn't use H tags though
<div id="tags">
<div class="title">Popular Searches</div>
<?php
// Snippet taken from [prism-perfect.net]
include "/path/to/public_html/search/settings/database.php";
include "/path/to/public_html/search/settings/conf.php";
$query = "SELECT query AS tag, COUNT(*) AS quantity
FROM sphider_query_log
WHERE results > 0
GROUP BY query
ORDER BY query ASC
LIMIT 10";
$result = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
$tags[$row['tag']] = $row['quantity'];
}
// change these font sizes if you will
$max_size = 30; // max font size in %
$min_size = 11; // min font size in %
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
$spread = 1;
}
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
// loop through our tag array
foreach ($tags as $key => $value) {
// calculate CSS font-size
// find the $value in excess of $min_qty
// multiply by the font-size increment ($size)
// and add the $min_size set above
$size = $min_size + (($value - $min_qty) * $step);
// uncomment if you want sizes in whole %:
// $size = ceil($size);
// you'll need to put the link destination in place of the /search/search.php...
// (assuming your tag links to some sort of details page)
echo '<a href="/search/search.php?query='.$key.'&search=1" style="font-size: '.$size.'px"';
// perhaps adjust this title attribute for the things that are tagged
echo ' title="'.$value.' things tagged with '.$key.'"';
echo '>'.$key.'</a> ';
// notice the space at the end of the link
}
?>
</div>
#Ryan
That's correct but it actually makes the tags with the least number, larger. This code has been tested:
$artist = array("the roots","michael jackson","billy idol","more","and more","and_YET_MORE");
$count = array(5,3,9,1,1,3);
$highest = max($count);
for ($x = 0; $x < count($artist); $x++) {
$normalized = ($highest - $count[$x]+1) / $highest;
$heading = ceil($normalized * 6); // 6 heading types
echo "<h$heading>{$artist[$x]}</h$heading>";
}
This method is for SQL/PostgreSQL fanatics. It does the entire job in the database, and it prints text with "slugified" link. It uses Doctrine ORM just for the sql call, I'm not using objects.
Suppose we have 10 sizes:
public function getAllForTagCloud($fontSizes = 10)
{
$sql = sprintf("SELECT count(tag) as tagcount,tag,slug,
floor((count(*) * %d )/(select max(t) from
(select count(tag) as t from magazine_tag group by tag) t)::numeric(6,2))
as ranking
from magazine_tag mt group by tag,slug", $fontSizes);
$q = Doctrine_Manager::getInstance()->getCurrentConnection();
return $q->execute($sql);
}
then you print them with some CSS class, from .tagranking10 (the best) to .tagranking1 (the worst):
<?php foreach ($allTags as $tag): ?>
<span class="<?php echo 'tagrank'.$tag['ranking'] ?>">
<?php echo sprintf('<a rel="tag" href="/search/by/tag/%s">%s</a>',
$tag['slug'], $tag['tag']
); ?>
</span>
<?php endforeach; ?>
and this is the CSS:
/* put your size of choice */
.tagrank1{font-size: 0.3em;}
.tagrank2{font-size: 0.4em;}
.tagrank3{font-size: 0.5em;}
/* go on till tagrank10 */
This method displays all tags. If you have a lot of them, you probably don't want your tag cloud to become a tag storm. In that case you would append an HAVING TO clause to your SQL query:
-- minimum tag count is 8 --
HAVING count(tag) > 7
That's all
I know it's a very old post, still I'm posting my view as it may help someone in future.
Here is the tagcloud I used in my website:
http://www.vbausefulcodes.in/
<?php
$input= array("vba","macros","excel","outlook","powerpoint","access","database","interview questions","sendkeys","word","excel projects","visual basic projects","excel vba","macro","excel visual basic","tutorial","programming","learn macros","vba examples");
$rand_tags = array_rand($input, 5);
for ($x = 0; $x <= 4; $x++) {
$size = rand ( 1 , 4 );
echo "<font size='$size'>" . $input[$rand_tags[$x]] . " " . "</font>";
}
echo "<br>";
$rand_tags = array_rand($input, 7);
for ($x = 0; $x <= 6; $x++) {
$size = rand ( 1 , 4 );
echo "<font size='$size'>" . $input[$rand_tags[$x]] . " " . "</font>";
}
echo "<br>";
$rand_tags = array_rand($input, 5);
for ($x = 0; $x <= 4; $x++) {
$size = rand ( 1 , 4 );
echo "<font size='$size'>" . $input[$rand_tags[$x]] . " " . "</font>";
}
?>
As a helper in Rails:
def tag_cloud (strings, counts)
max = counts.max
strings.map { |a| "<span style='font-size:#{((counts[strings.index(a)] * 4.0)/max).ceil}em'>#{a}</span> " }
end
Call this from the view:
<%= tag_cloud($artists, $counts) %>
This outputs <span style='font-size:_em'> elements in an array that will be converted to a string in the view to ultimately render like so:
<span style='font-size:3em'>the roots</span>
<span style='font-size:2em'>michael jackson</span>
<span style='font-size:4em'>billy idol</span>
<span style='font-size:1em'>more</span>
<span style='font-size:1em'>and more</span>
<span style='font-size:2em'>and_YET_MORE</span>
It would be better to have a class attribute and reference the classes in a style sheet as mentioned by Brendan above. Much better than using h1-h6 semantically and there's less style baggage with a <span>.