Розробка кастомного пакету (Extra) MODX

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомного пакету (Extra) MODX
Складна
~1-2 тижні
Часті питання

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

Етапи розробки

Останні роботи

  • 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

Розробка кастомного пакета (Extra) MODX

Extra MODX — повнофункціональне розширення: компонент (інтерфейс у менеджері), набір сніпетів, плагінів, чанків, системних налаштувань. Упакований як .transport.zip для встановлення через Package Manager. Це правильний спосіб розповсюджувати та підтримувати складну функціональність.

Структура Extra

core/components/myextra/
├── controllers/
│   └── home.class.php          # Контролер MODX
├── docs/
│   └── changelog.txt
├── elements/
│   ├── chunks/
│   ├── plugins/
│   ├── snippets/
│   └── templates/
├── lexicon/
│   └── ru/
│       └── default.inc.php     # Переклади
├── model/
│   └── myextra/                # моделі xPDO
│       ├── myitem.class.php
│       ├── mysql/
│       │   ├── myitem.class.php
│       │   └── myitem.map.inc.php
│       └── myextra.mysql.schema.xml
└── processors/
    └── mgr/
        └── items/
            ├── getlist.class.php
            ├── get.class.php
            ├── create.class.php
            ├── update.class.php
            └── remove.class.php

assets/components/myextra/
├── js/
│   ├── mgr/
│   │   └── myextra.js          # Інтерфейс ExtJS
│   └── widgets/
│       └── items.grid.js
└── css/
    └── mgr.css

Схема БД xPDO

<!-- core/components/myextra/model/myextra/mysql/myextra.mysql.schema.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<model package="myextra" baseClass="xPDOObject" platform="mysql" version="1.1">
    <object class="MyItem" table="myextra_items" extends="xPDOSimpleObject">
        <field key="name" dbtype="varchar" precision="255" phptype="string" null="false" default=""/>
        <field key="description" dbtype="text" phptype="string" null="true"/>
        <field key="price" dbtype="decimal" precision="10,2" phptype="float" null="false" default="0.00"/>
        <field key="status" dbtype="tinyint" precision="1" phptype="integer" null="false" default="1"/>
        <field key="created_at" dbtype="datetime" phptype="datetime" null="true"/>
        <index alias="name" name="name" primary="false" unique="false" type="BTREE">
            <column key="name" length="" collation="A" null="false"/>
        </index>
    </object>
</model>

Модель xPDO

// core/components/myextra/model/myextra/myitem.class.php
class MyItem extends xPDOSimpleObject {
    public function getLink(): string {
        return $this->xpdo->makeUrl(
            $this->xpdo->getOption('myextra.item_page', null, 1),
            '',
            ['id' => $this->get('id')],
            'full'
        );
    }
}

Процесор (операції CRUD)

// core/components/myextra/processors/mgr/items/getlist.class.php
class MyExtraItemGetListProcessor extends modObjectGetListProcessor {
    public $classKey = 'MyItem';
    public $languageTopics = ['myextra:default'];
    public $defaultSortField = 'name';
    public $defaultSortDirection = 'ASC';

    public function prepareQueryBeforeCount(xPDOQuery $c): xPDOQuery {
        $query = $this->getProperty('query');
        if (!empty($query)) {
            $c->where(['name:LIKE' => "%{$query}%"]);
        }

        $status = $this->getProperty('status', null);
        if ($status !== null && $status !== '') {
            $c->where(['status' => (int)$status]);
        }

        return $c;
    }

    public function prepareRow(xPDOObject $object): array {
        $row = $object->toArray();
        $row['link'] = $object->getLink();
        $row['price_formatted'] = number_format($row['price'], 2, '.', ' ') . ' ₽';
        return $row;
    }
}

Сніпет Extra

<?php
// core/components/myextra/elements/snippets/myextra.snippet.php
$basePath = $modx->getOption('myextra.core_path', null,
    $modx->getOption('core_path') . 'components/myextra/');

$modx->addPackage('myextra', $basePath . 'model/');
$modx->lexicon->load('myextra:default');

$limit  = (int)($scriptProperties['limit'] ?? 10);
$offset = (int)($scriptProperties['offset'] ?? 0);
$tpl    = $scriptProperties['tpl'] ?? 'myextra.item';

$c = $modx->newQuery('MyItem');
$c->where(['status' => 1]);
$c->limit($limit, $offset);
$c->sortby('name', 'ASC');

$items = $modx->getCollection('MyItem', $c);
$output = '';

foreach ($items as $item) {
    $output .= $modx->getChunk($tpl, $item->toArray());
}

return $output;

Збірка Transport Package

// _build/build.transport.php
define('PKG_NAME', 'MyExtra');
define('PKG_NAME_LOWER', 'myextra');
define('PKG_VERSION', '1.0.0');
define('PKG_RELEASE', 'pl');

// Створення пакета
$builder = new modPackageBuilder($modx);
$builder->createPackage(PKG_NAME_LOWER, PKG_VERSION, PKG_RELEASE);
$builder->registerNamespace(PKG_NAME_LOWER, false, true, '{core_path}components/' . PKG_NAME_LOWER . '/');

// Добавити категорію з елементами
$category = $modx->newObject('modCategory');
$category->set('id', 1);
$category->set('category', PKG_NAME);

// Добавити сніпети, чанки, плагіни...
$snippets = includeSnippets($builder, $modx);
$category->addMany($snippets);

// Створити vehicle
$attr = [
    xPDOTransport::PRESERVE_KEYS => false,
    xPDOTransport::UPDATE_OBJECT => true,
    xPDOTransport::UNIQUE_KEY => 'category',
    xPDOTransport::RELATED_OBJECTS => true,
    xPDOTransport::RELATED_OBJECT_ATTRIBUTES => ['Snippets' => [...], 'Chunks' => [...]],
];

$vehicle = $builder->createVehicle($category, $attr);
$builder->putVehicle($vehicle);

// Остаточна упаковка
$builder->pack();

Терміни

Розробка Extra з інтерфейсом CRUD у менеджері, 2–3 сніпетами та базовою схемою БД — 2–3 тижні.