Рубрика «PHP»

Календарь на PHP

Основная проблема при формировании календаря заключается в том, что месяц, как правило, начинается с середины недели. Сам календарь представляет собой таблицу с количеством строк, равных количеству дней в неделе, и количеством столбцов, равных количеству недель в месяце, поэтому формирование календаря целесообразно проводить сразу в двухмерном массиве.

<?php
  setlocale ( LC_ALL, '' );
  // Название месяца
  echo '<h3>'.strftime( '%B' ).'</h3>';
  // Вычисляем число дней в текущем месяце
  $dayofmonth = date('t');
  // Счётчик для дней месяца
  $day_count = 1;

  // Первая неделя
  $num = 0;
  for( $i = 0; $i < 7; $i++ ) {
    // Вычисляем номер дня недели для числа
    $dayofweek = date('w', mktime(0, 0, 0, date('m'), $day_count, date('Y')));
    // Приводим к числа к формату 1 - понедельник, ..., 6 - суббота
    $dayofweek = $dayofweek - 1;
    if($dayofweek == -1) $dayofweek = 6;

    if($dayofweek == $i) {
      // Если дни недели совпадают, заполняем массив $week числами месяца
      $week[$num][$i] = $day_count;
      $day_count++;
    } else {
      $week[$num][$i] = '';
    }
  }

  // Последующие недели месяца
  while( true ) {
    $num++;
    for( $i = 0; $i < 7; $i++ ) {
      $week[$num][$i] = $day_count;
      $day_count++;
      // Если достигли конца месяца - выходим из цикла
      if( $day_count > $dayofmonth ) break;
    }
    // Если достигли конца месяца - выходим из цикла
    if( $day_count > $dayofmonth ) break;
  }
  // Какой сегодня день
  $today = date( 'j' );
  // Выводим содержимое массива $week в виде календаря
  echo '<table border="1" style="border-collapse:collapse" cellpadding="5" cellspacing="0">';
  for( $j = 0; $j < 7; $j++ ) {
    echo '<tr align="right">';
    for( $i = 0; $i < count($week); $i++ ) {
      if( !empty( $week[$i][$j] ) ) {
        if ( $week[$i][$j] == $today )
          echo '<td bgcolor="#DDDDDD">';
        else
          echo '<td>';
        // Если имеем дело с субботой и воскресеньем - подсвечиваем их
        if( $j == 5 || $j == 6 )
          echo '<span style="color:red">'.$week[$i][$j].'</span>';
        else
          echo $week[$i][$j];
        echo '</td>';
      } else {
        echo '<td>&nbsp;</td>';
      }
    }
    echo '</tr>';
  }
  echo '</table>';
?>

Чтобы изменить формат вывода календаря недель месяца с вертикального на горизонтальный - достаточно внести незначительные изменения в тот фрагмент кода, который отвечает за вывод сформированного массива в виде таблицы:

<?php
  setlocale ( LC_ALL, '' );
  // Название месяца
  echo '<h3>'.strftime( '%B' ).'</h3>';
  // Вычисляем число дней в текущем месяце
  $dayofmonth = date('t');
  // Счётчик для дней месяца
  $day_count = 1;

  // Первая неделя
  $num = 0;
  for( $i = 0; $i < 7; $i++ ) {
    // Вычисляем номер дня недели для числа
    $dayofweek = date('w', mktime(0, 0, 0, date('m'), $day_count, date('Y')));
    // Приводим к числа к формату 1 - понедельник, ..., 6 - суббота
    $dayofweek = $dayofweek - 1;
    if($dayofweek == -1) $dayofweek = 6;

    if($dayofweek == $i) {
      // Если дни недели совпадают, заполняем массив $week числами месяца
      $week[$num][$i] = $day_count;
      $day_count++;
    } else {
      $week[$num][$i] = '';
    }
  }

  // Последующие недели месяца
  while( true ) {
    $num++;
    for( $i = 0; $i < 7; $i++ ) {
      $week[$num][$i] = $day_count;
      $day_count++;
      // Если достигли конца месяца - выходим из цикла
      if( $day_count > $dayofmonth ) break;
    }
    // Если достигли конца месяца - выходим из цикла
    if( $day_count > $dayofmonth ) break;
  }
  // Какой сегодня день
  $today = date( 'j' );
  // Выводим содержимое массива $week в виде календаря
  echo '<table border="1" style="border-collapse:collapse" cellpadding="5" cellspacing="0">';
  for( $i = 0; $i < count($week); $i++ ) {
    echo '<tr align="right">';
    for( $j = 0; $j < 7; $j++ ) {
      if( !empty( $week[$i][$j] ) ) {
        if ( $week[$i][$j] == $today )
          echo '<td bgcolor="#DDDDDD">';
        else
          echo '<td>';
        // Если имеем дело с субботой и воскресеньем - подсвечиваем их
        if( $j == 5 || $j == 6 )
          echo '<span style="color:red">'.$week[$i][$j].'</span>';
        else
          echo $week[$i][$j];
        echo '</td>';
      } else {
        echo '<td>&nbsp;</td>';
      }
    }
    echo '</tr>';
  }
  echo '</table>';
?>

Время формирования страницы

Для вычисления времени формирования страницы с требуемой точностью можно использовать функцию microtime(), которая возвращает строку вида “msec sec”, где msec - составляющая в микросекундах, а sec - время в секундах, прошедшее с 1970 года. Результат, возвращаемый функцией, может быть, к примеру, таким:

0.48023600 1076713360

Такое представление не очень удобно для вычисления разницы во времени, поэтому его необходимо преобразовать в числовой вид. Иначе говоря, строку “msec sec” необходимо преобразовать к виду “sec.msec”:

<?php
$part_time = explode(' ', microtime());
$real_time = $part_time[1].substr($part_time[0], 1);
?>

Здесь при помощи функции explode() стока, принимаемая во втором параметре, разбивается на подстроки по разделителю, передаваемому в первом параметре (в нашем случае это символ пробела).

Для получения разности между двумя числами, представленными в виде строк, можно воспользоваться функцией bcsub():

<?php
$diff_time = bcsub($stop_time, $start_time, 5);
?>

Здесь 5 - число знаков после запятой. Таким образом код, вычисляющий время генерации страницы, выглядит так:

<?php
$start_time = gettime();

// Здесь код, формирующий страницу

$stop_time = gettime();
$diff_time = bcsub($stop_time, $start_time, 5);
echo '<p>Страница сформирована за '.$diff_time.' сек.</p>';

// Вспомогательная функция
function gettime()
{
  $part_time = explode(' ', microtime());
  $real_time = $part_time[1].substr($part_time[0], 1);
  return $real_time;
}
?>

Сортировка результатов SQL-запроса

Сортировка результатов SQL-запроса производится при помощи конструкции ORDER BY, после которой указывается имя столбца, который подвергается сортировке. Если после имени столбца указано ключевое слово ASC, сортировка производится по возрастанию, если же указано ключевое слово DESC, то сортировка будет по убыванию. Таким образом, задача сводится к динамическому формированию SQL-запроса, в конструкцию ORDER BY которого подставлялись бы имена выбранных столбцов и порядок сортировки. Для этого будем использовать запрос вида

$query = "SELECT * FROM products WHERE 1 ORDER BY ".$orderby." ".$sort;

где переменная $orderby будет содержать имя столбца, а $sort принимать значение ASC или DESC, в зависимости от того, какой вид сортировки выбран.

<?php
$dblocation = "localhost";   // Имя сервера
$dbuser     = "root";        // Имя пользователя
$dbpswrd    = "";            // Пароль
$dbname     = "catalog";     // Имя базы данных

// Соединение с сервером базы данных
$dblink = mysql_connect( $dblocation, $dbuser, $dbpswrd );
mysql_query( 'SET NAMES cp1251' );
// Выбираем базу данных
mysql_select_db( $dbname, $dblink );

// По умолчанию сортировка по наименованию, по возрастанию
$orderby = 'title';
$sort = 'ASC';
if ( isset( $_GET['orderby'] ) and isset( $_GET['sort'] ) ) {
  if ( in_array( $_GET['orderby'], array( 'code', 'title', 'price' ) ) ) $orderby = $_GET['orderby'];
  if ( in_array( $_GET['sort'], array( 'ASC', 'DESC' ) ) ) $sort = $_GET['sort'];
}

$query = 'SELECT code, title, description, price
          FROM products
          ORDER BY '
.$orderby.' '.$sort;
$res = mysql_query( $query );
echo '<h1>Каталог продукции</h1>'."\n";
// Выводим "шапку" таблицы
echo '<table border="1" cellpadding="4" cellspacing="0" style="border-collapse: collapse; empty-cells: show">'."\n";
echo '<tr>';
if ( $sort == 'ASC' ) {
  $tmp = 'DESC';
  $image = 'down.gif';
} else {
  $tmp = 'ASC';
  $image = 'up.gif';
}
if ( $orderby == 'code' )
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=code&sort='.$tmp.'">Код</a>&nbsp;<img src="'.$image.'" alt="" /></th>';
else
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=code&sort=ASC">Код</a></th>';
if ( $orderby == 'title' )
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=title&sort='.$tmp.'">Наименование</a>&nbsp;<img src="'.$image.'" alt="" /></th>';
else
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=title&sort=ASC">Наименование</a></th>';
echo '<th>Описание</th>';
if ( $orderby == 'price' )
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=price&sort='.$tmp.'">Цена</a>&nbsp;<img src="'.$image.'" alt="" /></th>';
else
  echo '<th><a href="'.$_SERVER['PHP_SELF'].'?orderby=price&sort=ASC">Цена</a></th>';
echo '</tr>'."\n";
while( $prd = mysql_fetch_array( $res ) ) {
  echo '<tr>';
  echo '<td>'.$prd['code'].'</td>'."\n";
  echo '<td>'.$prd['title'].'</td>'."\n";
  echo '<td>'.$prd['description'].'</td>'."\n";
  echo '<td>'.$prd['price'].'</td>'."\n";   
  echo '</tr>'."\n";
}
echo '</table>'."\n";
?>

Посмотреть рабочий пример можно здесь.