Данный документ описывает принципы работы модульной архитектуры Ultralight CRM и правила разработки модулей.
Ultralight CRM построена на модульной архитектуре, что позволяет расширять функциональность системы без изменения ядра. Модули могут добавлять новые сущности, интерфейсы, бизнес-логику и интеграции.
Каждый модуль представляет собой отдельную директорию в папке modules/ и имеет следующую структуру:
modules/
└── [ModuleName]/
├── init.php # Точка входа для установки
├── remove.php # Точка входа для удаления
├── info.json # Метаданные модуля
├── web.php # Маршруты модуля
├── client/ # Клиентские скрипты
│ ├── module.js
│ └── styles.css
├── Services/ # Бизнес-логика
│ └── ModuleService.php
├── views/ # Шаблоны представления
│ └── index.blade.php
└── database/ # Миграции и сидеры
├── migrations/
└── seeders/
info.jsonФайл метаданных модуля в формате JSON:
{
"module-id": "ModuleName",
"name": "Название модуля",
"version": "1.0.0",
"description": "Описание модуля",
"author": "Имя автора",
"license": "Тип лицензии",
"dependencies": [
"ДругойМодуль"
]
}
init.phpТочка входа для установки модуля. Должна содержать функцию установки:
<?php
use App\Services\Modules\Api\CrmModulesInfo;
function initModule() {
// Регистрация сущностей
// Создание миграций
// Инициализация данных
// Подключение маршрутов
return true; // Успешная установка
}
remove.phpТочка входа для удаления модуля:
<?php
function removeModule() {
// Удаление миграций
// Очистка данных
// Отключение маршрутов
return true; // Успешное удаление
}
web.phpФайл маршрутов модуля:
<?php
use Illuminate\Support\Facades\Route;
Route::prefix('module/[ModuleName]')->group(function () {
Route::get('/', '[Controller]@index')->name('[module].index');
Route::get('/create', '[Controller]@create')->name('[module].create');
Route::post('/store', '[Controller]@store')->name('[module].store');
});
Центральный интерфейс для работы с модулями:
// Получить список всех модулей
CrmModulesInfo::getModulesList();
// Получить информацию о модуле
CrmModulesInfo::getModuleInfo('ModuleName');
// Получить версию ядра
CrmModulesInfo::getCoreVersion();
// Получить версию модуля
CrmModulesInfo::getInstalledModuleVersion('ModuleName');
API для работы с сущностями из модулей:
$entityId = CrmEntityApi::newEntityType('Project', 'App\\Models\\Project')
->addField('name', 'CHAR', 128)
->addField('status', 'CHAR', 32)
->addField('deadline', 'DATE')
->register();
$project = CrmEntityApi::create('Project') ->set('name', 'Новый проект') ->set('status', 'active') ->set('deadline', '2025-12-31') ->execute();
$projects = CrmEntityApi::find('Project', [
'FILTER' => [['status', '=', 'active']]
]);
CrmEntityApi::update($project, 'status', 'completed');
Установка выполняется через административный интерфейс или API:
init.phpПосле установки модуль:
Обновление выполняется по следующему алгоритму:
Удаление выполняется в следующем порядке:
remove.php# Создаем директорию модуля
mkdir modules/MyModule
# Создаем обязательные файлы
touch modules/MyModule/info.json
touch modules/MyModule/init.php
touch modules/MyModule/remove.php
touch modules/MyModule/web.php
// modules/MyModule/info.json
{
"module-id": "MyModule",
"name": "Мой модуль",
"version": "1.0.0",
"description": "Описание моего модуля",
"author": "Имя разработчика",
"license": "MIT",
"dependencies": []
}
// modules/MyModule/init.php
<?php
use App\Services\Modules\Api\CrmEntityApi;
function initModule() {
try {
// Регистрируем новый тип сущности
CrmEntityApi::newEntityType('Task', 'App\\Models\\Task')
->addField('title', 'CHAR', 255)
->addField('description', 'TEXT')
->addField('status', 'CHAR', 20)
->addField('priority', 'INTEGER')
->register();
return true;
} catch (Exception $e) {
return false;
}
}
// modules/MyModule/remove.php
<?php
function removeModule() {
try {
// Удаление миграций и данных будет выполнено автоматически
// Дополнительная очистка при необходимости
return true;
} catch (Exception $e) {
return false;
}
}
// modules/MyModule/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ModuleController;
Route::prefix('module/mymodule')->group(function () {
Route::get('/', [ModuleController::class, 'index'])->name('mymodule.index');
Route::get('/tasks', [ModuleController::class, 'tasks'])->name('mymodule.tasks');
Route::post('/tasks', [ModuleController::class, 'storeTask'])->name('mymodule.storeTask');
});
// app/Http/Controllers/ModuleController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Services\Modules\Api\CrmEntityApi;
class ModuleController extends Controller
{
public function index()
{
return view('module.mymodule.index');
}
public function tasks()
{
$tasks = CrmEntityApi::find('Task', [
'ORDER_BY' => ['priority', 'DESC']
]);
return view('module.mymodule.tasks', compact('tasks'));
}
public function storeTask(Request $request)
{
$task = CrmEntityApi::create('Task')
->set('title', $request->input('title'))
->set('description', $request->input('description'))
->set('status', 'new')
->set('priority', $request->input('priority', 1))
->execute();
return redirect()->route('mymodule.tasks');
}
}
{{-- resources/views/module/mymodule/index.blade.php --}}
@extends('app')
@section('content')
<div class="container">
<h1>Мой модуль</h1>
<p>Добро пожаловать в мой модуль!</p>
</div>
@endsection
/dub — отладочный эндпоинт для просмотра списка модулейinit.phpweb.php и кэш маршрутовМодульная архитектура Ultralight CRM предоставляет мощные возможности для расширения функциональности системы, сохраняя при этом стабильность и безопасность ядра.