I am trying to create an array for years which i will use in the DOB year piece of a form I am building. Currently, I know there are two ways to handle the issue but I don't really care for either:
1) Range:
I know I can create a year array using the following
<?php
$year = range(1910,date("Y"));
$_SESSION['years_arr'] = $year;
?>
the problem with Point 1 is two fold: a) my function call shows the first year as 'selected' instead of "Year" as I have as option="0", and b) I want the years reversed so 2010 is the first in the least and shown decreasing.
My function call is:
PHP
<?php
function showOptionsDrop($array, $active, $echo=true){
$string = '';
foreach($array as $k => $v){
$s = ($active == $k)? ' selected="selected"' : '';
$string .= '<option value="'.$k.'"'.$s.'>'.$v.'</option>'."\n";
}
if($echo) echo $string;
else return $string;
}
?>
HTML
<table>
<tr>
<td>State:</td>
<td><select name="F1State"><option value="0">Choose a year</option><?php showOptionsDrop($_SESSION['years_arr'], null, true); ?></select>
</td>
</tr>
</table>
2) Long Array
I know i can physically create an array with years listed out but this takes up a lot of space and time if I ever want to go back and modify.
ex: PHP
$years = array('1900'=>"1900", '1901'=>"1901", '1902'=>"1902", '1903'=>"1903", '1904'=>"1904", '1905'=>"1905", '1906'=>"1906", '1907'=>"1907", '1908'=>"1908", '1909'=>"1909", '1910'=>"1910", '1911'=>"1911", '1912'=>"1912", '1913'=>"1913", '1914'=>"1914", '1915'=>"1915", '1916'=>"1916", '1917'=>"1917", '1918'=>"1918", '1919'=>"1919", '1920'=>"1920", '1921'=>"1921", '1922'=>"1922", '1923'=>"1923", '1924'=>"1924", '1925'=>"1925", '1926'=>"1926", '1927'=>"1927", '1928'=>"1928", '1929'=>"1929", '1930'=>"1930", '1931'=>"1931", '1932'=>"1932", '1933'=>"1933", '1934'=>"1934", '1935'=>"1935", '1936'=>"1936", '1937'=>"1937", '1938'=>"1938", '1939'=>"1939", '1940'=>"1940", '1941'=>"1941", '1942'=>"1942", '1943'=>"1943", '1944'=>"1944", '1945'=>"1945", '1946'=>"1946", '1947'=>"1947", '1948'=>"1948", '1949'=>"1949", '1950'=>"1950", '1951'=>"1951", '1952'=>"1952", '1953'=>"1953", '1954'=>"1954", '1955'=>"1955", '1956'=>"1956", '1957'=>"1957", '1958'=>"1958", '1959'=>"1959", '1960'=>"1960", '1961'=>"1961", '1962'=>"1962", '1963'=>"1963", '1964'=>"1964", '1965'=>"1965", '1966'=>"1966", '1967'=>"1967", '1968'=>"1968", '1969'=>"1969", '1970'=>"1970", '1971'=>"1971", '1972'=>"1972", '1973'=>"1973", '1974'=>"1974", '1975'=>"1975", '1976'=>"1976", '1977'=>"1977", '1978'=>"1978", '1979'=>"1979", '1980'=>"1980", '1981'=>"1981", '1982'=>"1982", '1983'=>"1983", '1984'=>"1984", '1985'=>"1985", '1986'=>"1986", '1987'=>"1987", '1988'=>"1988", '1989'=>"1989", '1990'=>"1990", '1991'=>"1991", '1992'=>"1992", '1993'=>"1993", '1994'=>"1994", '1995'=>"1995", '1996'=>"1996", '1997'=>"1997", '1998'=>"1998", '1999'=>"1999", '2000'=>"2000", '2001'=>"2001", '2002'=>"2002", '2003'=>"2003", '2004'=>"2004", '2005'=>"2005", '2006'=>"2006", '2007'=>"2007", '2008'=>"2008", '2009'=>"2009", '2010'=>"2010");
$_SESSION['years_arr'] = $years_arr;
Does anybody have a recommended idea how to work - or just how to simply modify my existing code?
Thank you!
Not sure why you're using the session for this, but generating the array can be done with the array_combine function.
$years = array_combine(range(date("Y"), 1910), range(date("Y"), 1910));
Reversing the parameters to range will give you a descending array and array_combine will use the first array as the keys and the second as the values, giving the array(1910 => 1910, ...); map you're after.
reverse the numbers in the range to get years in descending order
$years = range(2010, 1900); // => [2010, 2009, 2008, ... ]
use date('Y') instead of hard-coding the current year
$years = range(date('Y'), 1900);
append an option "Select year" at the beginning
array_unshift($years, "Select year");
And finally why have a select drop-down for year or date of birth at all? It might be prevalent but it's super irritating. A simple text-box with validations, something like dd/mm/yyyy or mm/dd/yyyy is way better. Having drop-downs for date, month, and year only means that a user is allowed to select valid values and not necessarily correct values if they find it convoluted just to input a date. Moreover, since users can still enter junk values by modifying the DOM, validations need to be done on the server side. If validations are being done on the server-side, might as well just offer them a simple text box.
Also drop-downs make client-side coding complex. For example, if Feb and a leap year are selected, then a days dropdown should contain 29 days, otherwise 28.
Why do you need to store the array into the session?
Based on your use case, you do not need to use the array to store data beforehand.
define('DOB_YEAR_START', 1900);
$current_year = date('Y');
for ($count = $current_year; $count >= DOB_YEAR_START; $count--)
{
print "<option value='{$count}'>{$count}</option>";
}
In option 1 add:
$year = array_reverse( $year );
or just use:
$year = range( date("Y") , 1910 );
for ($count = date('Y'); $count >= 1910; $count--)
echo '<option value="' . $count . '">' . $count . '</option>';
Why don't you do this on your first approach
foreach($array as $k){
$string .= '<option value="'.$k.'">'.$k.'</option>'."\n";
}
Semantically, and functionally, speaking it's better to use the year as value than an int.
Also, use drawnonward method to get an inverted array so the year 2010 is the first, and default, value on your list.
If just reversing the order of your year array is the goal you can use the array_reverse() function.
http://www.php.net/manual/en/function.array-reverse.php
part 2:
$years = array();
for($i = 1900;$i<= 2010;$i++)
$years["$i"] = $i;
I'd go with option #1. However all you need to do is prepend a value to the array before you print it:
<?php
$years = $_SESSION['years_arr'];
// reverse the year list
rsort($years);
// prepend the 'choose a year' value to the array
array_unshift($years, 'Choose a year');
?>
<td><select name="F1State"><?php showOptionsDrop($years, null, true); ?></select>
you can simply use PHP foreach() function!
example:
$years_now = date("Y");
echo '<select name="y">';
echo '<option value="" disabled>Now:</option>';
echo '<option value="'.$years_now.'" selected="selected">'.$years_now.'</option>';
echo '<option value="" disabled>Other:</option>';
foreach (range($years_now, 1910) as $years) {
echo '<option value="'.$years.'">'.$years.'</option>';
}
echo '</select>';
Extending Brenton Alker's answer; if you need to add something to the start of the array you could do something like this:
$keys = array_merge(['any'], range(date("Y"), 1910));
$values = array_merge(['Any'], range(date("Y"), 1910));
$choice = array_combine($keys, $values);
This will add the key/value of any/Any to the start of the array whilst keeping all the subsequent keys in place
Related
I am trying to display a table with PHP MYSQL where the FIELD is the DATE and rows are TIME from a MySQL database with unknown/infinite records, one with different TIMES for the same DATE, by querying it for the DateTime.
My mysql date stores the dateTime in the same column, but I am splitting this and trying to display them seperately. BUT I cannot seem to display the date only once and the time multiple times, it is just both.
$sql_result = mysqli_query($connection, "SELECT DATE(date_time) AS date_part, TIME(date_time) AS time_part FROM $table WHERE date_time LIKE '$date_input%'");
if (mysqli_num_rows($sql_result) == 0)
{
echo "<p>No bookings exist.</p>";
}
else {
echo "<h3>Results for booked " . $table . " Appointments:</h3>";
echo "<h3>" . $formattedDate ."</h3>";
while ($row = mysqli_fetch_array($sql_result))
{
echo $row['date_part'];
$array_time = array($row['time_part']);
foreach ($array_time as $time_output)
{
echo $time_output;
}
}
}
My output is like this:
2013-12-0809:00:002013-12-0810:00:002013-12-0811:00:002013-12-0812:00:002013-12-0814:00:002013-12-0815:00:002013-12-0816:00:002013-12-0817:00:002013-12-0909:00:002013-12-0809:00:00
But I would like it like this:
2013-12-08 09:00:0010:00:0011:00:0012:00:0014:00:0015:00:0016:00:0017:00:0009:00:000
2013-12-09 9:00:00
Hrrmm. Theres a bit of logic problem here:
while ($row = mysqli_fetch_array($sql_result))
{
echo $row['date_part'];
$array_time = array($row['time_part']); // HERE
foreach ($array_time as $time_output)
{
echo $row['time_part'];
}
}
$array_time will always have only one value, since $row['time_part'] only refers to ONE row (each iteration of while ($row = mysqli_fetch_array($sql_result)) reassigns a single row to $row)
try doing this first pass to define a workable array
while ($row = mysqli_fetch_array($sql_result))
{
$array[$row['date_part']][$row['time_part']] = 1; // the value assigned doesn't matter, all we wish is a definite hierarchy
}
this will give you an array like:
['2013-12-08']['9:08'] = 1
['12:30'] = 1
[23:17] = 1
['2013-12-09']['10:00'] = 1
[14:20] = 1
THEN! you can foreach through your result
foreach ($array as $date_part => $array_time)
{
echo $date_part . ' ';
foreach ($array_time as $time_part => $i) // again our $i is not used
{
echo $time_part;
}
echo '<br>'; // here it breaks line after all times for the date has been echoed
}
You need to GROUP in your query:
SELECT DATE(date_time) AS date_part, TIME(date_time) AS time_part
FROM $table
WHERE date_time LIKE '$date_input%'
GROUP BY date_part
I think I understand what you're trying to say, however, MySQL won't create a multidimensional array. You should try something like this:
$dates = array();
while ($row = mysqli_fetch_array($sql_result)) {
$dates[$row['date_part']][] = $row['time_part']
}
Then you could have something like this:
foreach ($dates as $key => $value) {
echo $key.'<br />';
foreach ($value as $time) {
echo $time.' - ';
}
echo '<br />';
}
which should look something like:
2013-09-01
09:00 - 09:30 - 10:20 - 11:00
2013-09-02
10:12 - 11:00 - 12:24 //etc
Hope this helps!
Two comments. First, it seems like you need an order by time so as to order your records.
SELECT DATE(date_time) AS `date_part`, TIME(date_time) AS `time_part`
FROM $table
WHERE date_time LIKE '$date_input%'
ORDER BY date_time ASC
Second, if I read your question correctly, it seems like you want to output your data into two columns, one with date and the other with all times for that date. You might consider using GROUP_CONCAT() to do this in SQL, making your output easy.
SELECT DATE(date_time) AS `date_part`, GROUP_CONCAT(TIME(date_time)) AS `times`
FROM $table
WHERE date_time LIKE '$date_input%'
GROUP BY `date_part`
ORDER BY date_time ASC
This would give output like
date_part times
2013-12-08 11:22:33,11:33:44,12:44:55
2013-12-09 12:00:00
With this approach, there would be no need to build a multi-dimensional array in PHP, as the data would come out of the database just the way you need it. That also means that you don't need to load the entire result set into memory in order to work with it (as you would have to do if creating multi-dimensional array).
I have created an array of data, from which I can loop through specific fields and echo these values out, but what I need to do is add these values to a new array, ultimately allowing me to find the average of the values in the new array. As i've said, I can echo out the data, and I think I've figured how to get the average, if only I can create the new array! Any help would be greatly appreciated as I just can't find the answer anywhere, and I'm running low on talent!
My table contains approx 25 fields, im pulling out a number of rows based on a session variable. In the instance im working on, I need to take just the values from 1 column in the table, and add these to an array. The code below will loop through the values, and echo them out, 1 at a time:-
while ($cdarray=mysql_fetch_array($calldata)) {
echo $cdarray['score_total'];
}
This gives me 25555 which are the 4 values I would expect 25, 5, 5, 5
I've tried
while ($cdarray=mysql_fetch_array($calldata)) {
$cdts = $cdarray['score_total'];
$cdtsar = array($cdts);
}
Which results in $cdts being assigned a value of 5,
Any help greatly appreciated!!
This will get your data from the array, place it into a new one and calculates the average.
$cdtsar = array();
while ($cdarray=mysql_fetch_array($calldata)) {
$cdtsar[] = $cdarray['score_total'];
}
$average = array_sum($cdtsar) / count($cdtsar);
It actually prints 25 and 5 and 5 and 5, but there are no spaces in between so it looks like "25555". To verify this yourself:
while ($cdarray=mysql_fetch_array($calldata)) {
echo $cdarray['score_total'];
echo " / ";
}
To get the average, you can either use
$sum = $count = 0;
$average = null;
while ($cdarray=mysql_fetch_array($calldata)) {
$sum += $cdarray['score_total'];
++$count;
}
// Make sure to guard against divide by zero
if ($count) {
$average = $sum / $count;
}
or you might have the database calculate the average for you, if changing the query is an option.
If you want to assign the elements to the new array use like this
$cdtsar = array();
while ($cdarray=mysql_fetch_array($calldata)) {
array_push($cdtsar,$cdarray['score_total']);
}
To find the average of the array
$sum = array_sum($cdtsar);
$num = sizeof($cdtsar);
$avg = $sum/$num;
echo $avg;
<?php
// initial value
$week = 50;
$year = 2001;
$store = array();
do
{
$week++;
$result = "$week/$year";
array_push($store,$result);
if($week == 53){
$week = 0;
$year++;//increment year by 1
}
continue;
}
// End of Loop
while ($result !== "2/2002");
?>
print_r($store);
result want return will be
array("51/2001", "52/2001", "01/2002", "02/2002");
What is my problems by using while using do..while ,continue?
Your arguments to array_push are the wrong way around. Read the manual entry for functions you use. Turn on warnings on your server; running this in codepad showed me the problem immediately. [Edit: You have now quietly fixed that in your question.]
You also have a typo: $i instead of $week.
Finally, you test against "02/2002", but for that month the string will be "2/2002".
Fixed code (live demo):
<?php
// initial value
$week = 50;
$year = 2001;
$store = array();
do
{
$week++;
$result = "$week/$year";
array_push($store, $result);
if($week == 53){
$week = 0;
$year++;//increment year by 1
}
continue;
}
// End of Loop
while ($result !== "2/2002");
?>
In general, I'd recommend against loops like this. As you've discovered, your code is very fragile because you're testing for just one very specific value, and if that value is not precisely correct you get an infinite loop.
Instead, consider comparing $week and $year separately and numerically:
while ($week < 2 && $year <= 2002)
Next time please include in your question the output that you are seeing, as well as the output that you want to see. It'll save us time in reproducing your problem.
I may not be understanding this correctly... If you could explain a bit more that'd help.
Try turning the loop into a function, and turn the while(..) to check the functions variable.
then just call it 4 times to fill your array.
I have set to constants, a start year and an end year,
so i have built a while loop on the condition that
if the start year is < than the current year increment until true.
the problem i have is that instead of it going up like this:
1999,2000,2001,2002,2003,2004
it goes like:
1999,2001,2003,2005,2007,2009
Here is my code:
function yearCount()
{
$yearBegin = START_YEAR;
$yearCurrent = CURRENT_YEAR;
while($yearBegin < $yearCurrent){
echo "<option value=\"".$yearBegin++."\">".$yearBegin++."</option>";
}
}
any ideas would be highly appreciated.
You are incrementing the value twice:
echo "<option value=\"".$yearBegin++."\">".$yearBegin++."</option>";
Each $yearBegin++ increments it by one.
Use a for loop instead:
for ($yearBegin = START_YEAR; $yearBegin < CURRENT_YEAR; $yearBegin++)
{
echo "<option value=\"".$yearBegin."\">".$yearBegin."</option>";
}
Using a for loop is usually the way to do this,
for($year=START_YEAR;$year<=CURRENT_YEAR;$year++)
{
//User the $year here
}
your problem with the code is that your calling $yearBegin++ 2 times within the while loop, causing it to increment twice.
using the for loop is much cleaner then as incrementing is done within the expression for you
function yearCount()
{
$yearBegin = START_YEAR;
$yearCurrent = CURRENT_YEAR;
while($yearBegin < $yearCurrent){
$this_year = $yearBegin++;
echo "<option value=\"".$this_year."\">".$this_year."</option>";
}
}
use only one time ++ , increment
echo "<option value=\"".$yearBegin."\">".$yearBegin++."</option>";
You increment $yearBegin twice, one time in the value part, one time in the display part ...
You need to change it so it only increments once
You increment it twice, once setting it as a value, and the second time displaying it in option tag
I'm trying to do something relatively simple here. Basically I have a table with a bunch of rows in it marked with a timestamp (format: 2009-05-30 00:14:57).
What I'm wanting to is do is a query which pulls out all of the rows, and splits them by the month so I'm left with a final result like:
February
rowID name order date
rowID name order date
rowID name order date
January
rowID name order date
rowID name order date
rowID name order date
etc.
I have a few vague ideas how to do this - they just seem long winded.
One of the ways would be to do a query for each month. I'd derive what the current month is in PHP then construct a for() which goes back a certain number of months.
like:
$currentmonth = 8;
$last6months = $currentmonth - 6;
for($i = $currentmonth; $i == $last6months; $i--) {
$sql = 'SELECT * FROM reports WHERE MONTH(reports.when) = $currentmonth ';
$res = mysql_query($sql);
// something would go here to convert the month numeral into a month name $currentmonthname
echo $currentmonthname;
while($row = mysql_fetch_array($res)) {
// print out the rows for this month here
}
}
Is there a better way to do this?
It's better to fetch all data once,ordered by month..
Then while fetching with php you can store your current month in a variable (for example $curMonth) and if there is a change in the month, you echo "New Month"...
Executing a query is slow, it's better to minimize your "conversations" with the db..
Don't forget that you have to deal with years aswell. If you have two records, one for January '09 and one for January '08, your results may be skewed.
Best to follow Svetlozar's advice and fetch all data at once. Once you have it in memory, use PHP to segment it into something usefull:
$monthData = array();
$queryResult = mysql_query("
SELECT
*,
DATE_FORMAT('%m-%Y', when) AS monthID
FROM
reports
WHERE
YEAR(when) = 2009 AND
MONTH(when) BETWEEN 5 and 11
");
while ($row = mysql_fetch_assoc($queryResult))
{
if (!isset($monthData[$row['monthID']]))
$monthData[$row['monthID']] = array();
$monthData[$row['monthID']][] = $row;
}
mysql_free_result($queryResult);
foreach($monthData as $monthID => $rows)
{
echo '<h2>Data for ', $monthID, '</h2>';
echo '<ul>';
foreach($rows as $row)
{
echo '<li>', $row['someColumn'], '</li>';
}
echo '</ul>';
}
You could change your SQL query to get your entire report. This is much more efficient than querying the database in a loop.
select
monthname(reports.when) as currentmonth,
other,
fields,
go,
here
from reports
order by
reports.when asc
You could then use this loop to created a nested report:
var $currentMonth = '';
while($row = mysql_fetch_array($res)) {
if($currentMonth !== $row['currentMonth']) {
$currentMonth = $row['currentMonth']);
echo('Month: ' . $currentMonth);
}
//Display report detail for month here
}
*Note: Untested, but you get the general gist of it I'm sure.
This is the SQL script:
SELECT*, DATE_FORMAT(fieldname,'%Y-%m') AS report FROM bukukecil_soval WHERE MONTH(fieldname) = 11 AND YEAR(fieldname)=2011
I hope you know where you should put this code :D