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

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

0 Опубликована Опубликовано в: Cotonti Siena CMF > Cotonti - чтиво. Документация.
Кеширование в 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 для этого не нужен.

Комментарии отсутствуют
Добавление комментариев доступно только зарегистрированным пользователям
webitproff
webitproff

Онлайн

Последняя авторизация: 11.10.2026 20:45

Обо мне кратко
Поддержка и разработка веб-проектов на CMF Cotonti: приватные мессенджеры через сайт, открытые и закрытые небольшие социальные сети, торговые площадки и маркетплейсы, портал биржи фриланса и услуг, каталоги товаров оптовых поставщиков, дропшиппинг-платформы, интернет-магазины и многое другое.
Смотреть разработки и скачать
Публичное портфолио моих работ и разработок
Телеграм для сообщений
@webitproff
Телеграм-канал
@s/aBuyFILE
Публичный профиль
  • Дата размещения 11.10.2026 15:40
  • Обновлено 11.10.2026 15:40