Кеширование в Cotonti. Техническое руководство

Кеш — сохранённая копия того, что сайт уже один раз посчитал или сгенерировал. Что это и зачем? Как работает кеширование файлов в cotonti? Управление дисковым кешем в админке

0 Published Filed under: Cotonti Siena CMF > Cotonti - reading materials. Documentation.
Кеширование в Cotonti. Техническое руководство

Кеширование в Cotonti

Что это и зачем

Кеш — сохранённая копия того, что сайт уже один раз посчитал или сгенерировал. Вместо того чтобы каждый раз заново собирать страницу из базы, шаблонов и PHP-кода, Cotonti достаёт готовый результат из хранилища. Это ускоряет сайт и снижает нагрузку на сервер и базу данных.

Какие уровни кеша есть в Cotonti

В движке четыре независимых хранилища:

  1. Дисковый кеш (File). Файлы в папке cache_dir. Работает всегда, если папка доступна для записи.
  2. Кеш в базе данных (MySQL). Таблица cot_cache с полями имя / область / срок жизни / значение. Используется по умолчанию для «средних» данных.
  3. Кеш в памяти (Memcache / APC / XCache). Самый быстрый. Работает только если на сервере установлено соответствующее расширение PHP. При перезапуске сервиса данные из памяти пропадают.
  4. Статический кеш страниц (Page cache). Готовый HTML целой страницы, сжатый gzip, с заголовками Last-Modified и ETag. Отдаётся посетителю мгновенно, без обращения к PHP и БД.

Всеми четырьмя управляет одна общая надстройка Cache, у которой есть ссылки на каждый уровень отдельно: disk, db, mem, static.

Как это работает

Области (realm). Каждая запись принадлежит какой-то области: cot (по умолчанию), system, page, forums — обычно имя модуля или расширения. Область позволяет чистить кеш точечно — только то, что относится к конкретному разделу, не трогая остальное.

Срок жизни (TTL). У записи можно указать срок — сколько секунд она считается актуальной. По умолчанию для динамического кеша — 3600 секунд (1 час). У статического (File) срока нет, файл живёт до явного удаления.

Автоочистка (garbage collection). Для кеша в БД работает вероятностный сборщик: при создании объекта кеша примерно в 10% случаев происходит удаление записей с истёкшим сроком.

Статический кеш страниц. Перед выдачей страницы Cotonti проверяет, есть ли готовая копия. Если есть и она не устарела, посетителю уходят HTTP-заголовки 304 Not Modified либо сразу готовый gzip-html. Если копия отсутствует — генерируется новой.

Ограничение по размеру. Кеш в БД не принимает объекты больше ~16 МБ (предел типа MEDIUMTEXT). Более крупные значения в БД не сохраняются.

Где чистить кеш в админке

  • Дисковый кеш. Админ-панель → Other → Disk cache. Показывается список областей, число файлов и общий размер. Кнопки: Обновить (перечитать состояние) и Очистить всё (полностью стереть содержимое папки кеша). Напротив каждой области — своя кнопка удаления.
  • Кеш в БД и в памяти очищается программно — обычно через тот же административный раздел «Cache» (admin.cache.disk.php чистит только диск). Общая очистка всех уровней делается вызовом $cache->clear() из кода или через настройки движка (кнопка сброса кеша при изменении конфигурации).
  • Кеш шаблонов сбрасывается автоматически при их правке в админке.

Что защищено от удаления

При очистке дискового кеша не удаляются два файла в корне папки:

  • index.html — заглушка от просмотра содержимого папки в браузере.
  • .htaccess — правила доступа.

Они сохраняются всегда, в том числе при «Очистить всё».

Когда и зачем чистить дисковый кеш

Обязательно чистить:

  • После обновления движка или модулей — старые файлы могут конфликтовать с новым кодом.
  • После смены темы сайта — старая разметка может кешироваться и выдаваться вместо новой.
  • После массовой правки статей, категорий, настроек — кеш хранит устаревшие версии.
  • Если на сайте видны «призраки» — удалённый товар, изменённая цена, старый заголовок.

Полезно чистить:

  • Перед важным обновлением контента — чтобы посетители сразу увидели новое.
  • Если диск на сервере быстро заполняется — папка cache_dir иногда разрастается до гигабайт.

Не нужно чистить:

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

Что происходит после очистки

Первые посетители после очистки получат страницы, собранные «с нуля» — это на секунды нагрузит сервер и БД. Затем кеш снова наполнится, и сайт вернётся к обычной скорости. Никакие данные при очистке не теряются — удаляется только копия, оригинал (статьи, товары, настройки) остаётся в базе.

Кеширование в Cotonti. Техническое руководство

Материал построен на анализе файлов: system/cache.php (класс Cache, драйверы), system/admin/admin.cache.disk.php, system/admin/tpl/admin.cache.disk.tpl. Никаких предположений — только то, что видно в исходниках.


1. Архитектура

Единая точка входа — класс Cache, который держит ссылки на четыре независимых драйвера:

public $disk;    // File_cache      — статический, файловый
public $db;      // Db_cache_driver — временный, в MySQL
public $mem;     // Temporary_cache_driver — в памяти (Memcache/APC/XCache)
public $static;  // Page_cache      — целые HTML-страницы

Управляется одной инициализацией Cache::init(), которая поднимает каждый драйвер по очереди. Если драйвер недоступен (папка не пишется, расширение PHP не установлено) — в $this->mem остаётся false, но остальные продолжают работать.

Всего четыре константы типа кеша для точечной очистки:

COT_CACHE_TYPE_ALL     = 0
COT_CACHE_TYPE_DISK    = 1
COT_CACHE_TYPE_DB      = 2
COT_CACHE_TYPE_MEMORY  = 3
COT_CACHE_TYPE_STATIC  = 4
COT_CACHE_TYPE_DEFAULT = COT_CACHE_TYPE_DB

Константы COT_DEFAULT_REALM = 'cot' и COT_DEFAULT_TTL = 3600 (1 час) — значения по умолчанию для всех драйверов.


2. Иерархия классов драйверов

Абстрактные классы:

  • Cache_driver— базовый. Методы clear(), exists(), get(), remove().
  • Static_cache_driver— добавляет store($id, $data, $realm) без TTL. Живёт до явного удаления.
  • Dynamic_cache_driver— добавляет store($id, $data, $realm, $ttl = COT_DEFAULT_TTL). С TTL.
  • Writeback_cache_driver(наследник Dynamic) — копит изменения в памяти и пишет их одним пакетом в flush() на __destruct. Даёт remove_now() и store_now() для немедленной записи в обход буфера.
  • Db_cache_driver(наследник Writeback) — добавляет get_all($realm) для загрузки всех значений области в глобальную область видимости.
  • Temporary_cache_driver(наследник Dynamic) — добавляет inc(), dec(), get_info() и get_ini_size().

Реальные драйверы:

КлассРодительТипУсловие загрузки
File_cacheStatic_cache_driverДискВсегда
MySQL_cacheDb_cache_driverБДВсегда
Memcache_driverTemporary_cache_driverПамятьextension_loaded('memcache')
APC_driverTemporary_cache_driverПамятьextension_loaded('apc')
Xcache_driverTemporary_cache_driverПамятьextension_loaded('xcache')

Класс Page_cacheне наследуется ни от чего — это самостоятельный контроллер статических страниц.

Список доступных драйверов ведётся в массиве $cot_cache_drivers при загрузке файла.


3. Область (realm)

Каждая запись кеша привязана к области. Это строковое имя — по умолчанию cot, но может быть любым: system, page, forums, market, имя плагина.

Область участвует в:

  • Идентификации: ключ = realm . '/' . id (для Memcache, APC, XCache).
  • Файловом пути: cache_dir/<realm>/<id> (для File_cache).
  • SQL-условии: WHERE c_realm = '...' (для MySQL_cache).
  • Выборочной очистке: clear_realm($realm, $type).

Автозагрузка при инициализации: Cache::init() формирует список областей $cot_cache_autoload, куда всегда попадают system и cot, плюс текущий Cot::$env['ext'], плюс значения, дописанные ранее. Все эти области загружаются из БД в глобальную область видимости через MySQL_cache::get_all().

Это значит: переменные, сохранённые в этих областях, доступны в PHP как $имя_переменной сразу после init(), без явного get().


4. Драйвер File_cache

Конструктор: принимает корневую папку (cache_dir по умолчанию). Если папки нет — создаёт с правами 0755. Если не пишется — бросает Exception. Папка обязательна.

Формат хранения: <cache_dir>/<realm>/<id>, содержимое — serialize($data). Без gzip.

exists($id, $realm, $ttl = 0): проверяет file_exists и, если TTL > 0, что time() - filemtime < $ttl.

get(): если запись существует и не истекла — unserialize(file_get_contents(...)), иначе NULL.

store(): создаёт папку области при необходимости, пишет serialize в файл.

remove(): удаляет файл, возвращает bool.

clear($realm = '', $exceptRealms = ['assets', 'static', 'htmlpurifier', 'templates']):

  • Если указан $realm — чистит только эту папку и удаляет её саму.
  • Если пусто — обходит все подпапки cache_dir, кроме перечисленных в $exceptRealms.
  • Всегда сохраняет index.html и .htaccess в корне кеша — их не удаляет ни при каких условиях.
  • Удаление рекурсивное: файлы, затем подпапки, затем саму папку.

Исключённые области не чистятся никогда при clear() без параметров. Это защита от потери статики сайта (ассеты темы), кеша HTMLPurifier (тяжело пересобирается) и кеша шаблонов.


5. Драйвер MySQL_cache

Работает через буфер в памяти и записывает всё пакетом. Таблица — Cot::$db->cache (обычно cot_cache).

Конструктор: с вероятностью 10% (условие mt_rand(1, 10) == 5) вызывает gc() — удаление записей с истёкшим TTL.

__destruct(): вызывает flush(). То есть все изменения уходят в БД в самом конце скрипта, одним запросом.

flush():

  • Для removed_data формирует один DELETE ... WHERE (c_name=... AND c_realm=...) OR ....
  • Для writeback_data формирует INSERT ... VALUES (...), (...), ... ON DUPLICATE KEY UPDATE c_value=VALUES(c_value), c_expire=VALUES(c_expire).
  • c_expire = 0 означает бессрочное хранение.

store(): проверяет длину serialize($data) — если больше 16 777 215 байт (предел MEDIUMTEXT), возвращает false без записи.

store_now() / remove_now(): пишут в БД немедленно, в обход буфера. Используются, когда данные нужны другим процессам прямо сейчас.

get_all($realm): выбирает значения из БД и через global ${$row['c_name']} создаёт/перезаписывает переменные в глобальной области. Возвращает количество загруженных записей.

exists(): после первого обращения к записи кладёт её в буфер $this->buffer[$realm][$id], повторные обращения идут из памяти.


6. Драйверы в памяти

Все три (Memcache, APC, XCache) наследуют Temporary_cache_driver и работают с ключом realm . '/' . id.

Memcache дополнительно префиксует ключ через createKey(): md5(Cot::$cfg['site_id'] . $key). Это позволяет нескольким сайтам использовать один Memcached-сервер без коллизий. clear() для Memcache не поддерживает очистку конкретной области — вызывает полный flush(), стирая всё.

APC при переполнении памяти (свободно < 20%) сам вызывает $this->clear() перед записью. Хранит serialize($data), читает с unserialize().

XCache при clear($realm) использует хак xcache_unset_by_prefix — обёртку над xcache_clear_cache(XC_TYPE_VAR, 0), которая по факту чистит всё, а не только по префиксу.

Все три получают информацию о памяти через get_info(). Если у драйвера нет данных (например, Memcache не отвечает) — возвращает массив с нулями или -1.


7. Выбор драйвера памяти

В Cache::init():

Cot::$cfg['cache_drv'] .= '_driver';
if (in_array(Cot::$cfg['cache_drv'], $cot_cache_drivers)) {
    $selected = Cot::$cfg['cache_drv'];
}

То есть в конфиге $cfg['cache_drv'] хранится короткое имя (memcache, apc, xcache), а код дописывает суффикс _driver и ищет полученное имя в списке загруженных драйверов.

После создания объекта проверяется get_info()['max']. Если максимум ≤ 1024 байт (то есть расширение установлено, но кеш не работает), драйвер не принимается, $this->mem = false.

Если $cfg['cache_drv'] не совпадает ни с одним драйвером — $this->mem = false. Кеш в памяти просто не используется.


8. Контроллер Cache

Публичные методы:

  • init() — поднимает все четыре драйвера. Вызывается один раз при старте.
  • bind($event, $id, $realm, $type) — привязывает событие к записи кеша. При срабатывании события запись автоматически удаляется.
  • bind_array($bindings) — пакетная версия bind.
  • unbind($realm, $id = '') — снять привязки. Без $id — все из области.
  • trigger($event) — запустить событие, удалить все привязанные записи, вернуть число удалённых.
  • clear($type = COT_CACHE_TYPE_ALL) — очистить всё или определённый тип.
  • clear_realm($realm, $type = COT_CACHE_TYPE_ALL) — очистить конкретную область.
  • get_info() — информация о памяти (от текущего memory-драйвера или пусто).

Магические свойства:

  • mem_available — true, если memory-драйвер работает.
  • mem_driver — имя выбранного драйвера (Memcache_driver и т. п.).

Защита от повторной синхронизации: если в течение запроса были bind(), bind_array() или unbind(), ставится флаг resync_on_exit, и в __destruct() перечитываются привязки.

Важный нюанс. В исходниках функции resync_bindings() код закомментирован (строки SELECT/INSERT в БД). То есть механизм привязок декларирован, но в текущей версии не работает полностью: bind() пишет в таблицу cot_cache_bindings, а trigger() ищет привязки в пустом массиве $this->bindings и всегда возвращает 0.

Практический вывод: автоматическая инвалидация по событиям не работает. Очистку кеша нужно делать явно через $cache->clear_realm(...) или $cache->disk->remove(...).


9. Статический кеш страниц (Page_cache)

Хранит целый HTML страницы, сжатый gzip. Расположен в <cache_dir>/static/.

Инициализация:

$pageCache->init($path, $name, $exclude = [], $ext = '');
  • $path — путь-«папка» кеша внутри static/.
  • $name — базовое имя файла.
  • $exclude — GET-параметры, которые игнорируются при формировании имени.
  • $ext — расширение файла (если нужно).

Имя файла = path/name + _ + md5(serialize(GET-args)) + sha1(...) + .ext. Параметры сортируются ksort перед хешированием.

initByUri($uri, ...)— вариант с автоматическим вычислением пути. Разбирает URI, берёт c и e из query string, формирует путь. Если установлена функция cot_staticCacheGetPathByUri (расширение), делегирует ей.

read()— если файл есть:

  • Считает ETag = md5(имя + размер + mtime).
  • Если пришёл заголовок If-None-Match со совпадающим ETag и If-Modified-Since >= mtime — отправляет 304 Not Modified и выходит.
  • Иначе — Last-Modified, ETag, Expires: Mon, 01 Apr 1974 00:00:00 GMT, Cache-Control: must-revalidate, proxy-revalidate.
  • Если клиент не принимает gzip — readgzfile(), иначе Content-Encoding: gzip + сырое содержимое.
  • Всегда завершается exit — дальнейший код не выполняется.

write()— если кеш включён, создаёт папку пути и пишет gzencode(cot_outputFilters(ob_get_contents())). То есть сжатый gzip результат всех выходных фильтров.

clear($path, $withSubDirectories = false)— удаляет все файлы в папке (и подпапки, если указано).

disable()— отключает кеш для текущего запроса (например, если пришёл авторизованный пользователь).

Папка staticвсегда в списке $exceptRealms для File_cache::clear() — общая очистка дискового кеша её не тронет.


10. Управление дисковым кешем в админке

Файл system/admin/admin.cache.disk.php доступен только при $usr['isadmin'] == true. Хуки: admin.cache.disk.first, admin.cache.disk.loop, admin.cache.disk.tags.

Действия:

  • a=purge — вызывает cot_diskcache_clearall(), дополнительно удаляет из БД запись cot_rc_html (кеш консолидации ресурсов), редиректит обратно.
  • a=delete&id=<имя> — удаляет одну папку или один файл. Значение id=COT_DISKCACHE_ONLYFILES ('*files*') означает «файлы в корне кеша, без подпапок».

Защита от подстановок: проверяется, что id не содержит / и \, не равен . или ...

Функции просмотра:

  • cot_diskcache_calc($dir, $do_subdirs = true) — рекурсивно считает файлы и размер папки.
  • cot_diskcache_list() — возвращает массив «имя папки → [файлов, байт]». Плюс строка для корневых файлов под именем *files*.
  • cot_diskcache_clear($dir, $do_subdirs = true, $rm_dir = false) — рекурсивное удаление.
  • cot_diskcache_clearall() — чистит корень без подпапок, затем каждую подпапку с удалением.

Что не удаляется: ни при каком действии не трогаются <cache_dir>/index.html и <cache_dir>/.htaccess.

UI (admin.cache.disk.tpl): таблица «Item | Files | Size | Delete», кнопки «Обновить» и «Очистить всё», в подвале — общее число файлов и суммарный размер.


11. Конфигурационные параметры

Из кода используются:

  • $cfg['cache_dir'] — корневая папка дискового кеша. Обязательна.
  • $cfg['cache_drv'] — имя memory-драйвера (memcache, apc, xcache). Пустая строка — memory-кеш не используется.
  • $cfg['cache_drv_host'] — хост для Memcache.
  • $cfg['cache_drv_port'] — порт для Memcache.
  • $cfg['site_id'] — используется Memcache для разделения ключей между сайтами на одном сервере.
  • $cfg['dir_perms'] — права на создаваемые папки.

Плюс константы в глобальной области:

  • $cot_cache_drivers — список загруженных memory-драйверов.
  • $cot_cache_autoload — массив областей для автозагрузки.
  • $cot_cache_bindings — устаревший массив; в текущей версии не заполняется.

12. Реальные примеры использования

Запись в БД-кеш со сроком жизни 5 минут:

Cot::$cache->db->store('my_data', $value, 'myrealm', 300);

Чтение:

$value = Cot::$cache->db->get('my_data', 'myrealm');
if ($value === null) {
    // кеш промахнулся — считаем и сохраняем
    $value = calc();
    Cot::$cache->db->store('my_data', $value, 'myrealm', 300);
}

Запись немедленно (в обход буфера) — нужно, когда другой процесс должен увидеть данные сразу:

Cot::$cache->db->store_now('my_data', $value, 'myrealm', 300);

Запись в память, если доступна, с фолбэком на БД:

if (Cot::$cache->mem) {
    Cot::$cache->mem->store('my_data', $value, 'myrealm', 300);
} else {
    Cot::$cache->db->store('my_data', $value, 'myrealm', 300);
}

Очистка всей области во всех слоях:

Cot::$cache->clear_realm('myrealm', COT_CACHE_TYPE_ALL);

Точечное удаление одной записи во всех слоях:

$id = 'my_data';
$realm = 'myrealm';
Cot::$cache->disk->remove($id, $realm);
Cot::$cache->db->remove($id, $realm);
if (Cot::$cache->mem) {
    Cot::$cache->mem->remove($id, $realm);
}

Автозагрузка переменной из БД-кеша в глобальную область:

Достаточно в Cache::init() расширить $cot_cache_autoload именем области. После этого переменные области будут доступны как глобальные.


13. Особенности и подводные камни

Буферизация записи в БД-драйвере. store() не пишет в базу сразу — только накапливает. Если процесс упадёт до __destruct(), данные не сохранятся. Для критичных случаев используйте store_now().

Проверка размера в БД. Значения больше ~16 МБ не запишутся, store() вернёт false без ошибки.

Очистка memory-кеша. У Memcache и XCache очистка конкретной области фактически сбрасывает всё хранилище. Это надо учитывать при совместном использовании сервера несколькими сайтами.

Page_cache завершает скрипт. Если read() нашёл страницу — вызывается exit. Весь оставшийся PHP не выполнится. Это значит, что динамические блоки (приветствие пользователя, корзина) в такую страницу не попадут.

Инвалидация по событиям не работает. Как указано выше, в текущей версии ядра trigger() ничего не удаляет — массив $this->bindings пуст. Придётся чистить вручную.

cache_drv в конфиге хранит короткое имя. Реальный класс называется <имя>_driver, суффикс дописывается кодом.

Корневые index.html и .htaccess неприкосновенны. Не пытайтесь удалить их скриптом — они всё равно не удалятся через штатные функции.

Примеры файлов с хуками для admin.cache.disk.php

Хуки в Cotonti регистрируются в заголовке каждого файла-обработчика, а не в setup-файле. Ниже — три отдельных файла, по одному на каждый хук этого документа.


1. admin.cache.disk.first

Вызывается в начале admin.cache.disk.php — до обработки purge и delete.

Файл plugins/cacheguard/cacheguard.admin.cache.disk.first.php:

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=admin.cache.disk.first
Order=10
[END_COT_EXT]
==================== */

/**
 * Запрещает очистку дискового кеша в рабочее время (будни, 9:00–18:00).
 * В остальное время очистка работает как обычно.
 *
 * @package cacheguard
 * @version 1.0.0
 * @author webitproff
 * @copyright (c) 2026 webitproff
 * @license BSD
 */

defined('COT_CODE') or die('Wrong URL.');

$hour = (int) date('G');
$dow  = (int) date('N'); // 1 = Пн ... 7 = Вс

// Будни, рабочее время — блокируем очистку
if ($dow <= 5 && $hour >= 9 && $hour < 18) {
    if (in_array($a, ['purge', 'delete'], true)) {
        cot_message('Очистка кеша запрещена в рабочее время (9:00–18:00 по будням).');
        cot_redirect(cot_url('admin', ['m' => 'cache', 's' => 'disk'], '', true));
    }
}

Что делает: перехватывает запросы на purge и delete в рабочее время, разворачивает администратора обратно с сообщением.


2. admin.cache.disk.loop

Вызывается внутри цикла по областям кеша (foreach ($row as $i => $x)), для каждой строки таблицы.

Файл plugins/cacheguard/cacheguard.admin.cache.disk.loop.php:

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=admin.cache.disk.loop
Order=10
[END_COT_EXT]
==================== */

/**
 * Добавляет в строку таблицы кеша пользовательскую заметку:
 * для области "static" — сколько страниц закешировано,
 * для остальных — пусто.
 *
 * @package cacheguard
 * @version 1.0.0
 * @author webitproff
 * @copyright (c) 2026 webitproff
 * @license BSD
 */

defined('COT_CODE') or die('Wrong URL.');

if ($i === 'static') {
    // В области static кешируются целые страницы, файлы — обычные .gz
    $t->assign(
        'ADMIN_DISKCACHE_ITEM_NOTE',
        '<span class="text-muted">Кеш страниц: ' . (int) $x[0] . ' файлов</span>'
    );
} else {
    $t->assign('ADMIN_DISKCACHE_ITEM_NOTE', '');
}

В шаблоне admin.cache.disk.tpl внутри блока ADMIN_DISKCACHE_ROW добавить колонку:

<td class="textcenter">{ADMIN_DISKCACHE_ITEM_NOTE}</td>

Что делает: для области static выводит отдельную заметку в строке таблицы. Для остальных областей — ничего.


3. admin.cache.disk.tags

Вызывается в самом конце admin.cache.disk.php — перед $t->parse('MAIN').

Файл plugins/cacheguard/cacheguard.admin.cache.disk.tags.php:

<?php
/* ====================
[BEGIN_COT_EXT]
Hooks=admin.cache.disk.tags
Order=10
[END_COT_EXT]
==================== */

/**
 * Добавляет в шаблон страницы дискового кеша:
 * — общий размер кеша в мегабайтах,
 * — предупреждение, если размер превышает 500 МБ.
 *
 * @package cacheguard
 * @version 1.0.0
 * @author webitproff
 * @copyright (c) 2026 webitproff
 * @license BSD
 */

defined('COT_CODE') or die('Wrong URL.');

$mbTotal = round($cachesize / 1048576, 2);

$t->assign([
    'ADMIN_DISKCACHE_TOTAL_MB' => $mbTotal,
    'ADMIN_DISKCACHE_SIZE_WARNING' => ($mbTotal > 500)
        ? '<div class="alert alert-warning">Дисковый кеш превышает 500 МБ. Рекомендуется очистить.</div>'
        : '',
]);

В admin.cache.disk.tpl добавить:

{ADMIN_DISKCACHE_SIZE_WARNING}
<p class="text-muted">Всего на диске: {ADMIN_DISKCACHE_TOTAL_MB} МБ</p>

Что делает: добавляет предупреждение при превышении 500 МБ и точный размер кеша в МБ.


Файл cacheguard.setup.php (без регистрации хуков)

В setup-файле никакой регистрации хуков быть не должно — она в заголовках выше. Setup-файл только описывает само расширение:

<?php
/* ====================
[BEGIN_COT_EXT]
Name=Cache Guard
Description=Защита и мониторинг дискового кеша
Version=1.0.0
Date=2026-01-01
Author=webitproff
Copyright=(c) 2026 webitproff
Notes=
Auth_guests=R
Lock_guests=W12345A
Auth_members=R
Lock_members=W12345A
[END_COT_EXT]
==================== */

defined('COT_CODE') or die('Wrong URL.');

Как это работает

  • Cotonti при установке плагина сканирует все файлы cacheguard.*.php в папке плагина.
  • У каждого файла читает блок [BEGIN_COT_EXT] из первых строк и смотрит значение Hooks=....
  • Записывает пару «плагин → файл → хук» в таблицу cot_plugins.
  • При вызове cot_getextplugins('admin.cache.disk.first') ядро находит все плагины, зарегистрированные на этот хук, и подключает их файлы через include.
  • Order в заголовке задаёт порядок вызова, если на один хук подписано несколько плагинов. По умолчанию — 10.

Один плагин может объявлять несколько хуков — по одному в каждом файле. Файл .setup.php для этого не нужен.

No comments yet
Only registered users can post new comments
webitproff
webitproff

Offline

Last logged: 2026-10-12 18:21

About me briefly
Support and development of web projects on the CMF Cotonti: private messengers via the website, open and closed small social networks, trading platforms and marketplaces, freelance and services exchange portal, catalogs of goods from wholesale suppliers, dropshipping platforms, online stores, and much more.
Telegram for messages
@webitproff
Telegram channel
@s/aBuyFILE
Public profile
  • Date published 2026-10-11 15:40
  • Updated 2026-10-11 15:40