Стратегии оптимизации производительности Laravel

Источник: «Maximizing Laravel Performance: Essential Optimization Strategies for Web Developers»
Познакомьтесь с ключевыми стратегиями повышения производительности Laravel-приложений, включая кэширование, эффективное кодирование и оптимизацию баз данных.

Когда речь идёт о веб-сайтах, производительность веб-приложений/сайтов влияет на удобство использования и рейтинг в поисковых системах. При разработке с PHP фреймворком Laravel вы получаете функции и методы, включённые в фреймворк, для оптимизации скорости и эффективности работы сайта. В этой статье мы обсудим оптимизацию Laravel с использованием эффективных стратегий кэширования, эффективных запросов к базам данных, ленивой загрузки против нетерпеливой загрузки, и другие методы повышения производительности.

Стратегии кэширования

Кэширование используется для снижения нагрузки на базу данных и ускорения ответа. В Laravel есть множество бэкендов для кэширования, таких как Memcached и Redis. Их довольно просто реализовать в Laravel.

// Кэширование результатов запроса на 60 минут
$posts = Cache::remember('posts', 60, function () {
return Post::all();
});

Этот код проверяет наличие posts, и если их нет, то извлекает их и добавляет в кэш на 60 минут.

use Illuminate\Support\Facades\Cache;

$popularPosts = Cache::remember('popular_posts', 1440, function () {
return Post::with('author', 'comments')
->where('views', '>', 1000)
->orderBy('views', 'DESC')
->take(10)
->get();
});

Этот запрос кэширует топ-10 популярных постов вместе с авторами и комментариями в течение 1440 минут (24 часа). Запрос использует with для минимизации количества выполняемых запросов.

Составление запросов к базе данных для оптимизации Laravel

Мы всегда стараемся улучшить запросы к базе данных, но Laravel предоставляет Eloquent ORM, позволяющий писать сложные запросы простым способом, но важнее всего знать, как написать эффективный запрос.

// Вместо получения всех столбцов укажите нужные
$users = User::select('id', 'name', 'email')->get();

Этот небольшой и конкретный запрос снижает ненужную нагрузку на базу данных. Он извлекает только то, что необходимо.

$postsWithActiveAuthors = Post::whereHas('author', function ($query) {
$query->where('active', 1);
})->get();

Этот сниппет использует метод whereHas для получения сообщений, у которых есть активные авторы (очень полезно). Это делает запрос эффективным, позволяя не загружать все посты.

Ленивая загрузка vs Нетерпеливая загрузка

Laravel предоставляет возможность выбора способа загрузки связанных моделей. Ленивая загрузка, означающая, что связанные модели загружаются по требованию, и нетерпеливая загрузка, при которой связанные модели загружаются все сразу. В большинстве случаев предпочтительнее использовать нетерпеливую загрузку, если только у вас нет очень специфического случая для ленивой загрузки.

// Ленивая загрузка (неэффективная)
$books = Book::all();
foreach ($books as $book) {
echo $book->author->name;
}

// Нетерпеливая загрузка (эффективная)
$books = Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}

Нетерпеливая загрузка позволяет получить связанные модели в одном запросе и избежать проблемы N+1 при ленивой загрузке.

$users = User::all();
foreach ($users as $user) {
// Это приведёт к выполнению нового запроса для каждого пользователя, чтобы получить его сообщения
foreach ($user->posts as $post) {
echo $post->title;
}
}

Неэффективно: Сообщения каждого пользователя не обрабатываются до тех пор, пока к ним не будет получен доступ внутри цикла, что приводит к многочисленным запросам.

$users = User::with('posts')->get();
foreach ($users as $user) {
// Все сообщения загружаются вместе с пользователями в одном запросе
foreach ($user->posts as $post) {
echo $post->title;
}
}

Эффективно: with('posts') гарантирует, что все сообщения будут загружены в одном запросе. Это сокращает количество запросов до одного, делая его более эффективным.

Другие методы оптимизации

Внедрение приведённых ниже методов оптимизации Laravel также способствует значительному увеличению производительности приложения.

Оптимизируйте ресурсы

Laravel Mix предоставляет чистый и понятный API для сборки webpack. Мы можем использовать его для минификации и объединения CSS и JavaScript файлов. Это уменьшает количество HTTP-запросов.

// webpack.mix.js
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
.minify('public/js/app.js');

mix.sass('resources/sass/app.scss', 'public/css')
.minify('public/css/app.css');

Этот пример компилирует файлы JS и SASS и минифицирует их, в результате чего файлы становятся намного меньше и быстрее загружаются.

Индексирование базы данных

Используйте Index для столбцов, которые часто ищутся или используются в качестве внешних ключей. Это повышает производительность запросов к базе данных, а Index можно добавить с помощью миграций.

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('posts', function (Blueprint $table) {
// Создание индекса для столбца 'title'
$table->index('title');

// Создание уникального индекса для столбца 'slug'
$table->unique('slug');

// Индекс внешнего ключа
$table->foreign('user_id')->references('id')->on('users');
});

Кэширование маршрутов

Кэширование маршрутов повышает производительность сайта, особенно если у вас большое количество маршрутов.

php artisan route:cache

Здесь мы создаём файл кэша маршрутов для ускорения регистрации маршрутов. Обратите внимание, что для добавления новых маршрутов необходимо повторно выполнить эту команду.

Очереди для оптимизации Laravel

Для задач, требующих много времени, например, отправки электронной почты или обработки изображений, целесообразно выполнять их в фоновом режиме. Система очередей Laravel предназначена для постановки определённых задач в очередь и их асинхронной обработки.

Сначала создайте новое задание.

php artisan make:job ProcessImage

Далее добавьте поведение задания.

// app/Jobs/ProcessImage.php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessImage implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

protected $image;

public function __construct($image)
{
$this->image = $image;
}

public function handle()
{
// Обработайте изображение здесь
}
}

Теперь отправьте задание.

ProcessImage::dispatch($image);

Этот фрагмент отправляет задание на обработку изображения в очередь по умолчанию, а Laravel делает всё остальное.

Подведение итогов

Оптимизация приложения Laravel включает в себя сочетание стратегий кэширования, эффективных операций с базами данных и умной загрузки ресурсов. Применяя эти методы, вы сможете значительно сократить время загрузки и использование ресурсов, что приведёт к более плавному взаимодействию с пользователями и потенциально более высокому SEO-рейтингу.

Дополнительные материалы

Предыдущая Статья

PHP 8.4: Новые возможности и изменения

Следующая Статья

Laravel 11: Руководство по обновлению