В 16-ом уроке мы разберем одну из тем в разработке, это оптимизацию приложений. Даже если ваш код работает корректно, медленная скорость загрузки страниц или высокие нагрузки на сервер могут испортить впечатление пользователей. В этом уроке я расскажу, как улучшить производительность Yii 2-приложений, используя проверенные методы.
Оптимизация запросов к базе данных
Первое, на что стоит обратить внимание при оптимизации, это работа с базой данных.
Некорректно написанные запросы или избыточное обращение к БД могут замедлить приложение в разы.
Проблема N+1
Частая ошибка новичков, это проблема N+1. Представьте, что вы получаете список статей (SELECT * FROM articles), а затем для каждой статьи отдельно запрашиваете автора:
$articles = Article::find()->all(); foreach ($articles as $article) { $author = $article->author; // Отдельный запрос для каждой статьи! }
Если статей 100, это 100 дополнительных запросов. Решение, жадная загрузка данных с помощью метода with():
$articles = Article::find()->with('author')->all(); // Все авторы загружаются одним запросом
Использование индексов
Убедитесь, что в таблицах есть индексы на часто используемые поля. Например, для внешних ключей:
CREATE INDEX idx_author_id ON articles(author_id);
В Yii 2 вы можете добавить индексы через миграции:
$this->createIndex('idx_author_id', 'articles', 'author_id');
Оптимизация сложных запросов
Используйте методы ActiveQuery для построения эффективных запросов. Например, select() для выбора только нужных полей:
$articles = Article::find() ->select(['id', 'title', 'created_at']) ->where(['status' => 'published']) ->all();
Практическая задача:
- Найдите в своем коде места с проблемой N+1 и исправьте их, используя
with(). - Добавьте индексы для полей, которые участвуют в условиях
WHEREилиJOIN.
Использование ленивой и жадной загрузки
В Yii 2 есть два подхода к загрузке связанных данных: ленивая (lazy) и жадная (eager).
Ленивая загрузка
Ленивая загрузка происходит «по требованию»:
$article = Article::findOne(1); $author = $article->author; // Отдельный запрос выполняется здесь
Это удобно, но может привести к проблеме N+1.
Жадная загрузка
Жадная загрузка предварительно загружает все связанные данные:
$articles = Article::find()->with(['author', 'comments'])->all();
Yii 2 выполнит всего три запроса:
- Получить статьи.
- Получить авторов статей (WHERE IN).
- Получить комментарии к статьям (WHERE IN).
Пример с вложенными связями:
$articles = Article::find()->with([ 'author.profile', // Загрузить автора и его профиль 'comments.user' ])->all();
Практическая задача:
- Перепишите свой код, заменив ленивую загрузку на жадную там, где это уместно.
- Проверьте количество запросов в Debug Toolbar до и после изменений.
Минификация CSS и JS
Сжатие ресурсов уменьшает их размер и ускоряет загрузку страниц.
Настройка AssetManager
В Yii 2 можно настроить автоматическую минификацию через компонент assetManager в config/web.php:
'assetManager' => [ 'bundles' => [ 'yii\web\JqueryAsset' => [ 'js' => [ YII_ENV_PROD ? 'jquery.min.js' : 'jquery.js' ] ], ], 'appendTimestamp' => true, 'linkAssets' => true, ],
Использование консольных команд
Для минификации можно использовать утилиты вроде UglifyJS или CSSNano.
Например, добавить задачу в Gruntfile.js:
uglify: { options: { compress: {} }, target: { files: { 'web/js/all.min.js': ['src/js/*.js'] } } }
Практическая задача:
- Настройте
assetManagerдля сжатия CSS и JS. - Объедините и минифицируйте свои ресурсы с помощью Grunt/Gulp.
Настройка HTTP-кеширования
Кеширование на стороне клиента или сервера сокращает время обработки повторных запросов.
Кеширование в Action
Используйте фильтр yii\filters\HttpCache:
public function behaviors() { return [ [ 'class' => 'yii\filters\HttpCache', 'only' => ['view'], 'lastModified' => function ($action, $params) { return Article::find()->max('updated_at'); }, ], ]; }
ETag и Last-Modified
Yii 2 автоматически обрабатывает заголовки ETag и Last-Modified, если они заданы:
public function actionView($id) { $model = Article::findOne($id); $response = Yii::$app->response; $response->getHeaders() ->set('Last-Modified', gmdate('D, d M Y H:i:s', $model->updated_at) . ' GMT'); return $this->render('view', ['model' => $model]); }
Практическая задача:
- Добавьте HTTP-кеширование для страницы просмотра статьи.
- Проверьте заголовки ответа в браузере (вкладка Network).
Заключение
Оптимизация это не разовое действие, а постоянный процесс. Начните с анализа самых «тяжелых» мест через Debug Toolbar, настройте кеширование и следите за количеством запросов. Не забывайте применять полученные знания на практике. Если что-то не получается, пишите в комментариях, помогу.
Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.


