Ви запускаєте інтернет-магазин з каталогом у 10 000 товарів. Стандартний LAMP-стек справляється, але через місяць сторінки завантажуються по 3 секунди, а додавання нового розділу вимагає переписування чотирьох контролерів. Кожен запит до бази тягне десятки пов'язаних таблиць — N+1 проблема сповільнює роботу. Yii2 вирішує це за допомогою жадібного завантаження та кешування схеми. Ми пропонуємо розробку бекенду на Yii2 під ключ — рішення, яке прискорює розробку вдвічі та дозволяє легко масштабувати функціонал. Наші інженери мають 10+ років досвіду з Yii2 і гарантують стабільну роботу. Нижче — реальна історія переходу з моноліту на модульний REST API.
Які проблеми вирішує бекенд на Yii2?
Перша — N+1 запити. При вибірці списку товарів стандартний підхід робить запит для кожного пов'язаного елемента. Yii2 вирішує це через жадібне завантаження: Product::find()->with('category')->all(). Друга — відсутність прав доступу. Вбудований RBAC з ієрархією ролей та кастомними правилами позбавляє від саморобної реалізації. Третя — повільна робота без кешу. Yii2 підтримує кеш схеми БД, фрагментний кеш та HTTP-кеш, знижуючи навантаження на базу.
Нещодавно ми переносили монолітний додаток на Yii2 REST API. Клієнт мав 50+ таблиць, потрібно було створити модульну архітектуру. Ми використали Gii для генерації моделей та CRUD-контролерів, налаштували кеш схеми БД через Redis, RBAC з кастомними правилами та JWT. Строк розробки скоротився на 30%. Код вийшов одноманітним, що спростило підтримку. За словами клієнта: Перехід на Yii2 скоротив час виведення нових функцій на 40%.
Чому Yii2 швидший за Laravel?
Yii2 використовує кешування схеми БД, зменшуючи кількість запитів до бази. За нашими тестами, стандартний CRUD на Yii2 виконується на 40% швидше, ніж на Laravel. Gii генерує код без зайвих залежностей, знижуючи час виконання. У таблиці — наочне порівняння.
| Критерій | Yii2 | Laravel |
|---|---|---|
| Швидкість роботи | Висока (кеш схеми) | Середня |
| Генерація коду | Gii (вбудований) | Artisan + пакети |
| RBAC | З коробки | Через пакети |
| Крива навчання | Середня | Низька |
Як Yii2 допомагає уникнути N+1 запитів?
Yii2 надає жадібне завантаження через with() і зв'язки. Наприклад, Product::find()->with('category')->all() виконує 2 запити замість N+1. Ми завжди використовуємо це в проектах, що критично для швидкодії каталогів. Для складних сценаріїв застосовуємо joinWith().
Що таке Gii і як він прискорює розробку?
Gii — це генератор коду, вбудований у Yii2. Він створює моделі, CRUD-контролери та REST-ендпоінти за кілька команд. Для каталогу з 20 сутностями вся базова структура генерується за один день, економлячи 30–40% часу на рутинних операціях.
Як налаштувати кешування в Yii2?
Yii2 підтримує кілька типів кешу: кеш схеми БД, фрагментний кеш та HTTP-кеш. Для зберігання використовується Redis або Memcached. Налаштування компонента cache в конфігурації включає кеш схеми та фрагментів. Це знижує навантаження на базу і прискорює відповіді до 50%.
Ключові компоненти архітектури
Конфігурація додатку
// config/web.php return [ 'id' => 'my-app', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log', 'queue'], 'components' => [ 'db' => [ 'class' => yii\db\Connection::class, 'dsn' => 'pgsql:host=localhost;dbname=myapp', 'username' => getenv('DB_USER'), 'password' => getenv('DB_PASS'), 'charset' => 'utf8', 'enableSchemaCache' => true, 'schemaCacheDuration' => 3600, ], 'cache' => [ 'class' => yii\redis\Cache::class, 'redis' => ['hostname' => 'localhost', 'port' => 6379], ], 'user' => [ 'identityClass' => app\models\User::class, 'enableAutoLogin' => false, 'enableSession' => false, ], 'queue' => [ 'class' => yii\queue\redis\Queue::class, 'redis' => 'redis', 'channel' => 'queue', ], ], 'modules' => [ 'api' => [ 'class' => app\modules\api\Module::class, 'version' => 'v1', ], ], ]; ActiveRecord
namespace app\models; use yii\db\ActiveRecord; use yii\behaviors\TimestampBehavior; use yii\behaviors\SluggableBehavior; class Product extends ActiveRecord { public static function tableName(): string { return 'products'; } public function behaviors(): array { return [ TimestampBehavior::class, ['class' => SluggableBehavior::class, 'attribute' => 'name', 'slugAttribute' => 'slug', 'ensureUnique' => true], ]; } public function rules(): array { return [ [['name', 'price'], 'required'], ['name', 'string', 'min' => 2, 'max' => 255], ['price', 'number', 'min' => 0.01], ['category_id', 'exist', 'targetClass' => Category::class, 'targetAttribute' => 'id'], ['attributes', 'safe'], ['is_active', 'boolean'], ['is_active', 'default', 'value' => true], ]; } public function getCategory(): ActiveQuery { return $this->hasOne(Category::class, ['id' => 'category_id']); } public function getVariants(): ActiveQuery { return $this->hasMany(ProductVariant::class, ['product_id' => 'id']); } public static function find(): ProductQuery { return new ProductQuery(static::class); } } class ProductQuery extends ActiveQuery { public function active(): static { return $this->andWhere(['is_active' => true]); } public function byCategory(int $categoryId): static { return $this->andWhere(['category_id' => $categoryId]); } } REST API через yii\rest
Yii2 має вбудовану підтримку REST API:
namespace app\modules\api\controllers; use yii\rest\ActiveController; use yii\filters\auth\HttpBearerAuth; use yii\filters\Cors; class ProductController extends ActiveController { public string $modelClass = Product::class; public function behaviors(): array { $behaviors = parent::behaviors(); $behaviors['corsFilter'] = ['class' => Cors::class, 'cors' => ['Origin' => explode(',', getenv('ALLOWED_ORIGINS') ?: '*'), 'Access-Control-Allow-Credentials' => true]]; $behaviors['authenticator'] = ['class' => HttpBearerAuth::class, 'except' => ['index', 'view']]; return $behaviors; } public function actions(): array { $actions = parent::actions(); $actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider']; return $actions; } public function prepareDataProvider(): ActiveDataProvider { $params = Yii::$app->request->queryParams; return (new ProductSearch())->search($params); } public function actionFeatured(): array { return Product::find()->active()->orderBy(['views' => SORT_DESC])->limit(10)->all(); } } JWT аутентифікація
use Firebase\JWT\JWT; use Firebase\JWT\Key; use yii\filters\auth\AuthMethod; class JwtAuth extends AuthMethod { public function authenticate($user, $request, $response) { $authHeader = $request->getHeaders()->get('Authorization'); if (!$authHeader || !str_starts_with($authHeader, 'Bearer ')) return null; try { $token = substr($authHeader, 7); $decoded = JWT::decode($token, new Key(getenv('JWT_SECRET'), 'HS256')); return User::findOne($decoded->sub); } catch (\Exception $e) { throw new UnauthorizedHttpException('Invalid token'); } } } Gii — генератор коду
Gii автоматично створює моделі, CRUD та REST-контролери:
php yii gii/model --tableName=products --modelClass=Product php yii gii/crud --modelClass=Product --controllerClass=ProductController php yii gii/rest-controller --modelClass=Product Gii економить 30–40% часу на стандартних операціях. Наприклад, для каталогу з 20 сутностями вся базова структура генерується за один день.
Процес і терміни розробки
| Етап | Термін |
|---|---|
| Аналітика та архітектура | 2–5 днів |
| Проектування схеми БД та моделей | 3–7 днів |
| Реалізація REST API та бізнес-логіки | 1–3 тижні |
| Налаштування аутентифікації та RBAC | 3–5 днів |
| Кешування та черги | 2–4 дні |
| Тестування та налагодження | 5–10 днів |
| Деплой та документація | 3–5 днів |
Типовий проект займає 4–8 тижнів. Для прискорення використовуємо Gii та готові шаблони. Зв'яжіться з нами для точної оцінки вашого проекту.
Що входить у розробку?
- Аналіз вимог та архітектура
- Моделі та міграції
- REST API з документацією (OpenAPI/Swagger)
- RBAC та аутентифікація (JWT, OAuth)
- Кешування (Redis, Memcached) та черги (RabbitMQ, Redis)
- Деплой на staging та production
- Інструкція з експлуатації
- Навчання команди (2–5 годин)
- Пост-релізна підтримка 1 місяць
Готові почати? Замовте безкоштовну консультацію, і ми підготуємо детальну пропозицію для вашого проекту. Зв'яжіться з нашими інженерами через форму зворотного зв'язку для оперативної відповіді.







