Что такое кэширование?

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

А можно просто один раз сформировать страницу и записать ее в файл. И при каждом запросе выдавать результат из файла, а не делать все заново. Это и есть кэширование. Оно позволяет снизить нагрузку на сервер и на базу данных.

Единственная проблема — это устаревание кэша. Допустим, что страница изменились, а кэш страницы — еще нет, и пользователю будет выдаваться старая версия. Способы борьбы:

  1. Выставлять более-менее приемлимое время устаревания кэша. Например, через 10 минут страница устаревает и кэш генерится заново.
  2. Сделать в административной части сайта кнопку «очистить кэш». В некоторых CMS вообще нет кнопки «очистить кэш», вместо нее есть кнопка «перегенерить сайт целиком». Нажимаем на эту кнопку — и весь сайт генерится в статичные файлы, то есть, фактически, в кэш.
  3. «Перегенерить сайт целиком» — ресурсоемкая операция. Гораздо лучше при редактировании страницы удалять кэш только той страницы, которую мы изменили. Но тут есть сложность: часто изменение одной страницы затрагивает и несколько других. Главное — понять, каких именно и очистить кэш у них тоже.

А теперь посмотрим, как мы можем применить полученные знания на практике. В начало скрипта, готорый генерит страницы нашего сайта поместим такой код:

<?php
// раздел настроек, которые вы можете менять
$cachedir = $_SERVER['DOCUMENT_ROOT'].'/cache/';
$cachetime = 3600; //время жизни кэша (1 час)

$thispage = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$cachelink = $cachedir.md5($thispage).".html";
if (file_exists($cachelink)) {
    $cachelink_time = filemtime($cachelink);
    // если кэш еще не устарел, читаем страницу из файла и отдаем браузеру
    if ((time() - $cachetime) < $cachelink_time) {
        readfile($cachelink);
        die();
    }
}
ob_start();
?>

А в конце скрипта добавим такие строчки

<?php
$fp = fopen($cachelink, 'w');
fwrite($fp, ob_get_contents());
fclose($fp);
ob_end_flush();
?>

Вот, собственно, и все. Все ваши страницы будут кэшироваться на 3600 секунд. Кэш страниц будет сохранен в папке cache.

Функции, которые мы использовали:

void ob_start()
Эта функция включает буферизацию вывода. Если буферизация вывода активна, никакой вывод скрипта не высылается (кроме headers); вывод сохраняется во внутреннем буфере. Содержимое этого внутреннего буфера может быть скопировано в строковую переменную с использованием ob_get_contents(). Для вывода содержимого этого внутреннего буфера используйте ob_end_flush(). Альтернативно ob_end_clean() втихую отбрасывает содержимое буфера.

string ob_get_contents()
Возвращает содержимое буфера вывода или FALSE, если буферизация вывода неактивна.

void ob_end_flush()
Эта функция отправляет содержимое буфера вывода (если оно имеется) и выключает буферизацию вывода. Если вы хотите в дальнейшем обработать содержимое буфера, вы должны вызвать ob_get_contents() до ob_end_flush(), так как содержимое буфера выбрасывается после вызова ob_end_flush().

Ссылки по теме:

Как сделать, чтобы записи в таблице нумеровались “без пробоев”?

Несколько раз слышал на форумах такой вопрос:

Как сделать, чтобы записи в таблице нумеровались «без пробоев», т.е. первичные ключи шли по порядку 1,2,3,4,5? Ведь когда я удаляю одну из записей, то получается что-то типа 1,2,4,5, а 3-го нет.

Первичный ключ нужен не для того, что бы по нему можно было строить красивые HTML-таблички c нумерацией и не для сортировки. Он нужен для идентификации записей, чтобы по его значению можно было найти единственную запись. Он нужен для того, чтобы одна таблица могла ссылаться на другую, но не для нумерации. Забудьте, что это число, это просто уникальное значение (кстати, в большинстве других современных баз данных так и есть).

Допустим, у нас на сайте есть каталог продукции. Таблица categories (группы товаров):

+-------------------------------+---------------------+
| category_id INT [PRIMARY KEY] | name VARCHAR(255)   |
+-------------------------------+---------------------+
| ............................. | ................... |
+-------------------------------+---------------------+

и таблица products (товары):

+------------------------------+-----------------+---------------------+
| product_id INT [PRIMARY KEY] | category_id INT | name VARCHAR(255)   |
+------------------------------+-----------------+---------------------+
| .............................| ................| ................... |
+------------------------------+-----------------+---------------------+

Мы завели товары, группы товаров, все связали между собой с помощью поля category_id в таблице products. Спустя какое-то время шеф решил убрать какую-то группу товаров. Вы её убираете, заполняете «дыры» в нумерации таблицы categories, а про то, что надо изменить все соответствующие записи в products случайно забыли.

И начинается самое интересное – часть товаров куда-то пропадает, часть волшебным образом «переносится» в другие группы. Мониторы продаются в книжном отделе, пиво в компьютерах и так далее. Да, конечно, вы все предусмотрите и ничего не забудете. Но зачем? Для того, чтобы иметь напротив каждой строки порядковый номер? Но нумеровать строки можно и нужно в скриптах. Вот простейший пример:

<?php
$i = 1;
$res = mysql_query('SELECT *  FROM products');
echo '<table>';
while( $row = mysql_fetch_array($res) )
{
  echo '<tr><td>'.$i.'</td><td>'.$row['name'].'</td></tr>';
  $i = $i + 1;
}
echo '</table>';
?>

Источник: http://phpfaq.ru

Удаление/редактирование строк таблицы БД

Когда я не знаю, что написать в своем блоге, я иду на форум. Вот уж где есть возможность выбрать тему для заметки! На любой вкус. Итак, внимание, вопрос:

Имеется таблица на сайте, в которой перечислены данные взятые из таблицы MySQL (типа id, название, описание, дата добавления и т.д…). Все работает прекрасно. Но когда я хочу что-то удалить или изменить в этой таблице приходится это делать через phpmyadmin. Как мне это сделать непосредственно на сайте, напрямую?

Имя   | Описание       | Дата доб. | Удалить | Редактировать
------------------------------------------------------------
Слон  | Большой, серый | 30-12-06  | Удл.    | Ред.

Вообще, такой скрипт - неотъемлемая часть любой CMS. Ведь вся информация, как правило, хранится в базе данных. И когда мы через админку добавляем, удаляем, редактируем новости или статьи - фактически, мы добавляем, удаляем, редактируем записи в таблице.

<?php

if ( !isset( $_GET["action"] ) ) $_GET["action"] = "showlist"
 
switch ( $_GET["action"] )
{
  case "showlist":    // Список всех записей в таблице БД
    show_list(); break;
  case "addform":     // Форма для добавления новой записи
    get_add_item_form(); break;
  case "add":         // Добавить новую запись в таблицу БД
    add_item(); break;
  case "editform":    // Форма для редактирования записи
    get_edit_item_form(); break;
  case "update":      // Обновить запись в таблице БД
    update_item(); break;
  case "delete":      // Удалить запись в таблице БД
    delete_item(); break;
  default:
    show_list();
}

// Функция выводит список всех записей в таблице БД
function show_list()
{
  $query = 'SELECT id, title, description FROM items WHERE 1';
  $res = mysql_query( $query );
  echo '<h2>Список</h2>';
  echo '<table border="1" cellpadding="2" cellspacing="0">';
  echo '<tr><th>ID</th><th>Наименование</th><th>Описание</th><th>Ред.</th><th>Удл.</th></tr>';
  while ( $item = mysql_fetch_array( $res ) )
  {
    echo '<tr>';
    echo '<td>'.$item['id'].'</td>';
    echo '<td>'.$item['title'].'</td>';
    echo '<td>'.$item['description'].'</td>';
    echo '<td><a href="'.$_SERVER['PHP_SELF'].'?action=editform&id='.$item['id'].'">Ред.</a></td>';
    echo '<td><a href="'.$_SERVER['PHP_SELF'].'?action=delete&id='.$item['id'].'">Удл.</a></td>';
    echo '</tr>';
  }
  echo '</table>';
  echo '<p><a href="'.$_SERVER['PHP_SELF'].'?action=addform">Добавить</a></p>'
}

// Функция формирует форму для добавления записи в таблице БД
function get_add_item_form()
{
  echo '<h2>Добавить</h2>'
  echo '<form name="addform" action="'.$_SERVER['PHP_SELF'].'?action=add" method="POST">';
  echo '<table>';
  echo '<tr>';
  echo '<td>Наименование</td>';
  echo '<td><input type="text" name="title" value="" /></td>';
  echo '</tr>';
  echo '<tr>';
  echo '<td>Описание</td>';
  echo '<td><textarea name="description"></textarea></td>';
  echo '</tr>';
  echo '<tr>';
  echo '<td><input type="submit" value="Сохранить"></td>';
  echo '<td><button type="button" onClick="history.back();">Отменить</button></td>';
  echo '</tr>';
  echo '</table>';
  echo '</form>';
}

// Функция добавляет новую запись в таблицу БД 
function add_item()
{
  $title = mysql_escape_string( $_POST['title'] );
  $description = mysql_escape_string( $_POST['description'] );
  $query = "INSERT INTO items (title, description) VALUES ('".$title."', '".$description."');";
  mysql_query ( $query );
  header( 'Location: '.$_SERVER['PHP_SELF'] );
  die();
}

// Функция формирует форму для редактирования записи в таблице БД
function get_edit_item_form()
{
  echo '<h2>Редактировать</h2>';
  $query = 'SELECT title, description FROM items WHERE id='.$_GET['id'];
  $res = mysql_query( $query );
  $item = mysql_fetch_array( $res );
  echo '<form name="editform" action="'.$_SERVER['PHP_SELF'].'?action=update&id='.$_GET['id'].'" method="POST">';
  echo '<table>';
  echo '<tr>';
  echo '<td>Наименование</td>';
  echo '<td><input type="text" name="title" value="'.$item['title'].'"></td>';
  echo '</tr>';
  echo '<tr>';
  echo '<td>Описание</td>';
  echo '<td><textarea name="description">'.$item['description'].'</textarea></td>';
  echo '</tr>';
  echo '<tr>';
  echo '<td><input type="submit" value="Сохранить"></td>';
  echo '<td><button type="button" onClick="history.back();">Отменить</button></td>';
  echo '</tr>';
  echo '</table>';
  echo '</form>';
}

// Функция обновляет запись в таблице БД 
function update_item()
{
  $title = mysql_escape_string( $_POST['title'] );
  $description = mysql_escape_string( $_POST['description'] );
  $query = "UPDATE items SET title='".$title."', description='".$description."'
            WHERE id="
.$_GET['id'];
  mysql_query ( $query );
  header( 'Location: '.$_SERVER['PHP_SELF'] );
  die();
}

// Функция удаляет запись в таблице БД
function delete_item()
{
  $query = "DELETE FROM items WHERE id=".$_GET['id'];
  mysql_query ( $query );
  header( 'Location: '.$_SERVER['PHP_SELF'] );
  die();
}
 
?>