How to validate day/month/year select with php? I red some topics about who to validate select with 2-3 or even 5-6 select options. I would know how to validate that kind of select. But in the case of, for exemple, month, there are 32 options. Or in the case of year option, the are 60-70 options. So im interested in whats the optimal way to do select validation when you have so much options?
For date it's actually relatively easy - you just use checkdate().
And for the other cases you could check if the value is within an expected range like:
if ($val >= min && $val <= max)
or, in case you have all the values in an array
if (in_array($val, $array_of_valid_values))
Validating selects is fairly trivial.
Year
Let's say you have a sequential range of years from 1960-2013.
Your HTML for the selects is:
<select name="year">
<option value="1960">1960</option>
...
<option value="2013">2013</option>
</select>
So, you know that your year has to fall in the range of 1960 to 2013:
$year = (int) $_POST["year"]);
if ($year < 1960 || $year > 2013) {
$validationPassed = false;
}
Simple enough to validate the year.
Month
Now that you know what year it is, you can find out if it is a leap year. However, that is only important for a single month, so first let's validate what month they selected:
<select name="month">
<option value="0">January</option>
...
<option value="11">December</option>
</select>
Once again, validation of the month is easy. We know it has to be a value between 0 and 11.
$month = (int) $_POST["month"];
if ($month < 0 || $month > 11) {
$validationPassed = false;
}
Day
Now we know the month and the year. to validate the selected day, we need to check the following criteria:
Is it a leap year?
Is it the month of the year with the extra day for the leap year? (February).
For a year to be a leap year, it has to be divisible by 400, or not divisible by 100 and divisible by 4:
function isLeapYear($year) {
if ($year % 400 == 0)
return true;
else if ($year % 100 == 0)
return false;
else if ($year % 4 == 0)
return true;
return false;
}
Now, we can check if it is a leap year or not. If it is a leap year, then we know we need to allow 1 extra day in February.
We make an array of days in each month:
$daysInMonth = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
Then we get the amount of days in the current month:
$monthDays = $daysInMonth[$month];
If it is a leap year, we add a day to the total days in the month:
if ($month == 1 && isLeapYear($year)) //February
$monthDays++;
Finally, we can validate the day
$day = (int) $_POST["day"];
if ($day < 0 || $day > $monthDays) {
$validationPassed = false;
}
Now, all of this is basically encapsulated into the checkdate() function that was in the other answer below. So, to use checkdate() instead of all the code above, you could simply do the following:
HTML
(Note: checkdate() is not zero-based, so we start our days and months at 1 instead of 0.)
<form action="myphp.php" method="post">
<select name="day">
<option value="1">1</option>
...
<option value="31">31</option>
</select>
<select name="month">
<option value="1">1</option>
...
<option value="12">12</option>
</select>
<select name="year">
<option value="1960">1960</option>
...
<option value="2013">2013</option>
</select>
</form>
PHP
$day = (int) $_POST["day"];
$month = (int) $_POST["month"];
$year = (int) $_POST["year"];
$validationPassed = checkdate($month, $day, $year);
Related
I am new to PHP. I have a selection box with a range of years starting at current year - 5 (2014) through the year 2050. My selection box contains the correct years but I need it to default to the current year. Right now, it defaults to 2014. I've been working on this for hours. I thought the $current_year variable was needed in the loop in some way - in order to set the default - but that doesn't work. After researching and seeing various examples, I'm now thinking I need to build an if statement within the loop but I really don't know.
<form id="calendarForm" name="calendarForm" method="post" action="">
<label for="select_year">Select the year: </label>
<select id="select_year" name="select_year">
<?php
$date = new DateTime();
// Sets the current year
$current_year = $date->format('Y');
// Year to start available options.
$earliest_year = ($current_year - 5);
$year = $earliest_year;
for ($year = $earliest_year; $year <= LATEST_YEAR; $year++) {
echo "<option value='$year'>$year</option>";
}
?>
</select>
Modify your for loop as follows:
for ($year = $earliest_year; $year <= LATEST_YEAR; $year++) {
if($year==$current_year)
{
echo "<option value='$year' selected>$year</option>";
}
else{
echo "<option value='$year'>$year</option>";
}
}
Try the following. You need to adjust your php tags but neat.
<option value='$year' <?php if($year == date("Y")) {echo "selected";}?> >$year</option>";
It will check against the current year and will be the selected option if matched.
I'm trying to write codes with PHP to enable leap year friendly select option tags. For example, you pick a year, then it checks if it is a leap year or not, then it shows a pull down menu (select option tags) of days preceded by another select option tags of 12 months. PHP codes are embedded in HTML. Here is my failed attempt below (I'm new to PHP):
<form method="post">
<select name="year">
<option value="" selected>Pick a year</option><!--Default-->
<option value="2016">2016</option>
<option value="2017">2017</option>
<option value="2018">2018</option>
<option value="2019">2019</option>
<option value="2020">2020</option>
</select>
<select name="month">
<option value="" selected>Pick a month</option><!--Default-->
<!--Show all 12 months-->
<?php for( $i = 1; $i <= 12; $i++ ): ?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php endfor; ?>
</select>
<select name="day">
<option value="" selected>Pick a day</option><!--Default-->
<!--Show dates depending on the conditions below:-->
<?php
if ( $month == 1 || 3 || 5 || 7 || 8 || 10 || 12 )
{
//Show dates until 31
for ( $i = 1; $i <= 31; $i++ )
{
?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php
}
}
elseif ( $month == 2 )
{
//Leap year
if ( $year != "" && $year % 4 == 0 && $year % 100 == 0 && $year % 400 == 0 )
{
//Show dates until 29
for ( $i = 1; $i <= 29; $i++ )
{
?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php
}
}
//Regular year (Non-leap year)
else
{
//Show dates until 28
for ( $i = 1; $i <= 28; $i++ )
{
?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php
}
}
}
elseif ( $month == 4 || 6 || 9 || 11 )
{
//Show dates until 30
for ( $i = 1; $i <= 30; $i++ )
{
?>
<option value="<?php echo $i; ?>"><?php echo $i; ?></option>
<?php
}
}
?>
</select>
<input type="submit" value="submit">
</form>
Notes:
I understand that the above is the incomplete code and it doesn't work. Besides, I don't know how to define $year or $month or $day from the select tags. Should I do it like this? If so, where should I put it?
<?php
if( $_SERVER["REQUEST_METHOD"] == "POST" )
{
$year = $_POST['year'];
$month = $_POST['month'];
$day = $_POST['day'];
//The rest of the php code?
}
?>
Preferably, I do not want to show years by using for loops as in months and days. I would like to do it manually this time (sorry, but if you suggest I should use the for loop, I appreciate your advise).
I wrote $year =! "" in the leap year February if block because I want to evade the empty default values from being counted.
I warmly welcome your suggestions and corrections, please help me out :)
Thanks in advance!
As far as I know about leap year:
/**
* In the Gregorian calendar 3 criteria must be taken into account to identify leap years:
* 1. The year is evenly divisible by 4;
* 2. If the year can be evenly divided by 100, it is NOT a leap year, unless;
* 3. The year is also evenly divisible by 400. Then it is a leap year.
*
* #param $year integer
* #return bool
*/
private static function isLeapYear($year)
{
// the rule was applied after 1582
if ($year > 1582) {
if (($year % 400 == 0 && $year % 100 != 0) || ($year % 4 == 0))
{
//"It is a leap year"
return true;
}
else
{
return false;
//"It is not a leap year"
}
}
return false;
}
This won't work:
( $month == 1 || 3 || 5 || 7 || 8 || 10 || 12 )
This will only check that $month == 1, then the other conditions will be evaluated to true because the integers are evaluated to true (and PHP can't compare a variable to booleans with this code).
It looks like you're trying to get the number of days per month. This can be done easily with DateTime::Format() that use the date() format:
t returns the Number of days in the given month:
$dt = new Datetime('2016-02-15');
print $dt->format('t');
// display "29"
Example.
L returns the 1 if a year is leap, 0 otherwise:
$dt = new Datetime('2016-02-15');
print $dt->format('L');
// display "1"
$dt = new Datetime('2015-02-15');
print $dt->format('L');
// display "0"
Example.
You should probably don't care about the inputs and display all the years, the 12 months and 31 days per month and check the date with checkdate() once the data have been submitted.
I am trying to create a HTML select input based on months/years and I am not sure the best approach for it.
While creating a standard loop of years was the first place I started, I wasn't sure how to get the last days of each of the month/years in order to create the values.
Is there any built in PHP functions that can accomplish something close to what I am looking for?
Logic:
Must be able to provide a starting year (ex. 2014).
Must start at the starting year and go 1 year past the current year (ex. If Start = 2014, it will show 2014, 2015, 2016.
The value of the option must be the last day of the month in date format (ex. <option value="01/31/2015">January 2015</option>
Output:
<select class="s2 span4" name="desiredCompletion" placeholder="Select a Desired Completion Date">
<optgroup label="2016">
<option value="01/31/2016">Janurary 2016</option>
<option value="02/28/2016">Feburary 2016</option>
<option value="03/31/2016">March 2016</option>
...
</optgroup>
<optgroup label="2015">
<option value="01/31/2015">Janurary 2015</option>
<option value="02/28/2015">Feburary 2015</option>
<option value="03/31/2015">March 2015</option>
...
</optgroup>
<optgroup label="2014">
<option value="01/31/2014">Janurary 2014</option>
<option value="02/28/2014">Feburary 2014</option>
<option value="03/31/2014">March 2014</option>
...
</optgroup>
</select>
This function should do:
function createYearSelect($from) {
// open select
echo "<select class=\"s2 span4\" name=\"desiredCompletion\" placeholder=\"Select a Desired Completion Date\">";
// for each year from the one specified to the one after current
foreach(range($from, date('Y') + 1) as $year) {
// open optgroup for year
echo "<optgroup label=\"$year\">";
// foreach month
foreach (range(1, 12) as $month) {
// timestamp of first day
$time = strtotime("$year-$month-01");
// create option with date() formatting
echo "<option value=\"".date("m/t/Y", $time)."\">".date("F Y", $time)."</option>";
}
// close optgroup for year
echo "</optgroup>";
}
// close select
echo "</select>";
}
Here's a bit more elegant way
foreach(range(2014, 2015) as $year){
foreach(range(1, 12) as $month){
echo date('Y.m.d', strtotime('Last day of ' . date('F', strtotime($year . '-' . $month . '-01')) . $year)) . PHP_EOL;
}
}
This outputs the list of the last days of months for the years in specified range.
2014.01.31
2014.02.28
2014.03.31
2014.04.30
...
Using the DateTime class you can create dates using natural language.
Eg,
$date = new DateTime("-1 Year");
echo $date->format('F Y'); // Prints 'December 2014'
You can use a decrementing for loop to create many dates going back in time.
Check for the function below which gives the total number of days in a month
date("t");
Further details are available at http://php.net/manual/en/function.date.php
I have D.O.B select box in a form, I want to populate an exact days base on selected year and month
Year:
<select name="yy" id="yy" class="box">
<option value="2013">2013</option>
.
.
<option value="1955">1955</option>
</select>
Month:
<select name="mm" id="mm" class="box">
<option value="01">01</option>
.
.
<option value="12">12</option>
</select>
I will use PHP function to populate days:
function days_in_month($month, $year){
// calculate number of days in a month
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
}
In jQuery onchange, how could I get yy and mm values pass to days_in_month($month, $year) like below?
$('#mm').on('change', function() {
alert( this.value );
});
I don't want the page refresh for every onchange of selected values.
You can do this using javascript , no need to use ajax with php in this case :
<script type='text/javascript'>
function days_in_month(month, year){
// calculate number of days in a month
return month == 2 ? (year % 4 ? 28 : (year % 100 ? 29 : (year % 400 ? 28 : 29))) : ((month - 1) % 7 % 2 ? 30 : 31);
}
$(document).ready(function() {
$('#mm').change(function(){
var mm=$(this).val();//get the month
var yy=$('#yy').val();//get the day
$('#dd').val(days_in_month(mm,yy));// i assume that your input for day has id='dd'
});
});
</script>
I need to generate an html code of a list of 10 open days following the current day, by open days I mean business days (m,t,w,t and f), I'm using the following function to translate the date to french:
function f_date() {
$temps = time();
$jours = array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');
$jours_numero = date('w', $temps);
$jours_complet = $jours[$jours_numero];
$NumeroDuJour = date('d', $temps);
$mois = array(' ', 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre');
$mois_numero = date("n", $temps);
$mois_complet = $mois[$mois_numero];
$an = date('Y', $temps);
$fr_temps = "$jours_complet, $NumeroDuJour $mois_complet $an";
return "$fr_temps";
}
echo "<br/>".f_date();
And i want to generate the following result:
<select name="ladate">
<option selected="selected" value="Mardi, 29 mai 2012">29 mai 2012</option>
<option value="Mercredi, 30 mai 2012">30 mai 2012</option></select>
....
<option value="Vendredi, 15 juin 2012">15 juin 2012</option></select>
</select>
Please tell me if you need further information.
Thank you.
Since you are only looking for MTWTF and you want the next 10 days, you can always safely look for the next 14 days and ignore the weekends and that will give 10 days. It won't work for holidays or anything like that but you can change it if you need to do that. I'll give you the pseudo-code here, I'll leave all the array mapping and text output to you
for ($days_to_add : 1 to 14) {
$new_date = date_add($days_to_add);
// check the day of the week
if (date('N', $new_date) >= 6) {
// ignore it, it's a weekend
continue;
}
// output the option tag for $new_date
echo "<option ... </option>"
}
This relies on the 10 and 14 day assumption, if you wanted to change that number you could add some sort of counter and only increment the counter if you were looking at a weekday/non-holiday
Just create a loop, increase the days up to ten and ignore all non open days (Sat, Sun). date('N') is your friend to detect the weekday of a given date.
<?php
$i = $openDay = 0;
while($openDay < 10) {
$i++;
$time = strtotime('+'.$i.' days');
$day = date('N', $time);
if ($day == 6 or $day == 7) { // ignore Saturdays and Sundays
continue;
}
echo f_date($time).'<br>';
$openDay++;
}
You also have to modify your date_f() function to use $temps as parameter.
<?php
function f_date($temps = null) {
// $temps = time();
// ...
}