Розробка бекенду на PHP CodeIgniter 4 з JWT та кешуванням

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

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка бекенду на PHP CodeIgniter 4 з JWT та кешуванням
Середній
~3-5 днів
Часті запитання

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

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

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

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

Розробка бекенду на PHP CodeIgniter 4 з JWT та кешуванням

При обмежених ресурсах хостингу та необхідності швидкого запуску проєкту вибір PHP-фреймворку часто зводиться до балансу продуктивності та функціональності. Ми стикалися з ситуаціями, коли Laravel виявлявся надлишковим — 30–50 МБ на старті, довга компіляція, вимогливий до ОЗУ. Саме для таких завдань ми використовуємо CodeIgniter 4: легковажний, без магії, з простою документацією.

CodeIgniter 4 — це фреймворк, який не заважає писати швидкий код. Він дає вбудований ORM (Query Builder + Model), HTTP-шар через PSR-7, JWT-аутентифікацію з коробки і при цьому споживає мінімум ресурсів. Правильні сценарії для CI4: невеликі та середні сайти, shared-хостинг, команди з досвідом CI, проєкти з жорсткими вимогами до часу відгуку на слабкому залізі. Докладніше про можливості мови можна дізнатися в документації PHP.

Розробка бекенду на PHP (CodeIgniter): з чого почати?

Першим кроком завжди йде аудит поточної інфраструктури та вимог. Ми аналізуємо навантаження, обсяг даних та очікуване зростання. Потім проєктуємо архітектуру БД та API, обираємо оптимальні інструменти кешування. CodeIgniter 4 дозволяє швидко розгорнути каркас завдяки вбудованому генератору коду та міграціям.

Які проблеми вирішуємо в бекенді на CodeIgniter?

N+1 запити та неоптимальна робота з БД

Типова ситуація: на список товарів у циклі робиться додатковий запит для кожної категорії. У CI4 ми використовуємо репозиторій або кастомні методи моделі з JOIN. Наприклад, метод getWithCategory() заздалегідь підтягує пов'язані дані одним запитом. Замість того щоб у циклі викликати $product->category() для кожного товару, ми робимо один запит з JOIN: $this->db->join('categories', 'categories.id = products.category_id'). Це знижує кількість запитів з N+1 до 1.

Відсутність структури в API

Багато хто починає писати логіку прямо в контролері. Ми застосовуємо сервіс-шар та репозиторії. Контролер лише приймає запит і повертає відповідь, вся бізнес-логіка — в сервісах. Це спрощує тестування та підтримку.

Аутентифікація та авторизація

Реалізуємо JWT-фільтр з перевіркою ролей. Фільтр перевіряє токен у заголовку Authorization, декодує JWT та зберігає payload в $request->user. Адмінські маршрути захищені окремими фільтрами.

Чому CodeIgniter 4 швидший за альтернативи?

На shared-хостингу CodeIgniter 4 обробляє запити в 2–3 рази швидше за Laravel за інших рівних умов. Це досягається завдяки продуманій архітектурі: менше завантажуваних класів, відсутність магії з фасадами, спрощений сервіс-контейнер. Для сайтів з високою відвідуваністю це дає виграш у TTFB до 40%.

Характеристика CodeIgniter 4 Laravel 11
Споживання пам'яті на запит ~5 MB ~15 MB
Час відгуку (shared-хостинг) ~200 ms ~500 ms
Розмір фреймворку ~1.2 MB ~25 MB

Як налаштувати CodeIgniter 4: покрокова інструкція

  1. Встановіть фреймворк через Composer: composer create-project codeigniter4/appstarter project-root.
  2. Налаштуйте підключення до БД у .env: database.default.hostname = localhost тощо.
  3. Створіть міграції для таблиць через php spark make:migration.
  4. Реалізуйте моделі з валідацією та зв'язками.
  5. Напишіть контролери та роути, підключіть JWT-фільтр.

Як впровадити JWT-аутентифікацію на CI4?

Ось готовий фільтр, який ми використовуємо в кожному проєкті:

namespace App\Filters;

use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class JwtFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null)
    {
        $authHeader = $request->getHeaderLine('Authorization');
        if (!str_starts_with($authHeader, 'Bearer ')) {
            return service('response')->setStatusCode(401)->setJSON(['error' => 'Unauthorized']);
        }

        try {
            $token = substr($authHeader, 7);
            $payload = JWT::decode($token, new Key(getenv('JWT_SECRET'), 'HS256'));

            // Перевірка ролі якщо передана в arguments
            if ($arguments && !in_array($payload->role, $arguments)) {
                return service('response')->setStatusCode(403)->setJSON(['error' => 'Forbidden']);
            }

            // Зберігаємо в request для контролерів
            $request->user = $payload;
        } catch (\Exception $e) {
            return service('response')->setStatusCode(401)->setJSON(['error' => 'Invalid token']);
        }
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) {}
}

Як ми це робимо: стек та конфігурація

Використовуємо останню версію CodeIgniter на сучасному PHP, PostgreSQL або MySQL, Redis для кешу, Nginx. Фронтенд — Vue.js або React через API. Ось приклад структури роутингу та контролера.

// app/Config/Routes.php
$routes->group('api/v1', ['namespace' => 'App\Controllers\Api\V1'], function ($routes) {
    // Auth (публічні)
    $routes->post('auth/login', 'AuthController::login');
    $routes->post('auth/refresh', 'AuthController::refresh');

    // Захищені через filter
    $routes->group('', ['filter' => 'jwt'], function ($routes) {
        $routes->get('profile', 'UserController::profile');
        $routes->resource('products', ['controller' => 'ProductController']);
        // Генерує: GET /, GET /:id, POST /, PUT /:id, DELETE /:id
    });

    // Admin-only
    $routes->group('admin', ['filter' => 'jwt:admin'], function ($routes) {
        $routes->resource('users', ['controller' => 'Admin\UserController']);
    });
});
namespace App\Controllers\Api\V1;

use App\Controllers\BaseController;
use App\Models\ProductModel;
use CodeIgniter\HTTP\ResponseInterface;

class ProductController extends BaseController
{
    private ProductModel $productModel;

    public function __construct()
    {
        $this->productModel = new ProductModel();
    }

    public function index(): ResponseInterface
    {
        $page  = (int) ($this->request->getGet('page') ?? 1);
        $limit = min((int) ($this->request->getGet('limit') ?? 20), 100);

        $query = $this->productModel
            ->where('is_active', 1)
            ->orderBy('created_at', 'DESC');

        if ($categoryId = $this->request->getGet('category_id')) {
            $query->where('category_id', (int) $categoryId);
        }

        $total    = $query->countAllResults(false);
        $products = $query->paginate($limit, 'default', $page);

        return $this->response->setJSON([
            'data'       => $products,
            'pagination' => [
                'page'  => $page,
                'limit' => $limit,
                'total' => $total,
                'pages' => (int) ceil($total / $limit),
            ],
        ]);
    }

    public function create(): ResponseInterface
    {
        $data = $this->request->getJSON(true);

        if (!$this->validate($this->productModel->getValidationRules())) {
            return $this->response->setStatusCode(422)->setJSON([
                'errors' => $this->validator->getErrors(),
            ]);
        }

        $id = $this->productModel->insert($data);
        $product = $this->productModel->find($id);

        return $this->response->setStatusCode(201)->setJSON($product);
    }
}

Модель з валідацією та кастомними методами:

namespace App\Models;

use CodeIgniter\Model;

class ProductModel extends Model
{
    protected $table      = 'products';
    protected $primaryKey = 'id';
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $useTimestamps  = true;

    protected $allowedFields = ['name', 'slug', 'price', 'category_id', 'description', 'is_active', 'attributes'];

    protected $validationRules = [
        'name'        => 'required|min_length[2]|max_length[255]',
        'price'       => 'required|decimal|greater_than[0]',
        'category_id' => 'permit_empty|integer|is_not_unique[categories.id]',
    ];

    protected $validationMessages = [
        'name'  => ['required' => 'Назва обов\'язкова'],
        'price' => ['greater_than' => 'Ціна має бути більше нуля'],
    ];

    protected $beforeInsert = ['generateSlug'];
    protected $beforeUpdate = ['generateSlug'];

    protected function generateSlug(array $data): array
    {
        if (isset($data['data']['name']) && empty($data['data']['slug'])) {
            $data['data']['slug'] = url_title($data['data']['name'], '-', true);
        }
        return $data;
    }
}

Орієнтовні терміни та що входить

Компонент Терміни
Конфігурація + моделі + міграції 2–4 дні
Роути + контролери + auth 1–1,5 тижня
Бізнес-логіка 1–3 тижні
Тести (phpunit + CI Test Tools) 3–5 днів

Невеликий або середній сайт: 3–7 тижнів. Терміни залежать від складності API та інтеграцій. Оцінимо проєкт за 1 день — просто напишіть нам.

Що ми робимо:

  • Проєктуємо архітектуру бази даних і створюємо міграції
  • Реалізуємо REST API з JWT-аутентифікацією
  • Налаштовуємо кешування (Redis/File) та оптимізуємо запити
  • Пишемо unit-тести та інтеграційні тести
  • Готуємо документацію API (Swagger/Postman)
  • Розгортаємо проєкт на сервері (Docker або bare-metal)
  • Передаємо доступи та навчаємо вашу команду
  • Забезпечуємо гарантійну підтримку 30 днів

Більше 8 років ми розробляємо на PHP. Портфоліо включає 20+ проєктів на CodeIgniter 4 — від простих лендінгів до маркетплейсів. 98% проєктів здаємо вчасно. Хочете швидкий і надійний бекенд без переплати? Зв'яжіться з нами — обговоримо ваш проєкт і запропонуємо оптимальне рішення. Отримайте консультацію по вашому проєкту вже сьогодні.

Послуги бекенд-розробки: production-grade надійність

На production-сервері о 3:14 ночі черга Laravel Jobs перестала оброблятися — 40 000 необроблених завдань у Redis. Причина: worker упав через memory leak у статичній змінній Eloquent observer, supervisor не перезапустив через misconfigured stopwaitsecs. Ми розбирали такий інцидент на проекті з 500 RPS: діагностика 4 години, фікс — 20 хвилин. Щоб ви не втрачали гроші, пропонуємо послуги бекенд-розробки з акцентом на production-grade надійність — 10+ років досвіду, 50+ проектів, 5 років на ринку. Оцінимо ваш проект за 2 дні.

Які проблеми вирішуємо

N+1 запити: головний вбивця швидкості

N+1 — найпоширеніша причина повільних сторінок у Laravel-додатках. Стандартна історія: сторінка працювала нормально на dev з 10 записами, на production з 10 000 — 8-секундне завантаження.

Laravel Debugbar у dev-оточенні показує кількість запитів. Більше 20 — сигнал для audit.

Model::preventLazyLoading(! app()->isProduction());

Telescope для профілювання: логує всі запити, jobs, mail, notifications з деталізацією. Після впровадження eager loading час завантаження сторінки падає з 8 с до 0.3 с — у 27 разів.

Memory leak у статичних змінних

У Laravel Octane або Swoole додаток тримається в пам’яті між запитами. Статичні змінні не скидаються — призводять до неконтрольованого росту пам’яті. Використовуємо defer-функції та контейнерні біндинги для коректного скидання стану.

Неправильний connection pool

Rails, Laravel, Django відкривають нове з'єднання PostgreSQL на кожен PHP/Python процес. 100 воркерів — 100 з'єднань. PostgreSQL деградує від 200+ активних з'єднань через overhead на управління.

PgBouncer у transaction pooling: 1000 воркерів → 20–50 реальних з'єднань. Це знижує latency на 40% та зменшує витрати на хостинг на 30% — при середній вартості хостингу $2,000/міс економить $600/міс. GIN-індекс для JSONB до 100 разів швидший за B-tree при пошуку.

Як Octane справляється з високим навантаженням?

Laravel Octane (RoadRunner або Swoole) прибирає overhead bootstrap на кожен HTTP-запит. Приріст: 3–8x на синтетичних бенчмарках, 2–4x на реальних додатках. Важливо: не зберігати стан у статичних змінних — застосовуємо це на проектах >1000 RPS.

Як PostgreSQL допомагає уникнути повільних запитів?

Використовуємо composite indexes для WHERE + ORDER BY, partial indexes для фільтрів з високою селективністю, GIN-індекси для JSONB та full-text search. to_tsvector + GIN замість LIKE '%query%' — запобігає seq scan навіть на мільйонах записів. Аналізуємо плани через EXPLAIN ANALYZE та pg_stat_statements.

Як обрати стек для вашого проекту?

Стек Коли використовувати
Laravel + Octane CRUD, бізнес-логіка, REST/GraphQL API, адмінки
Node.js (Fastify) Realtime WebSocket, streaming, serverless, висока I/O concurrency
Go Високонавантажені мікросервіси (>10k RPS), gRPC, DevOps-інструменти
Django + DRF ML-пайплайни, інтеграція з AI, складна обробка даних
Ruby on Rails Швидкий MVP з багатим екосистемою гемів

Node.js виправданий для realtime: Laravel публікує події в Redis Pub/Sub, Node.js підписується та транслює клієнтам. Go — для goroutines (10k з'єднань на сервер — норма), але розробка повільніша, ніж Laravel.

Чому Redis критичний для продуктивності?

Redis виконує кілька ролей:

Роль Деталі
Кеш Кешування результатів важких запитів, фрагментів HTML
Черги Backend для Laravel Queue / Celery
Session store Distributed sessions в multi-instance оточенні
Pub/Sub Realtime події між сервісами
Rate limiting Sliding window counters для API throttling
Leaderboards Sorted Sets для рейтингів

Redis Cluster для горизонтального масштабування, Sentinel для автоматичного failover. Замовте консультацію щодо оптимізації Redis для вашого проекту.

Що входить в роботу під ключ

  • Архітектурне проектування (документація API, схема БД, діаграма сервісів)
  • Реалізація за узгодженим ТЗ з code review
  • Налаштування CI/CD (GitHub Actions, Docker), моніторингу (Sentry, Grafana), алертингу
  • Навантажувальне тестування (k6, wrk) зі звітом
  • Передача вихідних кодів, доступів, інструкція з деплою
  • Навчання команди замовника (2–3 сесії)
  • Гарантійна підтримка 1 місяць після здачі

Орієнтири по термінах

Задача Термін
REST API для мобільного/SPA (середня складність) 6–12 тижнів
Backend зі складною бізнес-логікою + інтеграції 12–20 тижнів
Високонавантажений сервіс на Go 8–16 тижнів
Міграція legacy PHP на Laravel 16–32 тижні

Вартість розраховується індивідуально після аналізу вимог до навантаження, інтеграцій та бізнес-логіки. Зв'яжіться з нами для безкоштовного аудиту вашого поточного backend — отримайте план оптимізації за 2 дні. Замовте консультацію та дізнайтеся, як знизити витрати на інфраструктуру на 30% без втрати продуктивності.