Laravel 6.0 станет версией LTS (Long Term Support) — с поддержкой в течении длительного времени, вплоть до сентября 2022 года. Шестая версия фреймворка продолжает улучшения, сделанные в Laravel 5.8, переход на семантическое управление версиями, совместимость с Laravel Vapor, улучшенные ответы авторизации, мидлвары задач, ленивые коллекции, улучшения подзапросов, извлечение фронтенд каркаса ( frontend scaffolding) в отдельный пакет laravel/ui, и множество других исправлений и улучшений. Официальный релиз запланирован на 3 сентября 2019 года.
Семантическое управление версиями
Фреймворк Laravel (laravel/framework) теперь соответствует стандарту семантического управления версиями. Это делает фреймворк совместимым с другими пакетами 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 6.0 Release Notes
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.