SLOT-H: Создание модуля



Модуль в системе - это самодостаточный блок функциональности, который подключается автоматически при наличии определённой структуры. Для создания нового модуля достаточно добавить папку в директорию `Modules`.




Регистрация модуля



Перед созданием структуры модуля необходимо зарегистрировать его в ядре системы.

В файле `Application/Crud.php` добавить константу с именем модуля:

php
const MODULE_BLOG = 'Blog';

Включить модуль в список активных модулей:

php
public static $_modules = [
    Crud::MODULE_BASE => true,
    Crud::MODULE_FREE => true,
    Crud::MODULE_GEO => true,
    Crud::MODULE_BLOG => true
];

Базовая структура модуля


Минимальный модуль состоит из трёх обязательных файлов:

Bootstrap.php - определяет имя модуля и доступ для гостей

Crud.php - описывает права доступа и контроллеры

Preloader.php - выполняет предзагрузку (авторизация, проверка прав)

Дополнительные папки добавляются по мере необходимости:

Controllers - контроллеры модуля

Models - модели данных и DbTables

Views - шаблоны для каждого проекта

Public - CSS и JS для каждого проекта

Пример создания модуля Blog


1. Bootstrap.php


php
<?php

namespace Modules\Blog;

/**
 * Bootstrap class for the Blog module.
 *
 * @package   Modules\Blog
 */
class Bootstrap extends \Application\Bootstrap
{
    /**
     * Module name.
     *
     * @var string
     */
    public static $_module = \Application\Crud::MODULE_BLOG;

    /**
     * Guest access flag.
     *
     * @var bool
     */
    public static $_allow_guest = true;
}
`

2. Crud.php


php
<?php

namespace Modules\Blog;

use Application\Assistance\Controller\Controller as Cr;
use \Config\CC as C;

/**
 * CRUD configuration for the Blog module.
 *
 * @package   Modules\Blog
 */
class Crud extends \Application\Crud
{
    /** Module permission code */
    const MODULE_PERMISSION = 40;

    /** Permission code for Index controller */
    const INDEX_PERMISSION = 101;

    /** Index controller name */
    const INDEX_CONTROLLER = 'Index';

    /**
     * Get localized controller names.
     *
     * @return array Controller permission => localized name
     */
    public static function getNames()
    {
        return [
            self::INDEX_PERMISSION => 'Главная страница блога',
        ];
    }

    /**
     * Controller ID mapping (for permission system).
     *
     * @var array
     */
    public static $_ids = [
        self::INDEX_CONTROLLER => null,
    ];

    /**
     * List of controllers and their permission codes.
     *
     * @var array
     */
    public static $_controllers = [
        self::INDEX_CONTROLLER => self::INDEX_PERMISSION,
    ];

    /**
     * List of modules and their permissions.
     *
     * @var array
     */
    public static $_modules = [
        \Application\Crud::MODULE_BLOG => self::MODULE_PERMISSION
    ];

    /**
     * Access rules for module actions.
     *
     * @var array
     */
    public static $_rules = [
        self::MODULE_PERMISSION => [
            self::INDEX_PERMISSION => [
                Cr::INDEX_ACTION => Cr::READ_RULE
            ],
        ],
    ];
}
`

3. Preloader.php


php
<?php

namespace Modules\Blog;

use Application\Assistance\Controller\TraitGlobal;
use Config\CC as C;
use \Modules\Base\Models\DbTables as db;
use \Application\Assistance\Controller\Controller as Cr;

/**
 * Preloader for the Blog module.
 *
 * @package   Modules\Blog
 */
class Preloader
{
    use \Application\Assistance\Controller\TraitClass;

    /**
     * Initialize the preloader.
     *
     * @param \Application\Assistance\View\View $view    View object
     * @param \Application\Assistance\Request   $request Request object
     */
    public function __construct($view, $request)
    {
        // Check authentication via session/cookie
        if ($view->currentPrivate = \Modules\Base\Models\DbTables\PersonPrivate::checkAuth()) {
            // Load user data
            $view->currentPerson = $view->currentPrivate->linkPersonId();
            $view->currentProtected = $view->currentPerson->lotsPersonProtectedInBaseByPersonId();

            // Sync user preferences from cookies to database
            $this->checkPersonUpdates($view->currentPerson, $view->currentProtected);

            // Set user permissions
            $view->currentPerson->setPersonPermissions();

            // Enable translation mode if user has localization permission
            if ($view->currentPerson->checkRules(db\Rule::RULE_LOCALIZATION_CODE) && isset($_COOKIE[Cr::LOCALIZATION_COOKIE]) && $_COOKIE[Cr::LOCALIZATION_COOKIE] > 0) {
                \Config\CC::$_adminLocale = [];
            }
        }
    }
}
`

4. Добавление контроллера


Контроллеры создаются в папке Controllers. Каждый контроллер наследуется от базового контроллера системы.

php
<?php

namespace Modules\Blog\Controllers;

use \Modules\Blog\Models\DbTables as db;

/**
 * Blog Index controller.
 *
 * @package   Modules\Blog\Controllers
 */
class Index extends \Application\Assistance\Controller\Controller
{
    /**
     * Constructor.
     *
     * @param \Application\Assistance\Request $request Request object
     */
    public function __construct(\Application\Assistance\Request $request)
    {
        parent::__construct($request);
        $this->_actions = [];
    }

    /**
     * Index action.
     */
    public function indexAction()
    {
        $this->setViewPath()
            ->_view->setLayoutFree()
            ->append(['posts' => db\Post::getAll($this->_page)]);
    }
}
`

5. Добавление моделей


Модели создаются в папке Models. Для работы с базой данных требуется класс DbTable с описанием таблицы.

5.1 DbTables/Post.php


php
<?php

namespace Modules\Blog\Models\DbTables;

/**
 * Post database table class.
 *
 * @package   Modules\Blog\Models\DbTables
 *
 * @method static \Modules\Blog\Models\Post|\Modules\Blog\Models\Post[]|array|false getRow($ids = null, $page = false, $order = false, $model = true, $cache = true)
 * @method static \Modules\Blog\Models\Post[]|array|false getAll($page = false, $order = false, $model = true)
 */
class Post extends \Application\Assistance\DatabaseExtend
{
    /** Primary key field */
    const POST_ID = 'post_id';

    /** Post text content */
    const POST_TEXT = 'post_text';

    /** Post author */
    const POST_AUTHOR = 'post_author';

    /** Post creation time */
    const POST_TIME = 'post_time';

    /** Table name */
    public static $_table = 'posts';

    /** Primary key field */
    public static $_index = self::POST_ID;

    /**
     * Field definitions.
     *
     * @var array
     */
    public static $_fields = [
        self::POST_ID => [],
        self::POST_TEXT => [self::FP_TYPE => self::TYPE_TEXT],
        self::POST_AUTHOR => [self::FP_TYPE => self::TYPE_STRING],
        self::POST_TIME => [self::FP_TYPE => self::TYPE_INT],
    ];
}
`

5.2 Models/Post.php


php
<?php

namespace Modules\Blog\Models;

/**
 * Post model class.
 *
 * @package   Modules\Blog\Models
 *
 * @method int getPostId()
 * @method $this setPostId(int $post_id)
 * @method string getPostText()
 * @method $this setPostText(string $post_text)
 * @method string getPostAuthor()
 * @method $this setPostAuthor(string $post_author)
 * @method int getPostTime()
 * @method $this setPostTime(int $post_time)
 */
class Post extends \Application\Assistance\Model
{
    /** @var int Primary key */
    public $post_id;

    /** @var string Post text */
    public $post_text;

    /** @var string Post author */
    public $post_author;

    /** @var int Post creation time */
    public $post_time;
}
`

5.3 SQL для создания таблицы


sql
CREATE TABLE IF NOT EXISTS `posts` (
    `post_id` INT(11) NOT NULL AUTO_INCREMENT,
    `post_text` TEXT NOT NULL,
    `post_author` VARCHAR(255) NOT NULL,
    `post_time` INT(11) NOT NULL,
    `updated_at` DATETIME DEFAULT NULL,
    `deleted_at` DATETIME DEFAULT NULL,
    PRIMARY KEY (`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


6. Добавление представлений


Представления создаются в папке Views/Project_<номер проекта>/<имя контроллера>. Для каждого проекта могут быть свои представления.

6.1 Пример: Views/Project_1/Index/index.phtml



 php
<?php
use \Config\CC as C;

/** @var \Modules\Blog\Models\Post[] $posts */
/** @var \Application\Assistance\View\View $this */

$this->addEnvironment();
?>

<!-- код страницы, используя массив постов, переданных через ->append в контроллере -->

6.2 Добавление статики


CSS и JS файлы создаются в папках:

Public/css/Project_<номер проекта>/<имя контроллера>/index.css

Public/js/Project_<номер проекта>/<имя контроллера>/index.js

Структура готового модуля


text
Modules/Blog/
├── Bootstrap.php
├── Crud.php
├── Preloader.php
├── Controllers/
│   └── Index.php
├── Models/
│   ├── DbTables/
│   │   └── Post.php
│   └── Post.php
├── Public/
│   ├── css/
│   │   └── Project_1/
│   │       └── Index/
│   │           └── index.css
│   └── js/
│       └── Project_1/
│           └── Index/
│               └── index.js
└── Views/
    └── Project_1/
        └── Index/
            └── index.phtml

Завершение


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

bash
php Application/Tools/createAutoloader.php

Модуль становится доступным в системе. Можно переходить к настройке внешнего вида представления и стилей - они не влияют на работоспособность модуля.

Удаление модуля


Для удаления модуля достаточно удалить его папку из Modules и отключить (удалить его в классе Application/Crud). Система автоматически перестанет его загружать.

Важно: при удалении модуля необходимо также удалить его таблицы из базы данных, если они были созданы: не нужно плодить мусор в базе!




Что дальше?



- ➡️ Раздел 15. Структура базы данных
- ➡️ Раздел 16. Принципы ORM
- ➡️ Раздел 17. Методы работы