Разработка кастомного плагина Joomla

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

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

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка кастомного плагина Joomla
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы

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

Этапы разработки

Последние работы

  • 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

Разработка кастомного плагина Joomla

Плагины Joomla реагируют на системные события. Перехватывают моменты жизненного цикла: до/после сохранения статьи, при аутентификации, при поиске, при отправке формы. Это самый правильный способ расширить поведение системы без модификации ядра.

Группы плагинов

Группа Событие Применение
content onContentBeforeSave, onContentAfterSave Обработка контента
user onUserLogin, onUserAfterSave Аутентификация, синхронизация
system onAfterRoute, onBeforeRender Глобальные перехваты
authentication onUserAuthenticate Внешние провайдеры входа
finder onFinderIndexItem Поисковый индекс Smart Search
task onExecuteTask Планировщик задач (Joomla 4+)

Структура плагина

plg_content_synccrm/
├── plg_content_synccrm.php    # Точка входа (для legacy)
├── plg_content_synccrm.xml    # Манифест
├── services/
│   └── provider.php           # DI Provider
└── src/
    └── Extension/
        └── SyncCrmPlugin.php  # Основной класс

Манифест

<?xml version="1.0" encoding="utf-8"?>
<extension version="4.0" type="plugin" group="content">
    <name>plg_content_synccrm</name>
    <author>Your Company</author>
    <version>1.0.0</version>
    <description>Синхронизация контента с CRM при публикации</description>
    <namespace path="src">MyCompany\Plugin\Content\SyncCrm</namespace>

    <files>
        <filename plugin="plg_content_synccrm">plg_content_synccrm.php</filename>
        <folder>services</folder>
        <folder>src</folder>
    </files>

    <config>
        <fields name="params">
            <fieldset name="basic">
                <field name="crm_api_url" type="text" label="URL CRM API" />
                <field name="crm_api_key" type="password" label="API Key CRM" />
                <field name="sync_types" type="checkboxes" label="Синхронизировать типы">
                    <option value="article">Статьи</option>
                    <option value="product">Товары</option>
                </field>
            </fieldset>
        </fields>
    </config>
</extension>

DI Provider

// services/provider.php
use Joomla\CMS\Extension\PluginInterface;
use Joomla\DI\Container;
use MyCompany\Plugin\Content\SyncCrm\Extension\SyncCrmPlugin;

return new class implements \Joomla\DI\ServiceProviderInterface {
    public function register(Container $container): void {
        $container->set(PluginInterface::class, function (Container $container) {
            $dispatcher = $container->get(\Joomla\Event\DispatcherInterface::class);
            $plugin = new SyncCrmPlugin($dispatcher, []);
            $plugin->setApplication($container->get(\Joomla\CMS\Application\CMSApplicationInterface::class));
            return $plugin;
        });
    }
};

Основной класс плагина

// src/Extension/SyncCrmPlugin.php
namespace MyCompany\Plugin\Content\SyncCrm\Extension;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\Event;
use Joomla\Event\SubscriberInterface;

class SyncCrmPlugin extends CMSPlugin implements SubscriberInterface {
    public static function getSubscribedEvents(): array {
        return [
            'onContentAfterSave' => 'syncToCrm',
        ];
    }

    public function syncToCrm(Event $event): void {
        [$context, $article, $isNew] = array_values($event->getArguments());

        // Синхронизировать только статьи
        if ($context !== 'com_content.article') return;

        // Только опубликованные
        if ((int) $article->state !== 1) return;

        $syncTypes = $this->params->get('sync_types', []);
        if (!in_array('article', (array) $syncTypes)) return;

        try {
            $this->sendToCrm([
                'type'       => 'article',
                'external_id'=> $article->id,
                'title'      => $article->title,
                'url'        => \Joomla\CMS\Router\Route::link('site', 'index.php?option=com_content&view=article&id=' . $article->id),
                'published'  => (bool) $article->state,
                'updated_at' => $article->modified,
            ]);
        } catch (\Exception $e) {
            $this->getApplication()->getLogger()->error('CRM sync failed: ' . $e->getMessage());
        }
    }

    private function sendToCrm(array $data): void {
        $apiUrl = rtrim($this->params->get('crm_api_url'), '/') . '/articles';
        $apiKey = $this->params->get('crm_api_key');

        $http = \Joomla\CMS\Factory::getContainer()
            ->get(\Joomla\Http\HttpFactory::class)
            ->getHttp();

        $response = $http->post($apiUrl, json_encode($data), [
            'Content-Type'  => 'application/json',
            'Authorization' => 'Bearer ' . $apiKey,
        ]);

        if ($response->code >= 400) {
            throw new \RuntimeException('CRM API error: ' . $response->code);
        }
    }
}

Плагин аутентификации (внешний SSO)

public static function getSubscribedEvents(): array {
    return ['onUserAuthenticate' => 'authenticate'];
}

public function authenticate(Event $event): void {
    $credentials = $event->getArgument('credentials');
    $options     = $event->getArgument('options');
    $response    = $event->getArgument('response');

    // Проверяем через внешний OAuth-сервер
    $token = $this->verifyWithOAuthServer($credentials['username'], $credentials['password']);

    if ($token) {
        $response->status = \Joomla\CMS\Authentication\Authentication::STATUS_SUCCESS;
        $response->email  = $token['email'];
        $response->fullname = $token['name'];
        $response->type   = 'OAuth';
    } else {
        $response->status  = \Joomla\CMS\Authentication\Authentication::STATUS_FAILURE;
        $response->error_message = 'Неверные учётные данные';
    }
}

Сроки

Разработка плагина для одной группы событий (content, user или system) с конфигурируемыми параметрами — 1–3 дня.