Розробка кастомного модуля ProcessWire

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомного модуля ProcessWire
Середня
~3-5 робочих днів
Часті питання

Наші компетенції:

Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка кастомного модуля ProcessWire

Модульна система ProcessWire — один з головних аргументів на користь цієї CMS. Будь-який модуль — це PHP-клас, що наслідує Wire або один з його потомків. Модуль може бути хуком на системні події, кастомним типом поля, процесом (сторінкою в админці) або просто набором функцій, доступних через $modules->get("MyModule").

Типи модулів

Тип Базовий клас Призначення
Звичайний WireData / Wire Хелпери, утиліти, інтеграції API
Fieldtype Fieldtype Новий тип поля
Inputfield Inputfield Віджет редагування поля
Process Process Сторінка в админці
Textformatter Textformatter Обробка тексту при виводі
Module (hookable) WireData + хуки Розширення поведінки

Мінімальна структура модуля

/site/modules/
  MyModule/
    MyModule.module.php   # основний файл (або MyModule.php)
    MyModule.info.php     # метаданні (опціонально, можна інлайн)
<?php
// MyModule.module.php

class MyModule extends WireData implements Module {

    public static function getModuleInfo(): array {
        return [
            'title'    => 'My Module',
            'version'  => '1.0.0',
            'summary'  => 'Опис модуля',
            'author'   => 'Dev Name',
            'requires' => ['ProcessWire>=3.0.0'],
            'autoload' => true,   // завантажувати при кожному запиті
            'singular' => true,   // один екземпляр на запит
        ];
    }

    public function init(): void {
        // Хуки та ініціалізація
        $this->addHookAfter('Pages::saved', $this, 'onPageSaved');
    }

    protected function onPageSaved(HookEvent $event): void {
        $page = $event->arguments(0);
        if ($page->template->name !== 'product') return;
        // логіка після збереження сторінки типу product
    }
}

Хуки: до та після

ProcessWire дозволяє перехоплювати практично будь-який метод API:

// Хук "до" — можна змінити аргументи або відмінити виконання
$this->addHookBefore('Pages::delete', function(HookEvent $e) {
    $page = $e->arguments(0);
    if ($page->template->name === 'protected') {
        $e->replace = true; // відмінити виконання оригінального методу
        throw new WireException("Видалення заборонено для шаблону protected");
    }
});

// Хук "after" — можна змінити повертане значення
$this->addHookAfter('Page::render', function(HookEvent $e) {
    $html = $e->return;
    // додати метрику в кінець сторінки
    $e->return = str_replace('</body>', '<script>analytics();</script></body>', $html);
});

Конфігурація модуля

Модулі з налаштуваннями реалізують інтерфейс ConfigurableModule:

class MyModule extends WireData implements Module, ConfigurableModule {

    protected static array $defaults = [
        'api_key'    => '',
        'cache_ttl'  => 3600,
        'debug_mode' => 0,
    ];

    public static function getDefaultConfig(): array {
        return self::$defaults;
    }

    public static function getModuleConfigInputfields(array $data): InputfieldWrapper {
        $modules = wire('modules');
        $fields  = new InputfieldWrapper();

        $data = array_merge(self::$defaults, $data);

        $f = $modules->get('InputfieldText');
        $f->attr('name', 'api_key');
        $f->label = 'API Key';
        $f->value = $data['api_key'];
        $fields->add($f);

        $f = $modules->get('InputfieldInteger');
        $f->attr('name', 'cache_ttl');
        $f->label = 'Час кешу (секунди)';
        $f->value = $data['cache_ttl'];
        $fields->add($f);

        return $fields;
    }
}

Значення читаються всередині модуля через $this->api_key, $this->cache_ttl.

Приклад: модуль інтеграції з зовнішнім API

class ExternalApiSync extends WireData implements Module {

    public static function getModuleInfo(): array {
        return [
            'title'    => 'External API Sync',
            'version'  => '1.2.0',
            'autoload' => false,
            'singular' => true,
        ];
    }

    public function syncProducts(): int {
        $apiUrl  = "https://api.supplier.com/v2/products";
        $headers = ["Authorization: Bearer {$this->api_key}"];

        $http     = $this->wire('modules')->get('WireHttp');
        $response = $http->getJSON($apiUrl, true, [], $headers);

        if (!$response) {
            $this->wire('log')->error("ExternalApiSync: не удалось получить данные");
            return 0;
        }

        $count = 0;
        foreach ($response['items'] as $item) {
            $p = $this->wire('pages')->get("template=product, external_id={$item['id']}");
            if (!$p->id) {
                $p = new Page();
                $p->template = 'product';
                $p->parent   = $this->wire('pages')->get('/catalog/');
            }
            $p->title       = $item['name'];
            $p->external_id = $item['id'];
            $p->price       = $item['price'];
            $p->save();
            $count++;
        }
        return $count;
    }
}

Вызов із шаблону або CLI:

$sync  = $modules->get('ExternalApiSync');
$count = $sync->syncProducts();
echo "Синхронізовано: $count товарів";

Process-модуль: сторінка в админці

class ProcessMyAdmin extends Process {

    public static function getModuleInfo(): array {
        return [
            'title'    => 'My Admin Page',
            'version'  => '1.0.0',
            'requires' => ['ProcessWire>=3.0.0'],
            'page'     => [
                'name'   => 'my-admin',
                'title'  => 'My Admin',
                'parent' => 'admin',
            ],
        ];
    }

    public function execute(): string {
        $out  = "<h2>Панель керування</h2>";
        $out .= "<p>Кількість товарів: " . $this->pages->count("template=product") . "</p>";
        return $out;
    }
}

При встановленні модуль автоматично створює сторінку в адміністративному дереві за вказаною шляхом.

Сроки розробки модулів

Тип модуля Складність Срок
Хук + утиліта низька 2–6 ч
Інтеграція з API середня 1–3 дні
Кастомний Fieldtype + Inputfield висока 3–7 днів
Process (повнофункціональна admin-сторінка) середня–висока 2–5 днів