Категории форума

Механизм хуков в Cotonti. Как это работает? Примеры.

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


webitproff
webitproff • 14.05.2026 14:23 #1

 

В Cotonti механизм хуков работает так:

В нужном месте, где нужно "вклинить" или "повесить" свой код, - нужно прописать "крючок", то есть хук, на который будем вешать свой пользовательский код, а сделать это можно вызовом функции в нужном участке кода, например:


// Удаление товара предварительно - хук на который вешаем удаление переводов товара
foreach (cot_getextplugins('market.delete.first') as $pl) {
    include $pl;
}

         
То есть при запуске файла MarketControlService.php

до хука

// Хук для дополнительных действий после удаления
foreach (cot_getextplugins('market.delete.done') as $pl) {
    include $pl;
}

система сама ищет файлы в папках плагинов, где в заголовке указано Hooks=market.delete.first.

Файл plugins/i18n4marketpro/i18n4marketpro.market.delete.first.php как раз содержит такой заголовок и удаляет переводы. 
Затем продолжается выполнение кода и удаление товара.

В Cotonti хук — это способ для плагинов выполнить свой код в строго определённых местах ядра или модулей.
Разработчик модуля market разместил в методе MarketControlService::delete() вызов:
 

foreach (cot_getextplugins('market.delete.first') as $pl) {
   include $pl;
}

 

Этот код ищет все файлы плагинов, у которых в самом начале есть секция:
 

/* ====================
[BEGIN_COT_EXT]
Hooks=market.delete.first
[END_COT_EXT]
==================== */

 

Когда плагин i18n4marketpro активен, Cotonti находит его файл
plugins/i18n4marketpro/i18n4marketpro.market.delete.first.php, и при заходе в delete() включает его содержимое через include.
Внутри этого файла выполняется удаление записей из таблицы cot_i18n4marketpro_pages:
 

if (Cot::$db->tableExists('cot_i18n4marketpro_pages')) {
   Cot::$db->delete(Cot::$db->i18n4marketpro_pages, 'ipage_id = ?', $id);
}

 

Таким образом, до того как удалится сам товар, сначала удаляются его переводы.
Это решает проблему: внешний ключ fk_translation_market больше не блокирует удаление, и скрипт не проваливается в валидацию пустой формы.

Если плагин отключён, Cotonti игнорирует его хуки.
cot_getextplugins('market.delete.first') не находит ни одного файла, цикл ничего не включает, переводы остаются в базе, и при попытке удалить товар база данных выдаёт ошибку «Cannot delete or update a parent row: a foreign key constraint fails».
Именно эта ошибка перехватывается catch (Throwable $e) и приводит к return false в delete().
А так как код market.edit.php после неудачного удаления продолжает выполняться, он запускает cot_market_validate() с пустыми данными, и пользователь видит ошибки «Код категории бла-бла пиндец» и т.д.

Кратко: хуки позволяют плагинам «вклиниваться» в процесс удаления товара или другой нужный разработчику.
Сейчас вызов хука в MarketControlService::delete() уже написан - теперь можно писать файлы в плагинах с заголовком Hooks=market.delete.first и быть уверенным в том, что логика куда в этих файлах будет выполняться при обращении к нашему крючку в MarketControlService.php.
 

написано в образовательных целях для контекста и картины в целом!

 

При работе, стремимся к тому, что бы придерживаться штатных хуков, и логики как в файле ниже:

<?php
/**
* [BEGIN_COT_EXT]
* Hooks=market.delete.done
* [END_COT_EXT]
*/
/**
* featuredtopicsmarket.market.delete.done.php - Delete links on product delete
*
* featuredtopicsmarket plugin for Cotonti 0.9.26, PHP 8.4+
* Filename: featuredtopicsmarket.market.delete.done.php
*
* Date: May 14Th, 2026
* @package featuredtopicsmarket
* @version 2.7.8
* @author webitproff
* @copyright Copyright (c) webitproff 2026 | https://github.com/webitproff
* @license BSD
*/
defined('COT_CODE') or die('Wrong URL');
require_once cot_incfile('featuredtopicsmarket', 'plug'); 
global $db, $db_featured_topics_market, $id;
if ($id > 0)
{
   $db->delete($db_featured_topics_market, "rtm_from_id = ? OR rtm_to_id = ?", [$id, $id]);
}
/* просто как шпаргалка
    global $db, $db_x, $id;
    if ($id > 0) {
        $table = $db_x . 'featured_topics_market';
        $db->delete($table, "rtm_from_id = ? OR rtm_to_id = ?", [$id, $id]);
    } 
*/

 

 

Отредактировано: webitproff (14.05.2026 16:04, 2 месяца назад)
🗿

🧙‍♂️ Радуйся, странниче добрый и честный! Не понапрасну привела тя стезя в земли сии. Зде бо мужи мудры и искусники дела писменнаго и численнаго, что куют словеса и плетут узоры кода, тайны разгадывают и знанием делятся, летописи множа и ремесло цифровое творя.
⬅️ Аще налево пойдеши — обрящеши грамоты древния, писания старинныя и свитки учения. ⬆️ Аще прямо — слово мудрое и совет от мужей разумеющих, что в деле кодописном искусны, получиши. ➡️ Аще направо — сам в писцы и летописцы внидеши, и в ремесло цифровое, где строки и знаки в дело живое обращаются, слово свое в память веков вложиши.
📝 Не медли же — нареки имя свое, и вниди в чин наш, и стань с нами в братстве, где код есть магия, а строки — заклятия живыя, числом и буквою слово едины суть.
🏰 Не тайно есть собрание сие, и не инициации в нем, но многое сокрыто от пришлых и ступалого, понеже не всякому открывается знание, но токмо ищущим и пребывающим в деле сем.