Розробка кастомного плагіна Kirby

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомного плагіна Kirby
Середня
~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

Розробка користувацького плагіна Kirby

Плагін в Kirby — це PHP-пакет, який реєструє розширення через Kirby::plugin(). Одним викликом можна додати нові типи полів, блоки, маршрути, хуки, методи сторінок та багато іншого. Плагіни розповсюджуються через Composer або як папки в site/plugins/.

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

site/plugins/my-plugin/
├── composer.json
├── index.php          # точка входу
├── lib/               # PHP-класи
├── templates/         # шаблони блоків
└── assets/
    ├── css/
    └── js/
<?php
// site/plugins/my-plugin/index.php

use Kirby\Cms\App;
use Kirby\Cms\Page;

App::plugin('vendor/my-plugin', [
    'options' => [
        'cache' => true,
        'apiKey' => null,
    ],
    'fields'    => require __DIR__ . '/lib/fields.php',
    'methods'   => require __DIR__ . '/lib/methods.php',
    'routes'    => require __DIR__ . '/lib/routes.php',
    'hooks'     => require __DIR__ . '/lib/hooks.php',
    'blueprints' => require __DIR__ . '/lib/blueprints.php',
    'translations' => [
        'ru' => require __DIR__ . '/lib/translations/ru.php',
        'en' => require __DIR__ . '/lib/translations/en.php',
    ],
]);

Користувацькі методи сторінок

<?php
// lib/methods.php
return [
    'pages' => [
        'publishedAndFeatured' => function (): Pages {
            return $this->listed()->filter(
                fn($p) => $p->featured()->isTrue()
            );
        },
    ],
    'page' => [
        'readingTime' => function (): int {
            $words = str_word_count(
                strip_tags($this->text()->kirbytext())
            );
            return max(1, (int) ceil($words / 200));
        },

        'schemaOrg' => function (): string {
            $schema = [
                '@context' => 'https://schema.org',
                '@type'    => 'Article',
                'headline' => $this->title()->value(),
                'datePublished' => $this->date()->toDate('c'),
                'url'      => $this->url(),
            ];
            return '<script type="application/ld+json">'
                . json_encode($schema, JSON_UNESCAPED_UNICODE)
                . '</script>';
        },
    ],
    'file' => [
        'isWebOptimized' => function (): bool {
            return in_array($this->extension(), ['webp', 'avif', 'svg']);
        },
    ],
];

У шаблонах:

echo $page->readingTime(); // 5
echo $page->schemaOrg();   // <script type="application/ld+json">...</script>
$page->siblings()->publishedAndFeatured();

Користувацькі маршрути

<?php
// lib/routes.php
return [
    [
        'pattern' => 'api/v1/sitemap',
        'method'  => 'GET',
        'action'  => function () {
            $pages = kirby()->site()->index()->listed()->filter(
                fn($p) => $p->intendedTemplate()->name() !== 'error'
            );

            $urls = $pages->map(fn($p) => [
                'url'      => $p->url(),
                'modified' => $p->modified('Y-m-d'),
                'priority' => $p->isHomePage() ? '1.0' : '0.8',
            ])->values();

            return \Kirby\Http\Response::json(['urls' => $urls]);
        },
    ],
    [
        'pattern' => 'api/v1/search',
        'method'  => 'GET',
        'action'  => function () {
            $query = get('q', '');
            if (strlen($query) < 2) {
                return \Kirby\Http\Response::json(['results' => []]);
            }

            $results = kirby()->site()->search($query, 'title|text')
                ->listed()
                ->limit(10)
                ->map(fn($p) => [
                    'title'   => $p->title()->value(),
                    'url'     => $p->url(),
                    'excerpt' => $p->text()->excerpt(120),
                ]);

            return \Kirby\Http\Response::json(['results' => $results->values()]);
        },
    ],
];

Хуки

<?php
// lib/hooks.php
return [
    'page.create:after' => function (Page $page) {
        if ($page->intendedTemplate()->name() !== 'article') {
            return;
        }

        // ping пошукові системи
        $url = urlencode(kirby()->site()->url() . '/sitemap.xml');
        @file_get_contents("https://www.google.com/ping?sitemap={$url}");
    },

    'page.update:after' => function (Page $newPage, Page $oldPage) {
        // сбросить кеш конкретної сторінки
        if (kirby()->cache('pages')->exists($newPage->id())) {
            kirby()->cache('pages')->remove($newPage->id());
        }
    },

    'file.create:after' => function (\Kirby\Cms\File $file) {
        if (!$file->isImage()) {
            return;
        }

        // генерювати WebP-версії превентивно
        $file->thumb(['width' => 800, 'format' => 'webp']);
        $file->thumb(['width' => 400, 'format' => 'webp']);
    },

    'kirby.render:before' => function (string $template, array $data) {
        // можна додати глобальні дані
    },
];

Користувацький тип поля для панелі

Поля панелі пишуться на Vue.js і реєструються з PHP-серверною частиною:

<?php
// lib/fields.php
return [
    'colorpicker' => [
        'props' => [
            'value' => function ($value = '#000000') {
                return $value;
            },
            'presets' => function (array $presets = []) {
                return $presets;
            },
        ],
        'save' => function ($value): string {
            // валідація перед збереженням
            if (!preg_match('/^#[0-9A-Fa-f]{6}$/', $value)) {
                throw new \Exception('Invalid color format');
            }
            return $value;
        },
    ],
];
// assets/js/fields.js
panel.plugin('vendor/my-plugin', {
  fields: {
    colorpicker: {
      template: `
        <k-field v-bind="$props">
          <input type="color" :value="value" @input="$emit('input', $event.target.value)">
          <div class="presets">
            <button
              v-for="color in presets"
              :key="color"
              :style="{ background: color }"
              @click="$emit('input', color)"
            />
          </div>
        </k-field>
      `,
      props: {
        value:   String,
        presets: Array,
      },
    },
  },
});

Реєстрація ассета:

App::plugin('vendor/my-plugin', [
    'fields' => require __DIR__ . '/lib/fields.php',
    'assets' => [
        'js/fields.js' => __DIR__ . '/assets/js/fields.js',
    ],
]);

Опції плагіна

// отримання опції в коді плагіна
$apiKey = option('vendor/my-plugin.apiKey');
$useCache = option('vendor/my-plugin.cache', true);

Користувач перевизначає в site/config/config.php:

return [
    'vendor/my-plugin' => [
        'apiKey' => 'sk-...',
        'cache'  => false,
    ],
];

Терміни розробки

Плагін з методами та хуками без UI-частини: 1–3 дні. Плагін з користувацьким полем панелі (Vue + PHP): 3–6 днів. Складний плагін з користувацьким розділом панелі, зовнішнім API та кешуванням: 1–2 тижні.