Порядок загрузки модулей и классов в Koseven (Kohana)
Ключевой принцип Koseven: "Кто ниже в списке — тот важнее". Модули, объявленные позже, имеют более высокий приоритет и могут переопределять классы, конфиги и представления модулей, указанных ранее.
1. Каскадная файловая система (Cascading Filesystem)
Koseven использует каскадный поиск файлов. Когда фреймворку нужно найти класс, конфигурацию или представление, он проверяет пути в строгом порядке:
1. APPPATH
application/ — наивысший приоритет. Все, что лежит здесь, перекрывает всё остальное.
2. MODPATH (снизу вверх)
Модули из Kohana::modules(). Поиск идет с последнего к первому в списке.
3. SYSPATH
system/ — наинизший приоритет. Используется, если ничего не нашли выше.
2. Как происходит поиск класса? (на примере User)
При вызове класса User автозагрузчик ищет файл classes/User.php в следующем порядке:
| Порядок | Путь | Приоритет |
|---|---|---|
| 1 (самый высокий) | application/classes/User.php |
Всегда первый |
| 2 | application/modules/erp218_module_manager/classes/User.php |
Если модуль последний в списке |
| 3 | modules/auth/classes/User.php |
Если модуль первый в списке |
| 4 (самый низкий) | system/classes/User.php |
Всегда последний |
❗ Важно: Как только файл найден, он сразу подключается через require и поиск прекращается. Остальные файлы с таким же именем игнорируются. PHP не умеет "склеивать" части одного класса из разных файлов.
3. Как правильно "дополнить" класс (Transparent Extension)
Чтобы добавить функциональность без копирования всего класса, используйте наследование:
// system/classes/Kohana/User.php (оригинал)
class Kohana_User {
public function login() { /* ... */ }
}
// application/classes/User.php (ваше расширение)
class User extends Kohana_User {
// Ваши новые методы
public function login_with_2fa() { /* ... */ }
// Можно переопределить существующие
public function login() {
// Дополнительная логика
parent::login();
}
}
Теперь User будет иметь все методы из Kohana_User плюс ваши.
4. Правильный порядок модулей в Kohana::modules()
Располагайте модули от общих/инфраструктурных к частным/специфичным:
Kohana::modules(array(
// 1. Системные (фундамент)
'database' => MODPATH.'database',
'orm' => MODPATH.'orm',
'cache' => MODPATH.'cache',
// 2. Базовые сервисы (библиотеки)
'auth' => MODPATH.'auth',
'llm' => APPPATH.'modules/llm', // ← Базовый модуль, который используют другие
// 3. Ядро приложения
'entity' => APPPATH.'modules/entity',
'erp100_core' => APPPATH.'modules/erp100_core',
// 4. Функциональные модули (зависят от вышеперечисленных)
'erp118_links' => APPPATH.'modules/erp118_links',
'erp210_crm' => APPPATH.'modules/erp210_crm',
// 5. Специализированные/вспомогательные
'erp217_notification_center' => APPPATH.'modules/erp217_notification_center',
'erp218_module_manager' => APPPATH.'modules/erp218_module_manager',
));
✅ Правило: Если модуль A использует модуль B, то B должен стоять выше A в списке. Тогда A сможет использовать классы B, а при необходимости переопределить их — просто поместит свои файлы в свою папку.
5. Часто задаваемые вопросы
Q: Если класс есть и в application/classes/, и в модуле, что загрузится?
A: application/classes/ всегда имеет наивысший приоритет. Файл из модуля будет проигнорирован.
Q: Можно ли "дополнить" класс из модуля, не меняя его код?
A: Да, через наследование. Создайте в своем модуле (который ниже в списке) класс с тем же именем, но унаследованный от оригинального. Например, для Model_User из модуля auth создайте в своем модуле class Model_User extends Model_Auth_User.
Q: Что если два модуля внизу списка имеют одинаковые классы?
A: Приоритет у того, кто ниже (объявлен позже). Например, если erp218_module_manager и erp210_crm оба имеют classes/Helper.php, загрузится файл из erp218_module_manager, так как он стоит ниже.
Совет: При разработке модулей всегда учитывайте их зависимости. Сначала идут "строительные блоки" (база данных, ORM, авторизация), затем "бизнес-логика" (CRM, склад). Это обеспечит гибкость и возможность переопределения поведения на уровне приложения.