I require a nested for loop for my php website which gives me results as follows.
I want to two integers incrementally - one stops at 12 and other continues until the specified values.
If one string is $i and second string is $j than I want output as:
$i 1 2 3 4 5 6 7 8 9 10 11 12
$j 1 2 3 4 5 6 7 8 9 10 11 12
$i 1 2 3 4 5 6 7 8 9 10 11 12
$j 13 14 15 16 17 18 19 20 21 22 23 24
$i 1 2 3 4 5 6 7 8 9 10 11 12
$j 25 26 27 28 29 30 31 32 33 34 35 36
It should be repeated up to n values.
You can try this:
<?php
createMatrix(40);
function createMatrix($jMax)
{
$jVal = 0;
while ($jVal < $jMax) {
// print line $i
echo ('$i' . "\t");
for ($iVal = 1; $iVal <= 12; $iVal++) {
echo "$iVal\t";
}
echo "\n";
// print line $j
echo ('$j' . "\t");
for ($j = 1; $j <= 12; $j++) {
$jVal++;
echo "$jVal\t";
if ($jVal === $jMax) {
echo "\n";
break;
}
}
echo "\n";
}
}
OUTPUT:
I am currently generating an html table which contains dates in it's header
Those dates are the supposedly first days of each week through the whole year (the displayed year may change according to a filter), and they are generated by the following code
<?php $firstDay = strtotime($year . 'W' . str_pad($week, 2, '0', STR_PAD_LEFT)); ?>
<td><?= date('d/m/Y', $firstDay) ?></td>
This is inside a for loop that makes the $week go from 1 to the number of weeks in the whole year.
What I have noticed is that for some years, the last monday of December from the previous year is included in there too, such as 29/12/2014 when I select 2015 in the filter.
So far, to determine the number of weeks that are in a month, I used to count the number of mondays in said month programmatically and used it as the colspan for the row above the dates row, and so, there are uncounted weeks for january for some years, which makes the table shift.
The rendered html for the year 2015 would look like this
<table>
<thead>
<tr>
<th colspan="4">January</th>
<th colspan="4">February</th>
[...]
</tr>
<tr>
<!-- Under January cell -->
<th>29/12/2014</th>
<th>05/01/2015</th>
<th>12/01/2015</th>
<th>19/01/2015</th>
<!-- Under February cell -->
<th>26/01/2015</th>
<th>02/02/2015</th>
[...]
</tr>
</thead>
[...]
And after searching and testing a lot of week per month counters, none of those that I found seem to include that last monday from the previous year.
Could anyone find out how to count the weeks including that extra week from the previous year when it occurs?
The number of weeks falling in a given month is basically the number of days in a month, plus an offset that depends on which day of a week the month started in, divided by 7. Here is a solution using DateInterval and DatePeriod:
/**
* Get number of weeks starting *Monday*, occuring in a given month.
* A week occurs in a month if any day from that week falls in the month.
* #param $month_date is expected to be DateTime.
* #param $count_last count partial week at the end of month as part of month.
*/
function weeks_in_month($month_date, $count_last=true) {
$fn = $count_last ? 'ceil' : 'floor';
$start = new DateTime($month_date->format('Y-m'));
$days = (clone $start)->add(new DateInterval('P1M'))->diff($start)->days;
$offset = $month_date->format('N') - 1;
return $fn(($days + $offset)/7);
}
/**
* Wrapper over weeks_in_month() to get weeks in month for each month of a given year.
* #param $year_date is expected to be a DateTime.
*/
function year_month_weeks($year_date, $count_last=true) {
$start = new DateTime($year_date->format('Y') . '-01');
$year_month_weeks = [];
foreach(new DatePeriod($start, new DateInterval('P1M'), 11) as $month) {
$year_month_weeks[] += weeks_in_month($month, $count_last);
}
return $year_month_weeks;
}
print_r(year_month_weeks(new DateTime('2008-01'), true));
Gives:
Array
(
[0] => 5
[1] => 5
[2] => 6
[3] => 5
[4] => 5
[5] => 6
[6] => 5
[7] => 5
[8] => 5
[9] => 5
[10] => 5
[11] => 5
)
This can be validated against output of cal. For the first 6 months of 2008 should have 6 weeks in March, Jun, 5 for the rest:
>ncal -Mb -m 1 -A 5 2008
2008
January February March
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 1 2 3 1 2
7 8 9 10 11 12 13 4 5 6 7 8 9 10 3 4 5 6 7 8 9
14 15 16 17 18 19 20 11 12 13 14 15 16 17 10 11 12 13 14 15 16
21 22 23 24 25 26 27 18 19 20 21 22 23 24 17 18 19 20 21 22 23
28 29 30 31 25 26 27 28 29 24 25 26 27 28 29 30
31
April May June
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 1 2 3 4 1
7 8 9 10 11 12 13 5 6 7 8 9 10 11 2 3 4 5 6 7 8
14 15 16 17 18 19 20 12 13 14 15 16 17 18 9 10 11 12 13 14 15
21 22 23 24 25 26 27 19 20 21 22 23 24 25 16 17 18 19 20 21 22
28 29 30 26 27 28 29 30 31 23 24 25 26 27 28 29
30
Recently did a listing quite simliar with Carbon.
Here a Snipped with some example output:
<?php
use Carbon\Carbon;
$counter = Carbon::createFromDate(2018, 1, 1);
$end = $counter->copy()->endOfYear();
$months = [];
for (; $counter <= $end; $counter->addWeek()) {
// just to avoid E_NOTICE
if (!isset($months[$counter->month])) {
$months[$counter->month] = [
'count' => 0,
'weekstarts' => [],
];
}
++$months[$counter->month]['count'];
$months[$counter->month]['weekstarts'][] = $counter->copy();
}
foreach ($months as $month) {
printf('Month has %d weeks', $month['count']);
echo PHP_EOL;
foreach ($month['weekstarts'] as $num => $weekStartDate) {
printf('Week %d starts at %s', $num + 1, $weekStartDate);
echo PHP_EOL;
}
echo PHP_EOL;
}
So, this was my turnaround, using the function used to generate the first days of each week
function getIsoWeeksInYear($year) {
$date = new DateTime;
$date->setISODate($year, 53);
return ($date->format("W") === "53" ? 53 : 52);
}
function getWeeksPerMonth($year) {
$allWeeks = $this->getIsoWeeksInYear($year);
$allFirstDays = [];
for ($i = 0; $i < $allWeeks; $i++) {
$allFirstDays[] = date('m/Y', strtotime($year . "W" . str_pad($i, 2, "0", STR_PAD_LEFT)));
}
$countWeek = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
foreach ($allFirstDays as $firstDay) {
$theMonth = explode('/', $firstDay);
for ($i = 1; $i < 13; $i++) {
if ($theMonth[0] == $i) {
$countWeek[$i - 1]++;
}
}
}
return $countWeek;
}
So, the idea was to get a whole array of week numbers and use it in a loop for the colspans
<?php $span = getWeeksPerMonth($year) ?>
<?php for ($i = 1; $i < 13; $i++): ?>
<th colspan="<?= $span[$i - 1] ?>"><?= strftime('%B', mktime(0, 0, 0, $i)) ?></th>
<?php endfor ?>
And for the row below, I just use what I already used earlier in my question
<?php for ($i = 0; $i < getIsoWeeksInYear($year); $i++): ?>
<?php $firstDay = strtotime($year . 'W' . str_pad($week, 2, '0', STR_PAD_LEFT)); ?>
<th><?= date('d/m/Y', $firstDay) ?></th>
<?php endfor ?>
So, there may be some previous year included week in january and some next year excluded week for december.
Maybe, there are still some stuff to tweak somewhere. Anyway, I'll test out the other anwers and I guess I'll mark the easiest one to use as the answer.
Edit
It looks like I didn't have to explode the obtained date, as I initally thought I would have to use the year in some condition for the week starting the previous year
I am using simple pagination with following code.
But I want to show 1 2 3 ..... 10 11 12 type pagination.
When more number of pages are there, pagination should be adjusted accordingly.
My current simple pagination php code is :
<?php
if (isset($_GET["start"])){
$start = $db->filter($_GET["start"]);
}
if(empty($start)){
$start= 0;
}
$maxrecords = 10;
$pagination_query = "select * from table order by id desc";
$pagination_count = $db->num_rows($pagination_query);
$query = "select * from table order by id desc limit $start,$maxrecords"; // For record to display...
$result = $db->get_results($query);
?>
<div class="pagination">
<?php
for($i=0;$i<ceil($pagination_count/$maxrecords);$i++){
if($start==$i*$maxrecords){
?>
<a class='active'> <?php print $i+1;?></a>
<?php }else{ ?>
<?php print $i+1;?>
<?php
}
}
?>
</div>
<!-- Rest code to display records goes here -->
Now this code is working rightly...
Only thing is it is showing paginatin - 1 2 3 4 5 6 7 like unlimited depending upon total records in database...
I want to convert it to 1 2 3 .... 22 23 24 etc...
Your valuable help appreciated...
My answer begins by some notes about what I'm seeing about pagers.
Then, this answer doesn't provide the "expected result" you want, but I think it could be more "flexible".
I think your query to get the number of record seems to be expensive. You could just use a count(*) :
$pagination_query = "select count(*) as num from table order by id desc" ;
$pagination_count = $db->get_field_result() ; // I don't know your DB API.
I think your query to get the current results seems to doesn't take care about the $start and $maxrecords (but I don't known your database API) :
$query = "select * from table order by id desc limit ".($start*$maxrecords).",$maxrecords"; // range 0+10, 10+10, 20+10, ...
You could use several loops to display begining pages, "around current", and ending pages.
Here is a "sample" code, not perfect, but it could helps you to imaging your own pager.
$start = 7 ; // try with 1, 7, 24, 75...
$pagination_count = 40 ; // Number of results
$maxrecords = 10 ;
$num_pages = ceil($pagination_count / $maxrecords) ;
// echo "num_pages=$num_pages\n" ; // Just for dev
if ($start > $num_pages) { $start = $num_pages; }
if ($num_pages < 6) {
for ($i = 0; $i < $num_pages ; $i++) {
echo render_page_link($i, $start);
}
}
else {
// Begining
for ($i = 0 ; $i < min(3, $num_pages); $i++) {
echo render_page_link($i,$start) ;
}
echo ' (...) ' ;
$have_middle = ($start > 3 && $start <= $num_pages - 3) ;
if ($have_middle) {
// Around current
for ($i = max(3, $start - 3); $i < min($start + 3 - 1, $num_pages - 3) ; $i++) {
echo render_page_link($i,$start) ;
}
}
// Ending
if ($have_middle) echo ' (...) ' ;
for ($i = $num_pages - 3; $i < $num_pages ; $i++) {
echo render_page_link($i,$start);
}
}
echo "\n"; // just because I test on CLI.
// Here is a little function to display the link:
// Currently just "plain text", but could be <a> or <span> with CSS...
function render_page_link($index, $current = -1)
{
if ($index != $current - 1) return ($index+1) . " " ;
return "[".($index+1)."] " ;
}
Example result for 1 to 24 pages
[1] 2 3 (...) 22 23 24
1 [2] 3 (...) 22 23 24
1 2 [3] (...) 22 23 24
1 2 3 (...) [4] 5 6 (...) 22 23 24
1 2 3 (...) 4 [5] 6 7 (...) 22 23 24
1 2 3 (...) 4 5 [6] 7 8 (...) 22 23 24
1 2 3 (...) 5 6 [7] 8 9 (...) 22 23 24
1 2 3 (...) 6 7 [8] 9 10 (...) 22 23 24
1 2 3 (...) 7 8 [9] 10 11 (...) 22 23 24
1 2 3 (...) 8 9 [10] 11 12 (...) 22 23 24
1 2 3 (...) 9 10 [11] 12 13 (...) 22 23 24
1 2 3 (...) 10 11 [12] 13 14 (...) 22 23 24
1 2 3 (...) 11 12 [13] 14 15 (...) 22 23 24
1 2 3 (...) 12 13 [14] 15 16 (...) 22 23 24
1 2 3 (...) 13 14 [15] 16 17 (...) 22 23 24
1 2 3 (...) 14 15 [16] 17 18 (...) 22 23 24
1 2 3 (...) 15 16 [17] 18 19 (...) 22 23 24
1 2 3 (...) 16 17 [18] 19 20 (...) 22 23 24
1 2 3 (...) 17 18 [19] 20 21 (...) 22 23 24
1 2 3 (...) 18 19 [20] 21 (...) 22 23 24
1 2 3 (...) 19 20 [21] (...) 22 23 24
1 2 3 (...) [22] 23 24
1 2 3 (...) 22 [23] 24
1 2 3 (...) 22 23 [24]
How do i create a nested loop that will output the following numbers?
each round the inner loop increase from 1 to 5, 5 to 10 and so on.
from i = 0 to 5
inner loop:
result: 1 2 3 4 5
result: 6 7 8 9 1 0
result: 11 12 13 14 15
result: 16 17 18 19 20
next
for($i=0;$i<50;$i++)
{
$s = $i +5;
echo $s;
}
unless you have to use an inner do...while loop, this will work:
<?php
$max = 5;
for($i=0;$i<$max;$i++){
for($j=1;$j<=$max;$j++){
echo str_pad(($i*$max)+$j,4);
}
echo "\r\n";
}
output:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
I used str_pad() just to make the columns more uniform
Hi I have a 1D array (1 by 20) that I would like to transform to a 2D Array (4 by 5)
$winning_number = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
to
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
right now I am using this code:
foreach ($wining_no as $boulex)
{
for($i=0;$i<$5;$i++)
{
if($i==0)
{
for($j=0;$j<$4;$j++)
{
$boule_array[$j][$i] = $boulex;
}
}
}
}
For some reason this does not work
You could use the array_chunk($array, $size) function
For you it would be like this
array_chunk($winning_number, 5);