Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Журнал Начинающего Программиста



Здравствуйте,


SSI — с чем его едят и как готовят.

Server Side Includes — инклюды, способы применения, переменные



Возможно вам известно, что SSI часто употребляется в качестве инструмента для вставки инклюдов, особенно при программировании серверной части сайта использовался CGI или Perl.
Но какой в этом смысл при программировании на PHP, если PHP имеет свои собственные инклюды: <?php include ("filename.php"); ?> или <?php include_once ("filename.php"); ?>?

Дело в том, что мы, как небольшая компания часто работаем с разными программистами, или выполняем только часть работы — например дизайн и верстку. Часть из программистов работает на CGI/Perl, другие на PHP.
Не всегда мы получаем сайт на поддержку — сделали и ушли. Знакомая ситуация? Что делать клиенту, который получил сайт, со временем захотел доделать что-либо, но по тем, или иным причинам утратил связь с программистом, который исполнял работу? — Искать другого, конечно.
Нет, программиста найти не проблема. Но что если сайт написан на PHP, а ваш программист всем хорош, но пишет, к примеру на Perl? — Переделывать весь сайт ради одного модуля — невыгодно, нанимать еще кого-то — тоже не всегда удобно.

Вот тут-то и приходит на помощь SSI. Дело в том, что директивы SSI могут работать в файлах .html (.htm) и выполняются на уровне сервера. Именно поэтому работают они очень быстро и не затрачивая лишних ресурсов сервера. А язык настолько прост, что практически вся его документация может поместиться на одной странице.

Это и плюс, и минус — возможностей немного, но и времени на изучение языка нужно потратить минимум. А результат полностью это оправдывает.

Типы файлов, в которых сервер будет искать и выполнять директивы SSI можно переопределить в файле .htaccess. По умолчанию это файлы с расширением .shtml, .stm или .shtm
Чтобы добавить в этот список файлы .html напишем в файл .htaccess пару строк (сделать это можно в любой программе, работающей с текстовыми файлами, к примеру в Блокноте):

Options +Includes
AddHandler server-parsed .html

.htaccess — это файл конфигурации веб-серверов типа Apache. Его директивы выглядят также, как и основной конфигурационный файл сервера, но действуют только в тех каталогах (папках), в которых расположены, и в их дочерних папках.
Большинство хостинг-провайдеров разрешают клиентам размещать собственные файлы .htaccess. И чаще всего, при виртуальном хостинге — это единственный способ управления вашим веб-сервером.

Чтобы использовать SSI-инклюды в любом каталоге, файл .htaccess с вышеуказанными строками должен располагаться в корневой папке сайта.

SSI-инклюды

Теперь у нас есть возможность воспользоваться SSI. Из самого названия (Server Side Includes) следует, что эта технология предназначена прежде всего для включения содержимого (или результатов работы скриптов) одного файла в другой. С этого и начнем.

Любая директива SSI заключается в знак условных комментариев и отличается только наличием знака «#» («решетки»):

<!--#SSI-команда параметр="значение" -->

А наш инклюд будет выглядеть так:

<!--#include virtual="included_file.html" -->

Параметр virtual позволяет задать путь к подключаемому файлу в привычном виде — относительном, или абсолютном пути к файлу.

Допустим, что наш сайт — это вполне обычный сайт с шапкой, верхней и нижней навигацией, боковой колонкой (сайдбаром), и подвалом (футером). А исходный код страницы выглядит примерно так:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>SSI</title>
<meta http-equiv="keywords" content="ssi, includes" />
<meta http-equiv="description" content="Использование инклюдов SSI" />
<link href="/styles/main.css" rel="stylesheet" type="text/css" media="all" />
<script type="text/javascript" src="/jscripts/main.js" language="javascript">
</script>
</head>
<body>
<div id="container">
<div id="header">
<h2><a href="/">Это наш логотип в шапке</a></h2>
<ul id="navigation">
<li><a href="/">главная</a></li>
<li><a href="/services/">услуги</a></li>
<li><a href="/articles/">статьи</a></li>
<li><a href="/about/">о компании</a></li>
<li><a href="/contact/">контакт</a></li>
</ul><!-- end #navigation -->
<!-- end #header --></div>
<div id="mainContent">
<h1>Использование инклюдов SSI</h1>
<p>Тут у нас какой-то основной контент страницы</p>
<!-- end #mainContent --></div>
<div id="sidebar">
<h3>Тут у нас сайдбар</h3>
<p>А это текст в боковой колонке</p>
<!-- end #sidebar --></div>
<div id="footer">
<p id="bottom_navigation">
<a href="/">главная</a>
<a href="/services/">услуги</a>
<a href="/articles/">статьи</a>
<a href="/about/">о компании</a>
<a href="/contact/">контакт</a>
</p>
<!-- end #footer --></div>
<!-- end #container --></div>
</body>
</html>

Что мы видим?

На всех страницах нашего сайта одинаковые шапка и подвал, и у нас всего один или несколько вариантов содержимого для боковой колонки. Значит эти фрагменты можно сделать общими для всех страниц. Тогда, чтобы допустим, поменять шапку на всем сайте нам потребуется отредактировать всего лишь один файл.
Выносим общие фрагменты в отдельные файлы — header.html, sidebar.html и footer.html и складываем эти файлы в одну папку для удобства. Скажем, папку /ssi/.
А вместо этих фрагментов в файл впишем соответствующие инклюды.
Вот так теперь будет выглядеть наш основной файл:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>SSI</title>
<meta http-equiv="keywords" content="ssi, includes" />
<meta http-equiv="description" content="Использование инклюдов SSI" />
<link href="/styles/main.css" rel="stylesheet" type="text/css" media="all" />
<script type="text/javascript" src="/jscripts/main.js" language="javascript">
</script>
</head>
<body>
<div id="container">
<!--#include virtual="/ssi/header.html" -->
<div id="mainContent">
<h1>Использование инклюдов SSI</h1>
<p>Тут у нас какой-то основной контент страницы</p>
<!-- end #mainContent --></div>
<!--#include virtual="/ssi/sidebar.html" -->
<!--#include virtual="/ssi/footer.html" -->
<!-- end #container --></div>
</body>
</html>

Мы используем абсолютные пути для всех инклюдов и залинкованных файлов — жестко указанные относительно корневой папки сайта. Тогда все будет работать, в какой бы папке не располагались другие файлы вашего сайта с теми же инклюдами и прилинкованными файлами.

Меню навигации на SSI

Теперь перейдем к навигации и сделаем так, чтобы страница не ссылалась сама на себя и посетители видели, на какой странице сайта они находятся.
Для этого мы воспользуемся командами if — elif — else — endif и предопределенной переменной DOCUMENT_URI, которая указывает абсоютный путь к файлу, в котором она вызвана.
Откроем файл /ssi/header.html, в котором находится код нашей «шапки» с верхней навигацией. И допишем условия — на каких страницах и как она должна показываться:

<div id="header">
<h2><!--#if expr="$DOCUMENT_URI!=/^\/index.html/" -->
<a href="/">Это наш логотип в шапке</a>
<!--#else -->
<span>Это наш логотип в шапке</span>
<!--#endif --></h2>
<ul id="navigation">
<li>
<!--#if expr="$DOCUMENT_URI!=/^\/index.html/" -->
<a href="/"><a href="/">главная</a>
<!--#else --><span>главная</span>
<!--#endif -->
</li>
<li>
<!--#if expr="$DOCUMENT_URI=/\/services\/index.html/" -->
<span>услуги</span>
<!--#elif expr="$DOCUMENT_URI=/\/services\//" -->
<a class="current" href="/services/">услуги</a>
<!--#else -->
<a href="/services/">услуги</a>
<!--#endif -->
</li>
<li>
<!--#if expr="$DOCUMENT_URI=/\/articles\/index.html/" -->
<span>статьи</span>
<!--#elif expr="$DOCUMENT_URI=/\/articles\//" -->
<a class="current" href="/articles/">статьи</a>
<!--#else -->
<a href="/articles/">статьи</a>
<!--#endif -->
</li>
<li>
<!--#if expr="$DOCUMENT_URI=/\/about\/index.html/" -->
<span>о компании</span>
<!--#elif expr="$DOCUMENT_URI=/\/about\//" -->
<a class="current" href="/about/">о компании</a>
<!--#else -->
<a href="/about/">о компании</a>
<!--#endif -->
</li>
<li>
<!--#if expr="$DOCUMENT_URI!=/\/contact\//" -->
<a href="/contact/">контакт</a>
<!--#else -->
<span>контакт</span>
<!--#endif -->
</li>
</ul><!-- end #navigation -->
<!-- end #header --></div>

Параметр expr указывает на то, что переменная будет тестироваться на соответствие указанному регулярному выражению.
В итоге, на странице /services/index.html в меню будет <span>услуги</span>, в любом другом файле в папке /services/ — <a class="current" href="/services/">услуги</a>, а на всех остальных страницах сайта — <a href="/services/">услуги</a>. И нам остается только прописать соответствующие стили для отображения пунктов меню в CSS.

Показываем разное содержимое в одном и том же блоке на разных страницах

Таким же образом можно выбрать другое содержимое для какого-либо блока для показа на отдельных страницах. Например — в сайдбаре (файл /ssi/sidebar.html).

<div id="sidebar">
<h3>Тут у нас сайдбар</h3>
<!--#if expr="$DOCUMENT_URI!=/\/contact\//" -->
<p>Это текст в боковой колонке будет показан на всех страницах,
кроме тех страниц, файлы которых расположены в папке /contact/</p>
<!--#else -->
<p>А этот текст будет показан только на тех страницах,
файлы которых расположены в папке /contact/</p>
<!--#endif -->
<!-- end #sidebar --></div>

Вставка результатов работы серверных скриптов

А что же с файлами PHP и остальными серверными скриптами? — А то же самое — их тоже подключаем инклюдами SSI.
Если нам нужно передать в исполняемый серверный скрипт результаты GET-запроса — например, у нас на сайте есть страница, которая должна выводить результаты поиска и запрос выглядит как http://mysite.com/search.html?query=javascript
В этом случае мы прибавляем к линку на скрипт наш запрос с помощью переменной QUERY_STRING:

 <!--#include virtual="/ssi/search.php?$QUERY_STRING" -->

В файле search.php мы получаем запрос с помощью $_GET['query'] и выдаем соответствующий результат.

Для запуска скриптов CGI есть специальная команда — exec:

<!--#exec cgi="/cgi-bin/myscript.pl"-->

Вывод даты и времени

Замечательно было бы в копирайтах на десятках ваших сайтов не исправлять каждый год цифирку, а? ;)

  2009 - <!--#config timefmt="%Y" --><!--#echo var="DATE_LOCAL"-->

Выведет 2009 — 2010 (в этом году ;) )

Параметры для timefmt:

Формат Описание Пример
 %a Краткое название дня недели Mon
 %A Полное название дня недели Monday
 %b Аббревиатура названия месяца Dec
 %B Полное название месяца December
 %d День месяца 01 (не 1)
 %D Дата в формате «%m/%d/%y» 12/31/99
 %e День месяца 13
 %H Часы в 24-часовом формате 13
 %I Часы в 12-часовом формате 01
 %j День года 235
 %m Номер месяца 01
 %M Минуты 03
 %p AM/PM (до полудня/после) AM
 %r Время в формате «I:M:S p» 11:35:46 PM
 %S Секунды 34
 %s Время в секундах с 01.01.1970 957228726
 %T Время в формате «%H:%M:%S» 14:05:34
 %U Неделя года 16
 %w Номер дня недели 4
 %y Год в формате ГГ 99
 %Y Год в формате ГГГГ 1999
 %Z Временная зона MSK

Дата по-русски:

<!-- Получаем сегодняшнее число -->
<!--#config timefmt="%d" -->
<!--#set var="DT" value="$DATE_LOCAL"-->
<!-- Получаем день недели -->
<!--#config timefmt="%w" -->
<!--#set var="N" value="$DATE_LOCAL"-->
<!--#if expr="$N=1" -->
<!--#set var="D" value="Понедельник" -->
<!--#elif expr="$N=2" -->
<!--#set var="D" value="Вторник" -->
<!--#elif expr="$N=3" -->
<!--#set var="D" value="Среда" -->
<!--#elif expr="$N=4" -->
<!--#set var="D" value="Четверг" -->
<!--#elif expr="$N=5" -->
<!--#set var="D" value="Пятница" -->
<!--#elif expr="$N=6" -->
<!--#set var="D" value="Суббота" -->
<!--#else -->
<!--#set var="D" value="Воскресенье" -->
<!--#endif -->
<!-- Получаем название месяца -->
<!--#config timefmt="%m" -->
<!--#set var="NM" value="$DATE_LOCAL"-->
<!--#if expr="$NM=01" -->
<!--#set var="M" value="Января" -->
<!--#elif expr="$NM=02" -->
<!--#set var="M" value="Февраля" -->
<!--#elif expr="$NM=03" -->
<!--#set var="M" value="Марта" -->
<!--#elif expr="$NM=04" -->
<!--#set var="M" value="Апреля" -->
<!--#elif expr="$NM=05" -->
<!--#set var="M" value="Мая" -->
<!--#elif expr="$NM=06" -->
<!--#set var="M" value="Июня" -->
<!--#elif expr="$NM=07" -->
<!--#set var="M" value="Июля" -->
<!--#elif expr="$NM=08" -->
<!--#set var="M" value="Августа" -->
<!--#elif expr="$NM=09" -->
<!--#set var="M" value="Сентября" -->
<!--#elif expr="$NM=10" -->
<!--#set var="M" value="Октября" -->
<!--#elif expr="$NM=11" -->
<!--#set var="M" value="Ноября" -->
<!--#else -->
<!--#set var="M" value="Декабря" -->
<!--#endif -->
<!-- Получаем год -->
<!--#config timefmt="%Y" --><!--#set var="Y" value="$DATE_LOCAL" -->
<!-- Выводим дату -->
<p>Сегодня у нас на сервере <!--#echo var="D" -->,
<!--#echo var="DT" --> <!--#echo var="M" --> <!--#echo var="Y"--> года</p>

...Хотя как раз это я бы сделал иным способом — много букоф... :)
Время естественно выводится серверное, а не время у юзера, как в случае вывода с помощью JavaScript.

Вывод размера и даты последней модификации файла

Параметры вывода размера определяются с помощью sizefmt: «abbrev» — в килобайтах, «bytes» — в байтах.

Размер файла /index.html:
<!--#config sizefmt="abbrev"-->
<!--#fsize virtual="/index.html"-->
Файл изменен
<!--#config timefmt="%d.%m.%Y %H:%M:%S"-->
<!--#flastmod virtual="/index.html"-->

Для большинства случаев приведенных примеров будет достаточно.

Предопределенные переменные SSI

Список наиболее «интересных» из них:

  • DOCUMENT_ROOT (название основной папки для вебстраниц на сервере, обычно ваша папка public_html (www) и путь к ней)
  • HTTP_USER_AGENT (название и версия браузера, которым пользуется посетитель)
  • REMOTE_ADDR (IP-адрес посетителя)
  • REMOTE_HOST (адрес посетителя в нормальной форме — например, adsl53.peterlink.ru)
  • SERVER_ADDR (IP-адрес вашего сайта)
  • SERVER_NAME и HTTP_HOST (адрес сервера, типа userguide.webservis.ru)
  • DOCUMENT_URI, REQUEST_URI и SCRIPT_NAME (запрошенная вами страница, типа /examples/mysqlexample.shtml.)
  • DOCUMENT_NAME (имя файла (без каталогов) документа, запрошенного пользователем)
  • SCRIPT_FILENAME (полный путь к вебстранице на сервере. Например /home/home-webservis/public_html/ и так далее)
  • SERVER_SOFTWARE (название сервера, например, Apache/1.3.2 (Unix))
  • SERVER_ADMIN (почтовый адрес владельца сервера, указанный при установке)
  • DATE_LOCAL (сегодняшниее время и дата в вашем часовом поясе(для сервера))
  • DATE_GMT (текущее время по Гринвичу)
  • LAST_MODIFIED (дата последней модификации документа
  • HTTP_COOKIE (Строка Cookie).

Чтобы посмотреть все доступные предопределенные переменные воспользуйтесь командой

<!--#prinenv -->







 © 2010 LORD-EXPERT     • Forum   • Site     •


Ваши комментарии к рассылке. Архив рассылки


Общение/вопросы/и т.д.




В избранное