При ограниченных ресурсах хостинга и необходимости быстрого запуска проекта выбор 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: пошаговая инструкция
- Установите фреймворк через Composer:
composer create-project codeigniter4/appstarter project-root. - Настройте подключение к БД в
.env:database.default.hostname = localhostи т.д. - Создайте миграции для таблиц через
php spark make:migration. - Реализуйте модели с валидацией и связями.
- Напишите контроллеры и роуты, подключите 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% проектов сдаём в срок. Хотите быстрый и надёжный бэкенд без переплаты? Свяжитесь с нами — обсудим ваш проект и предложим оптимальное решение. Получите консультацию по вашему проекту уже сегодня.







