Feature flags в PHP: переключаем фичи без деплоя и молитв
Представьте: вы выкатили новую фичу — и всё сломалось. Сайт лёг, клиенты в панике, девопсы чешут репу. Знакомо? А теперь представьте, что вы можете включить эту фичу только для 5% пользователей, посмотреть на метрики, а если что-то пошло не так — просто щёлкнуть тумблером и откатить. Без деплоя, без коммитов, без боли. Это не магия, это feature flags в PHP.
Feature flags (они же фича-флаги или feature toggles) — это техника, которая позволяет включать и выключать функциональность приложения без изменения кода и повторного деплоя. Звучит как суперсила? Так оно и есть. В этой статье мы разберём, как внедрить управление функционалом PHP в реальных проектах: от простого конфига до интеграции с Symfony и Laravel. Поехали!
Зачем нужны feature flags в PHP-проектах?
Допустим, вы пишете интернет-магазин на PHP. Заказчик просит добавить новый платёжный шлюз. Вы пишете код, тестируете локально, но на проде — сюрприз: шлюз работает нестабильно. Обычно это значит: срочный фикс, ночной деплой, нервный тимлид. С фича-флагами всё иначе. Вы просто выключаете флаг, и старый платёжный шлюз продолжает работать, пока вы спокойно чините баг.
Когда feature flags особенно полезны:
- Canary releases (канареечные релизы) — включаем фичу для 1% пользователей, потом для 10%, потом для всех.
- A/B тестирование — показываем разным группам разный функционал и сравниваем конверсию.
- Отключение сломанного функционала — баг на проде? Выключаем флаг, не откатывая весь релиз.
- Поэтапный rollout — выкатываем фичу постепенно, чтобы не нагрузить сервера.
И самое главное: feature flags в PHP снижают риск деплоя. Вы перестаёте бояться коммитить в пятницу вечером (ну, почти).
Простейшая реализация: конфиг-файл
Начнём с базы. Самый простой способ — хранить флаги в конфигурационном файле. Например, в формате PHP-массива или JSON.
// config/features.php
return [
'new_checkout' => false,
'dark_mode' => true,
'ai_recommendations' => false,
];
Используем в коде:
// src/CheckoutService.php
$features = require __DIR__ . '/config/features.php';
if ($features['new_checkout']) {
// Новая логика оформления заказа
$this->processWithNewGateway();
} else {
// Старая логика
$this->processWithOldGateway();
}
Минус очевиден: чтобы изменить флаг, нужно редактировать файл на сервере. Это неудобно и небезопасно. Но для маленьких проектов — сойдёт. Главное, вы поняли принцип: фича флаги PHP — это просто условные операторы, завязанные на внешнее хранилище.
Продвинутый уровень: хранение в базе данных
Когда проект растёт, конфиг-файл становится узким местом. Хочется управлять флагами через админку. Тут на помощь приходит база данных.
Создаём простую таблицу:
CREATE TABLE feature_flags (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) UNIQUE NOT NULL,
enabled TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
И пишем простой сервис для работы с флагами:
class FeatureFlagService
{
private PDO $pdo;
private array $cache = [];
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function isEnabled(string $flagName): bool
{
if (!isset($this->cache[$flagName])) {
$stmt = $this->pdo->prepare(
'SELECT enabled FROM feature_flags WHERE name = ?'
);
$stmt->execute([$flagName]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$this->cache[$flagName] = $row ? (bool)$row['enabled'] : false;
}
return $this->cache[$flagName];
}
public function setFlag(string $flagName, bool $enabled): void
{
$stmt = $this->pdo->prepare(
'INSERT INTO feature_flags (name, enabled)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE enabled = ?'
);
$stmt->execute([$flagName, $enabled, $enabled]);
$this->cache[$flagName] = $enabled;
}
}
Теперь вы можете добавить простую админ-панель, где менеджер включает или выключает фичи. Без деплоя, без кода. Управление функционалом PHP становится делом нескольких кликов.
Feature flags в Symfony: готовое решение
Symfony — это фреймворк, который любит всё из коробки. Для фича-флагов у него есть специальный компонент symfony/feature-flags (доступен с Symfony 6.4). Но если вы на более старой версии, используйте пакет qandidate/toggle или opensolid/feature-flags-bundle.
Пример интеграции с Symfony 7:
// config/packages/feature_flags.yaml
feature_flags:
flags:
new_checkout:
default: false
dark_mode:
default: true
storage: 'database' # или 'config', 'redis'
В контроллере используем сервис:
use Symfony\Component\FeatureFlags\FeatureFlags;
class CheckoutController extends AbstractController
{
public function __construct(
private FeatureFlags $featureFlags
) {}
public function checkout(): Response
{
if ($this->featureFlags->isEnabled('new_checkout')) {
// Новая логика
} else {
// Старая логика
}
}
}
В шаблонах Twig тоже можно проверять:
{% if feature_flag('dark_mode') %}
<link rel="stylesheet" href="dark.css">
{% endif %}
Красота! Feature flags Symfony — это элегантно и гибко. Единственное: не забывайте кешировать запросы к БД, иначе каждый запрос будет долбить базу.
Feature flags в Laravel: просто и мощно
Laravel тоже не отстаёт. Есть официальный пакет laravel/feature-flags (начиная с Laravel 11), а также популярный pennant — лёгкая библиотека от Laravel-команды.
Установка:
composer require laravel/pennant
php artisan vendor:publish --provider="Laravel\Pennant\PennantServiceProvider"