Разработка бэкенда сайта на PHP (Yii2)
Yii2 — PHP-фреймворк с отличным соотношением возможностей к сложности освоения. Полный стек: ActiveRecord ORM, Gii (кодогенератор CRUD), RBAC из коробки, кеш, очереди через yii2-queue, REST-поддержка. При этом конфигурация через массивы PHP остаётся прозрачной и предсказуемой без магии аннотаций.
Актуален для проектов, где важна скорость разработки с российским/постсоветским стеком разработчиков — Yii2 исторически популярен в этом регионе, специалистов найти проще.
Конфигурация приложения
// 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, // для API — stateless
],
'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();
// CORS
$behaviors['corsFilter'] = [
'class' => Cors::class,
'cors' => [
'Origin' => explode(',', getenv('ALLOWED_ORIGINS') ?: '*'),
'Access-Control-Allow-Credentials' => true,
],
];
// Auth
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::class,
'except' => ['index', 'view'],
];
return $behaviors;
}
public function actions(): array
{
$actions = parent::actions();
// Кастомизируем index — добавляем фильтры
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider(): ActiveDataProvider
{
$params = Yii::$app->request->queryParams;
$search = new ProductSearch();
return $search->search($params);
}
// Дополнительные actions
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 — генератор кода
Одна из ключевых особенностей Yii2 — генератор CRUD:
# Генерация модели из таблицы БД
php yii gii/model --tableName=products --modelClass=Product
# Генерация CRUD-контроллера
php yii gii/crud --modelClass=Product --controllerClass=ProductController
# REST-контроллер
php yii gii/rest-controller --modelClass=Product
Gii существенно ускоряет создание шаблонного кода при большом числе сущностей.
Очереди через yii2-queue
namespace app\jobs;
use yii\base\BaseObject;
use yii\queue\JobInterface;
class SendEmailJob extends BaseObject implements JobInterface
{
public int $userId;
public string $template;
public array $params = [];
public function execute($queue): void
{
$user = User::findOne($this->userId);
if (!$user) return;
Yii::$app->mailer->compose($this->template, $this->params)
->setTo($user->email)
->send();
}
}
// Постановка в очередь
Yii::$app->queue->push(new SendEmailJob([
'userId' => $user->id,
'template' => 'welcome',
'params' => ['name' => $user->name],
]));
// С задержкой
Yii::$app->queue->delay(300)->push(new SendEmailJob([...]));
RBAC
// Назначение роли
$auth = Yii::$app->authManager;
$adminRole = $auth->getRole('admin');
$auth->assign($adminRole, $user->id);
// Проверка в контроллере
if (!Yii::$app->user->can('updateProduct', ['product' => $product])) {
throw new ForbiddenHttpException();
}
// Кастомное правило
class ProductOwnerRule extends Rule
{
public string $name = 'isProductOwner';
public function execute($user, $item, $params): bool
{
return isset($params['product']) && $params['product']->user_id === $user;
}
}
Сроки разработки
- Конфигурация + модели + миграции — 3–5 дней
- REST API модулей — 1–2 недели
- Auth + RBAC — 3–5 дней
- Gii-генерация шаблонного кода экономит 30–40% времени на стандартных CRUD
- Тесты — 3–7 дней
- Интеграции — по задаче
Корпоративный сайт или портал: 4–8 недель. Yii2 выигрывает на проектах с большим числом сущностей, где Gii даёт ощутимое ускорение.







