Отметить даты в календаре бронирования как полностью доступные, частично доступные или недоступные

Я работаю над календарем бронирования, в котором есть даты заезда и выезда. Мне нужно уметь:

  1. Показать календарь на любой месяц

  2. Для каждой даты в календаре укажите, является ли дата полностью доступной, частично доступной или недоступной

Для первого элемента в списке выше, я использую код из Статья Дэвида Уолша «Построение календаря с использованием PHP, XHTML и CSS». На случай, если эта ссылка испортится, вот код:

/* calendar */
table.calendar      { border-left:1px solid #999; }
tr.calendar-row {  }
td.calendar-day { min-height:80px; font-size:11px; position:relative; } * html div.calendar-day { height:80px; }
td.calendar-day:hover   { background:#eceff5; }
td.calendar-day-np  { background:#eee; min-height:80px; } * html div.calendar-day-np { height:80px; }
td.calendar-day-head { background:#ccc; font-weight:bold; text-align:center; width:120px; padding:5px; border-bottom:1px solid #999; border-top:1px solid #999; border-right:1px solid #999; }
div.day-number      { background:#999; padding:5px; color:#fff; font-weight:bold; float:right; margin:-5px -5px 0 0; width:20px; text-align:center; }
/* shared */
td.calendar-day, td.calendar-day-np { width:120px; padding:5px; border-bottom:1px solid #999; border-right:1px solid #999; }
/* draws a calendar */
function draw_calendar($month,$year){

/* draw table */
$calendar = '<table cellpadding="0" cellspacing="0" class="calendar">';

/* table headings */
$headings = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
$calendar.= '<tr class="calendar-row"><td class="calendar-day-head">'.implode('</td><td class="calendar-day-head">',$headings).'</td></tr>';

/* days and weeks vars now ... */
$running_day = date('w',mktime(0,0,0,$month,1,$year));
$days_in_month = date('t',mktime(0,0,0,$month,1,$year));
$days_in_this_week = 1;
$day_counter = 0;
$dates_array = array();

/* row for week one */
$calendar.= '<tr class="calendar-row">';

/* print "blank" days until the first of the current week */
for($x = 0; $x < $running_day; $x++):
$calendar.= '<td class="calendar-day-np"> </td>';
$days_in_this_week++;
endfor;

/* keep going with days.... */
for($list_day = 1; $list_day <= $days_in_month; $list_day++):
$calendar.= '<td class="calendar-day">';
/* add in the day number */
$calendar.= '<div class="day-number">'.$list_day.'</div>';

/** QUERY THE DATABASE FOR AN ENTRY FOR THIS DAY !!  IF MATCHES FOUND, PRINT THEM !! **/
$calendar.= str_repeat('<p> </p>',2);

$calendar.= '</td>';
if($running_day == 6):
$calendar.= '</tr>';
if(($day_counter+1) != $days_in_month):
$calendar.= '<tr class="calendar-row">';
endif;
$running_day = -1;
$days_in_this_week = 0;
endif;
$days_in_this_week++; $running_day++; $day_counter++;
endfor;

/* finish the rest of the days in the week */
if($days_in_this_week < 8):
for($x = 1; $x <= (8 - $days_in_this_week); $x++):
$calendar.= '<td class="calendar-day-np"> </td>';
endfor;
endif;

/* final row */
$calendar.= '</tr>';

/* end the table */
$calendar.= '</table>';

/* all done, return result */
return $calendar;
}

/* sample usages */
echo '<h2>July 2009</h2>';
echo draw_calendar(7,2009);

echo '<h2>August 2009</h2>';
echo draw_calendar(8,2009);

Я застрял на втором пункте, который у меня есть в списке в верхней части этого вопроса. Моя цель — получить календарь, который выглядит примерно так:

Пример календаря

Я увидел следующий комментарий в PHP-коде Дэвида Уолша:

/** QUERY THE DATABASE FOR AN ENTRY FOR THIS DAY !!  IF MATCHES FOUND, PRINT THEM !! **/

я мог поместите запрос к базе данных вместо этого комментария и попросите запрос найти строку, из-за которой эта дата не будет помечена как полностью доступная, а затем, если строка найдена, отметьте ее соответствующим образом. Что мне не нравится в этой идее, так это то, что я буду использовать базу данных как минимум 28 раз для календаря на один месяц. Я предпочел бы сделать один запрос заранее, который производит массив, как это:

$events = array(
array(
'check_in_date' => '2014-11-18',
'check_out_date' => '2014-11-19',
),
array(
'check_in_date' => '2014-11-19',
'check_out_date' => '2014-11-21',
),
array(
'check_in_date' => '2014-11-24',
'check_out_date' => '2014-11-27',
),
);

Таким образом, я мог бы сделать ту же логику выше, но ссылаясь на массив, а не выполнять запрос к базе данных. Хотя я не уверен, как это сделать. Я видел этот комментарий к статье Дэвида Уолша где кто-то достиг этой цели, но не опубликовал код, который использовал. Я написал человеку по электронной почте, но прошло уже почти неделю, а я до сих пор не получил ответа.

Любые идеи о том, как лучше всего выполнить второй пункт, который я имею в списке в верхней части этого вопроса?

0

Решение

Вы ищете что-то вроде этого:

$year = 2014;
$month = 11;

define('FREE', 'free');
define('PARTIAL_CHECKOUT', 'unavailable in the morning');
define('PARTIAL_CHECKIN', 'unavailable from the afternoon');
define('FULL', 'unavailable');

$nb_days = date("t", strtotime("$year-$month-01"));
$begin_month_tm = strtotime("$year-$month-01");
$end_month_tm = strtotime("$year-$month-$nb_days 23:59:59");

$days = array_fill(1, $nb_days, FREE);

foreach ($events as $event)
{
$check_in_tm = strtotime($event['check_in_date']);
$check_out_tm = strtotime($event['check_out_date']);

if (($check_out_tm < $begin_month_tm) || ($check_in_tm > $end_month_tm))
{
continue;
}

if ($check_in_tm >= $begin_month_tm)
{
$inD = (int)substr($event['check_in_date'], strrpos($event['check_in_date'], '-') + 1);
$days[$inD] = $days[$inD] == FREE ? PARTIAL_CHECKIN : FULL;
}
else
{
$inD = 0;
}

if ($check_out_tm <= $end_month_tm)
{
$outD = (int)substr($event['check_out_date'], strrpos($event['check_out_date'], '-') + 1);
$days[$outD] = $days[$outD] == FREE ? PARTIAL_CHECKOUT : FULL;
}
else
{
$outD = $nb_days + 1;
}

for ($day = $inD + 1; ($day < $outD); $day++)
{
$days[$day] = FULL;
}
}

var_dump($days);

С контекстом:

$events = array (
array (
'check_in_date' => '2014-10-29',
'check_out_date' => '2014-11-02',
),
array (
'check_in_date' => '2014-11-18',
'check_out_date' => '2014-11-19',
),
array (
'check_in_date' => '2014-11-19',
'check_out_date' => '2014-11-21',
),
array (
'check_in_date' => '2014-11-24',
'check_out_date' => '2014-11-27',
),
array (
'check_in_date' => '2014-11-29',
'check_out_date' => '2014-12-03',
),
);

Ты получишь:

array(30) {
[1]=>
string(11) "unavailable"[2]=>
string(26) "unavailable in the morning"[3]=>
string(4) "free"[4]=>
string(4) "free"[5]=>
string(4) "free"[6]=>
string(4) "free"[7]=>
string(4) "free"[8]=>
string(4) "free"[9]=>
string(4) "free"[10]=>
string(4) "free"[11]=>
string(4) "free"[12]=>
string(4) "free"[13]=>
string(4) "free"[14]=>
string(4) "free"[15]=>
string(4) "free"[16]=>
string(4) "free"[17]=>
string(4) "free"[18]=>
string(30) "unavailable from the afternoon"[19]=>
string(11) "unavailable"[20]=>
string(11) "unavailable"[21]=>
string(26) "unavailable in the morning"[22]=>
string(4) "free"[23]=>
string(4) "free"[24]=>
string(30) "unavailable from the afternoon"[25]=>
string(11) "unavailable"[26]=>
string(11) "unavailable"[27]=>
string(26) "unavailable in the morning"[28]=>
string(4) "free"[29]=>
string(30) "unavailable from the afternoon"[30]=>
string(11) "unavailable"}

С контекстом:

$events = array (
array (
'check_in_date' => '2014-10-29',
'check_out_date' => '2014-12-03',
),
);

Ты получишь:

array(30) {
[1]=>
string(11) "unavailable"[2]=>
string(11) "unavailable"[3]=>
string(11) "unavailable"[4]=>
string(11) "unavailable"[5]=>
string(11) "unavailable"[6]=>
string(11) "unavailable"[7]=>
string(11) "unavailable"[8]=>
string(11) "unavailable"[9]=>
string(11) "unavailable"[10]=>
string(11) "unavailable"[11]=>
string(11) "unavailable"[12]=>
string(11) "unavailable"[13]=>
string(11) "unavailable"[14]=>
string(11) "unavailable"[15]=>
string(11) "unavailable"[16]=>
string(11) "unavailable"[17]=>
string(11) "unavailable"[18]=>
string(11) "unavailable"[19]=>
string(11) "unavailable"[20]=>
string(11) "unavailable"[21]=>
string(11) "unavailable"[22]=>
string(11) "unavailable"[23]=>
string(11) "unavailable"[24]=>
string(11) "unavailable"[25]=>
string(11) "unavailable"[26]=>
string(11) "unavailable"[27]=>
string(11) "unavailable"[28]=>
string(11) "unavailable"[29]=>
string(11) "unavailable"[30]=>
string(11) "unavailable"}
1

Другие решения

Ответ Алена Тьембло дал мне большую часть пути туда. Я не мог бы сделать это без него. Хотя с его ответом были некоторые проблемы, но у меня сложилось впечатление, что его ответ должен был стать отправной точкой, а не исчерпывающим ответом, и это нормально. Вот окончательный код, который обрабатывает такие вещи, как даты регистрации за месяц до отображаемого месяца, даты регистрации за месяц после отображаемого месяца и т. Д .:

$year = 2014;
$month = 11;
$totalDays = date("t", strtotime("$year-$month-01"));

define('FREE', 'free');
define('PARTIAL_CHECKOUT', 'unavailable in the morning');
define('PARTIAL_CHECKIN', 'unavailable from the afternoon');
define('FULL', 'unavailable');

$days = array_fill(1, $totalDays, FREE);

foreach ($events as $event)
{
list($inY, $inM, $inD) = explode('-', $event['check_in_date']);
list($outY, $outM, $outD) = explode('-', $event['check_out_date']);

if ($inY != $year || $inM != $month)
{
// The check-in date is in a month before the month being displayed.

$inD = 1;

if ($outD != 1)
{
$days[$inD] = FULL;
}
}
else
{
$inD = (int) $inD;
$days[$inD] = $days[$inD] == FREE ? PARTIAL_CHECKIN : FULL;
}

if ($outY != $year || $outM != $month)
{
// The check-out date is in a month after the month being displayed.

$outD = $totalDays;

if ($inD != $totalDays)
{
$days[$outD] = FULL;
}
}
else
{
$outD = (int) $outD;
$days[$outD] = $days[$outD] == FREE ? PARTIAL_CHECKOUT : FULL;
}

for ($day = $inD + 1; ($day < $outD); $day++)
{
$days[$day] = FULL;
}
}

var_dump($days);
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector