Система управления «Сайт PRO»
Версия 20240107
  • Сайт PRO
  • Знакомство с системой управления

Знакомство с системой управления

Общие сведения

Термины и определения

URL – адрес страницы сайта. Страница сайта отображается при открытии этого адреса в браузере.

Объект – см. Объект в PHP. Каждый объект относится к определенному классу, имеет определенный набор свойств и методов.

Корневая папка – папка с файлами на севере, соответствующая URL Главной страницы сайта.

Концепция системы управления

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

Отображение информации происходит по следующей схеме:

  • Информация загружается из базы данных
  • На основе загруженных данных формируются объекты
  • Выбираются подходящие шаблоны отображения информации
  • Шаблоны заполняются данными из объектов и формируют страницу сайта

Редактирование информации на сайте происходит по следующей схеме:

  • Редактор сайта вызывает функцию редактирования данных на странице
  • Редактор заполняет открывшуюся форму редактирования данных
  • На основании введенных данных формируются объекты
  • Свойства этих объектов сохраняются в базе данных

Отображение информации

Основные файлы

При отображении любой страницы сайта, в том числе несуществующей, вызывается файл index.php в корне сайта. В этом файле могут быть сделаны любые глобальные настройки, которые должны быть применены до начала работы системы управления. Например, таким образом можно настроить Главное зеркало. Чтобы сделать перенаправление со всех доменов сайта на Главное зеркало, в начале index.php можно использовать следующий код:

if ($_SERVER['HTTP_HOST'] !== 'www.ru') {
    header('Location: http://www.ru' . $_SERVER['REQUEST_URI'], true, 301);
    header('Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0');
    header('Expires: ' . gmdate('D, j M Y H:i:s') . ' GMT');
    header('Pragma: no-cache');
    return;
}

Здесь www.ru необходимо заменить на адрес Главного зеркала.

Затем вызывается файл cms/main.php, который выполняет все необходимые действия по отображению информации на странице сайта. При этом подключаются все необходимые классы, создаются все необходимые объекты, из базы данных загружаются все необходимые данные.

Затем вызывается файл cms/html/template.index.php – Главный шаблон. В этом файле содержится основная HTML-разметка всех страниц: <!DOCTYPE>, <html>, <head>, <body> и остальные элементы, необходимые для отображения страницы. Для изменения HTML-разметки всех страниц сайта необходимо отредактировать этот файл. В качестве языка шаблонов используется стандартный язык PHP. Программирование шаблонов ничем не отличается от обычного программирования PHP-скриптов. Кроме того, в шаблонах могут быть использованы специальные переменные, определенные системой управления.

Файлы CSS подключаются стандартным образом. Чаще всего CSS-стили задаются в файле style.css в корневой папке сайта. Но это никак не регламентируется системой управления, и ссылка на этот файл может быть изменена.

Основные переменные

Перечисленные ниже переменные доступны в любом из шаблонов системы управления, в том числе в template.index.php. Доступ к API системы осуществляется через эти переменные:

$root – путь к корневой папке сайта.

Если необходимо прочитать файл, то полный путь к этому файлу может быть получен с использованием $root. Например:

file_get_contents("$root/style.css");

if (file_exists("$root/about/index.php")) {
    // ...
}

$App – главный объект для инициализации системы управления.

Объекты в системе управления создаются и инициализируются по требованию. $App предоставляет необходимое API для работы с объектами. Объект $App создается в файле cms/app.php. В начале работы скрипта, а также в том случае, когда неизвестно, были ли подключены необходимые классы, можно получить этот объект следующим образом:

$App = include('cms/app.php');

В том случае, когда известно, что необходимые классы системы уже были подключены, можно получить этот объект следующим образом:

$App = \Cms\Site\App::getInstance();

Как правило, у разработчиков не возникает необходимости напрямую использовать объект $App. Но в некоторых случаях это бывает необходимо. Например, для создания нового объекта, расширяющего функциональность системы.

$Conf - объект для работы с конфигурацией сайта.

Настройки сайта хранятся в файле cms/conf.php в виде массива. Объект $Conf позволяет осуществлять доступ к этим настройкам, читать и сохранять файл конфигурации. Примеры:

print $Conf->get('title');

$param = 'count';
$value = $Conf->get($param);
$value ++;
$Conf->set($param, $value);
$Conf->save();

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

$Data – объект для работы с базой данных.

Данный объект позволяет выполнять произвольные SQL-запросы к базе данных и получать результаты для их обработки. Наиболее типичный пример использования при этом выглядит так:

$query = "SELECT * FROM `table` WHERE `field`='value'";
if ($result = $Data->query($query)) {
    while ($row = $Data->fetch($result)) {
        var_dump($row);
        // array( 'field' => 'value', ... )
    }
}

Можно использовать более компактную аналогичную по функциональности запись:

$query = "SELECT * FROM `table` WHERE `field`='value'";
foreach ($Data->getRows($query) as $row) {
    var_dump($row);
    // array( 'field' => 'value', ... )
}

В случае, если требуется получить единственную (первую) запись:

$query = "SELECT * FROM `table` WHERE `field`='value' LIMIT 1";
$row = $Data->getRow($query);

В случае, если требуется получить значение единственного поля единственной (или первой) записи:

$query = "SELECT `field` FROM `table` WHERE `field`='value' LIMIT 1";
$value = $Data->dLookup($query);

Если в качестве значений параметров запроса используются недетерминированные строковые данные, то соответствующие значения должны быть экранированы для защиты от SQL-инъекций:

$param = $_GET['param'];
$query = "SELECT * FROM `table` WHERE `field`=" . $Data->quote($param);
if ($result = $Data->query($query)) {
    // ...
}

Крайне не рекомендуется использовать некоторые распространенные способы защиты от SQL-инъекций:

// Возможна SQL-инъекция, если $param == "' OR '1'='1":
$query = "SELECT * FROM `table` WHERE `field`='$param'";

// Возможна потеря части символов:
$query = "SELECT * FROM `table` WHERE `field`='" . str_replace("'", "", $param) . "'";

// Возможно использование управляющих последовательностей символов:
$query = "SELECT * FROM `table` WHERE `field`='" . addslashes($param) . "'";

Все функции системы управления, которые принимают в качестве параметра результат запроса $Data->query(), также могут принимать в качестве параметра массив. Эта функциональность позволяет произвольным образом обработать данные, после чего передать их другим функциям. Например:

$rows = $Data->getRows("SELECT * FROM `table` WHERE `field`='value'");
foreach ($rows as $i => $row) $rows[$i]['i'] = $i;
while ($row = $Data->fetch($rows)) {
    var_dump($row);
    // array( 'field' => 'value', 'i' => 0, ... )
    // array( 'field' => 'value', 'i' => 1, ... )
    // array( 'field' => 'value', 'i' => 2, ... )
    // ...
}

Объект $Data сохраняет информацию об ошибке в результате последнего невыполненного запроса. Например, если SQL-запрос не был выполнен из-за ошибки синтаксиса. По умолчанию, данная информация об ошибке нигде не отображается. Но ее можно отобразить на странице:

if (!$Data->query("SELECT *")) {
    print $Data->getError();
    // Ошибка запроса «SELECT *» No tables used
}

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

$Auth – объект с информацией об аутентификации и авторизации посетителя.

Информация о том, вошел ли посетитель на сайт, хранится в свойстве $Auth->login. Информация о том, является ли пользователь Администратором сайта, хранится в свойстве $Auth->admin. Примеры:

if ($Auth->admin) {
    // Администратор сайта
} elseif ($Auth->login) {
    // Вошел на сайт, но не является Администратором
} else {
    // Анонимный посетитель
}

$Main – объект для выполнения стандартных действий при отображении страницы сайта.

Данный объект содержит большое количество методов общего назначения. Например:

  • $Main->displayTitle() отображает заголовок сайта в тэге <title>
  • $Main->displayH1() отображает заголовок <h1>
  • $Main->displayPager() отображает список с постраничной разбивкой

$Form – объект для управления формами ввода данных на сайте.

Данные объект используется как для работы с формами, предназначенными для Администратора, так и для работы с формами для конечного посетителя. Например, для создания, отображения и отправки формы обратной связи.

Иерархия классов

При использовании системы управления все необходимые классы подключаются автоматически через механизм автоматической загрузки. Каждый класс, используемый системой управления, может быть доступен в двух пространствах имён:

  • \Cms\Root – эти классы определены в ядре системы и недоступны для модификации
  • \Cms\Site – эти классы определяются разработчиком сайта и полностью находятся под его контролем

Каждый класс пространства имён \Cms\Site должен являться наследником соответствующего класса пространства имён \Cms\Root или другого класса пространства имён \Cms\Site. Для переопределения какой-либо функциональности системы управления необходимо создать класс в пространстве имён \Cms\Site, переопределяющий необходимые методы.

Примеры:

Если требуется выполнять определенное действие при сохранении настроек сайта:
Настройки сохраняются с помощью метода $Conf->save(), определенного в классе \Cms\Root\Conf. Разработчик сайта может создать класс namespace Cms\Site; class Conf extends \Cms\Root\Conf и определить в нем метод save(), который будет выполнять требуемые действия и вызывать parent::save() родительского класса

Если при отображении заголовка <h1> требуется выполнять автозамену определенных слов, при этом данные в базе не должны меняться:
Заголовок <h1> отображается с помощью метода $Main->displayH1(). Разработчик сайта может создать класс namespace Cms\Site; class Main extends \Cms\Root\Main и определить в нем метод displayH1(), который будет вызывать parent::displayH1() родительского класса и затем выполнять автозамену.

Для того, чтобы функция автоматической загрузки корректно работала, классы должны быть определены в файлах с именами, сформированными по определенным правилам.

Классы пространства имён \Cms\Root определяются в файлах в папке cms/root-20240107, где 20240107 – это версия системы управления, а имя файла должно иметь вид *.php, где * – это последний компонент названия класса в нижнем регистре. Например, класс \Cms\Root\Conf определяется в файле cms/root-20240107/conf.php.

Классы пространства имён \Cms\Site определяются, соответственно, в файлах в папке cms/site.

Класс с более длинным именем (например, \Cms\Site\Page\Type) должен быть определен во вложенной папке (в примере выше, cms/site/page/type.php). В общем виде, для загрузки класса используется файл, соответствующий имени класса в нижнем регистре, в котором символы \ заменены на /, в конце добавлено .php, и компонент cms/root в начале пути заменен на cms/root-20240107 с указанием версии системы управления.

По умолчанию, папка cms/site пуста, никакие классы системы управления не переопределены, используются только классы пространства имён \Cms\Root.

Иерархия классов системы управления следующая:

  • \Cms\Site\Base extends \Cms\Root\Base – базовый класс для всех объектов. Для расширения функциональности к абсолютно всем объектам системы используется переопределить этот класс
  • namespace Cms\Site; class Conf extends \Cms\Root\Conf – класс используется для расширения функциональности объекта $Conf
  • namespace Cms\Site; class Data extends \Cms\Root\Data – класс используется для расширения функциональности объекта $Data
  • namespace Cms\Site; class Auth extends \Cms\Root\Auth – класс используется для расширения функциональности объекта $Auth
  • namespace Cms\Site; class Main extends \Cms\Root\Main – класс используется для расширения функциональности объекта $Main
  • namespace Cms\Site; class Form extends \Cms\Root\Form – класс используется для расширения функциональности объекта $Form
  • namespace Cms\Site; class Page extends \Cms\Root\Page – класс для расширения функциональности объектов, представляющих страницы сайта

Все методы всех классов системы управления определены как public и доступны для переопределения. Более подробно этот список классов и методов рассмотрен в API системы.

Этапы обработки запроса

Отображение статических файлов (картинок, стилей CSS, скриптов JS), как правило, выполняется непосредственно веб-сервером без участия интерпретатора PHP. Интерпретатор PHP задействуется только в том случае, если запрошена существующая страница сайта или если файл не найден (ошибка 404). При этом запускается файл index.php в корневой папке сайта, который вызывает файл cms/main.php. С помощью этого файла создается объект $App и вызывается метод $App->__main().

В процессе работы этого метода выполняется преобразование URL в идентификатор страницы, которая должна быть отображена. Правила преобразования следующие:

  • URL страницы нормализуется. При этом удаляются параметры, следующие за ?, и index.php в конце URL. Удаляются суффиксы .html и .php. Несколько идущих подряд / или . заменяются одним символом
  • Если запрашивается Главная страница, нормализованный URL которой /, то идентификатор страницы -
  • Если в нормализованном URL только один /, то идентификатор страницы – это нормализованный URL без / в начале
  • В остальных случаях идентификатор страницы – это нормализованный URL

URL нормализуется с помощью метода $Main->getSelf($href = null), а URL (нормализованный или нет) преобразуется в идентификатор страницы с помощью метода $Main->getId($href = null). Примеры:

print $Main->getId("/index.php");
// "-"

print $Main->getId("/about.html");
// "about"

print $Main->getId("/catalog/price.html");
// "/catalog/price"

print $Main->getId()
// $Main->getId($_SERVER['REQUEST_URI'])

Затем выполняется поиск страницы с запрашиваемым идентификатором в базе данных. Создается объект $Page. Если страница найдена в базе данных, то $Page в качестве свойств получает информацию из базы данных. Если страница не найдена, то добавляется свойство $Page->created = true.

Затем вызывается Главный шаблон – файл cms/html/template.index.php. В нем доступны все перечисленные выше объекты и переменные: $root, $App, $Conf, $Data, $Auth, $Main, $Form, $Page.