Найти в Дзене

Laravel 6: как изменилась жизнь разработчиков PHP?

Оглавление
Laravel framework
Laravel framework

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

Семантическое управление версиями

Фреймворк Laravel теперь соответствует стандарту семантического управления версиями. Это делает фреймворк совместимым с другими пакетами Laravel, уже использующими этот стандарт. Цикл выпуска Laravel останется неизменным.

Совместимость с Laravel Vapor

Автор: Taylor Otwell

Laravel 6.0 обеспечивает совместимость с Laravel Vapor, автоматически масштабируемой безсерверной платформой для развертывания Laravel. Vapor абстрагирует сложность управления приложениями Laravel в AWS Lambda, а также сопряжения этих приложений с очередями SQS, базами данных, кластерами Redis, сетями, CloudFront CDN и многим другим.

Улучшенные ответы авторизации (Improved Authorization Responses)

Реализация: Gary Green

В предыдущих версиях Laravel было сложно получать и выставлять пользовательские авторизационные сообщения конечным пользователям. Это затрудняло объяснение им, почему конкретный запрос был отклонен. В Laravel 6.0 делать это теперь намного проще через авторизационные ответные сообщения и новый метод Gate::inspect. Например, учитывая следующий метод политики:

/**
* Определить, может ли пользователь просматривать данный рейс
*
* @param \App\User $user
* @param \App\Flight $flight
* @return mixed
*/
public function view(User $user, Flight $flight)
{
return $this->deny('Объяснение отказа.');
}

Ответ и сообщение политики авторизации могут быть легко получены при помощи метода Gate::inspect:

$response = Gate::inspect('view', $flight);
if ($response->allowed()) {
// Пользователь имеет право просматривать рейс...
}
if ($response->denied()) {
echo $response->message();
}

Кроме того, эти пользовательские сообщения будут автоматически возвращаться на фронтенд при использовании вспомогательных методов, таких как $this->authorize или Gate::authorize из ваших маршрутов или контроллеров.

Мидлвары задач (Job Middleware)

Реализация: Taylor Otwell

Мидлвары задач позволяет вам обернуть очередь задач в собственную логику, уменьшая шаблонность в самих задачах. Например, в предыдущих версиях Laravel вы могли обернуть логику метода handle задачи коллбэком с ограничением скорости:

/**
* Выполнение задачи
*
* @return void
*/
public function handle()
{
Redis::throttle('key')->block(0)->allow(1)->every(5)->then(function () {
info('Получена блокировка...');
// Выполняем задачу...
}, function () {
// Блокировка не получена...
return $this->release(5);
});
}

В Laravel 6.0 эта логика может быть перемещена в мидлвар задачи, освобождая метод ваш handle задачи от лимитирования скорости:

namespace App\Jobs\Middleware;
use Illuminate\Support\Facades\Redis;
class RateLimited
{
/**
* Обработка задачи из очереди
*
* @param mixed $job
* @param callable $next
* @return mixed
*/
public function handle($job, $next)
{
Redis::throttle('key')
->block(0)->allow(1)->every(5)
->then(function () use ($job, $next) {
// Получена блокировка...
$next($job);
}, function () use ($job) {
// Блокировка не получена...
$job->release(5);
});
}
}

После создания мидлвара их можно прикрепить к задаче, вернув из метода middleware:

use App\Jobs\Middleware\RateLimited;
/**
* Получение мидлвара, через которое должна пройти задача
*
* @return array
*/
public function middleware()
{
return [new RateLimited];
}

Ленивые Коллекции

Реализация Joseph Silber

Многим разработчикам нравятся методы Laravel Collection. Чтобы дополнить и без того мощный класс Collection, Laravel 6.0 представляет LazyCollection, использующий генераторы PHP, для работы с очень большими наборами данных, сохраняя при этом низкое потребление памяти.

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

use App\LogEntry;
use Illuminate\Support\LazyCollection;
LazyCollection::make(function () {
$handle = fopen('log.txt', 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
})
->chunk(4)
->map(function ($lines) {
return LogEntry::fromLines($lines);
})
->each(function (LogEntry $logEntry) {
// обработка записи лога...
});

Или представьте, что вам нужно перебрать 10 000 моделей Eloquent. При использовании традиционных коллекций Laravel все 10 000 моделей Eloquent должны быть загружены в память одновременно:

$users = App\User::all()->filter(function ($user) {
return $user->id > 500;
});

Однако, начиная с Laravel 6.0, метод cursor в построителе запросов был обновлен и теперь возвращает экземпляр LazyCollection. Это позволяет вам по-прежнему выполнять только один запрос к базе данных, но одновременно сохранять в памяти только одну модель Eloquent. В этом примере обратный вызов filter не выполняется до тех пор, пока мы не проведем итерацию по каждому пользователю индивидуально, что позволяет значительно сократить использование памяти:

$users = App\User::cursor()->filter(function ($user) {
return $user->id > 500;
});
foreach ($users as $user) {
echo $user->id;
}

Расширения Eloquent Subquery

Реализация Jonathan Reinink

Laravel 6.0 представляет ряд новых усовершенствований и улучшений в поддержке подзапросов базы данных. Например, давайте представим, что у нас есть таблица destinations и таблица flight. Таблица flights содержит столбец arrived_at который указывает, когда рейс прибыл в пункт назначения.

Используя новую функцию выбора подзапроса в Laravel 6.0, мы можем выбрать все destinations и название рейса, который последний раз прибыл в этот пункт назначения, используя один запрос:

return Destination::addSelect(['last_flight' => Flight::select('name')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->latest()
->limit(1)
])->get();

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

return Destination::orderByDesc(
Flight::select('arrived_at')
->whereColumn('destination_id', 'destinations.id')
->orderBy('arrived_at', 'desc')
->latest()
->limit(1)
)->get();

Laravel UI

Каркас фронтенда, обычно поставляемый с предыдущими версиями Laravel, были перенесен в отдельный пакет laravel/ui. Это позволяет создавать и версионировать пользовательские интерфейсы отдельно от основного фреймворка. В результате этого изменения в дефолтном каркасе фреймворка не будет Bootstrap и Vue. Также была вынесена из фреймворка команда make:auth.

Чтобы восстановить традиционный каракас Vue/Bootstrap, имеющийся в предыдущих версиях Laravel, вы можете установить пакет laravel/ui
и использовать artisan команду
ui для установки фронтенд каркаса:

composer require laravel/ui
php artisan ui vue --auth

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