Laravel 6.0 - What`s New?

Laravel 6.0 - What`s New?

🍪 печенье

Привет.

Данный пост - перевод секции Release Notes из уже доступной, обновленной документации по новой LTS версии фреймворка Laravel - 6.0. Его релиз состоится уже буквально завтра, а обновления будут выходить вплоть до 3 сентября 2021 года (обновления безопасности - до 3 сентября 2022 года). Перед обновлением не забудьте ознакомиться с изменениями существующего функционала.

И не забывайте заглядывать на мой канал @gtxtymt_xyz, где я публикую дев-мемы (иногда даже смешные).

Итак, каких же нововведений стоит ожидать?


Улучшенные ответы авторизации

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

/**
 * Determine if the user can view the given flight.
 *
 * @param  \App\User  $user
 * @param  \App\Flight  $flight
 * @return mixed
 */
public function view(User $user, Flight $flight)
{
    return $this->deny('Explanation of denial.');
}

...информация об ответе может быть легко получена при помощи Gate::inspect.

$response = Gate::inspect('view', $flight);

if ($response->allowed()) {
    // User is authorized to view the flight...
}

if ($response->denied()) {
    echo $response->message();
}

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


Middleware для задач

Middleware для задач (jobs) поможет переместить логику выполнения задач в очереди в middleware, тем самым уменьшив количество кода непосредственно в задачах. Например, ранее вы могли установить ограничение скорости выполнения задач в методе handle:

/**
 * Execute the job.
 *
 * @return void
 */
public function handle()
{
    Redis::throttle('key')->block(0)->allow(1)->every(5)->then(function () {
        info('Lock obtained...');

        // Handle job...
    }, function () {
        // Could not obtain lock...

        return $this->release(5);
    });
}

В Laravel 6.0 эта логика может быть перемещена в middleware, освободив тем самым метод handle от этого кода.

<?php

namespace App\Jobs\Middleware;

use Illuminate\Support\Facades\Redis;

class RateLimited
{
    /**
     * Process the queued job.
     *
     * @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) {
                    // Lock obtained...

                    $next($job);
                }, function () use ($job) {
                    // Could not obtain lock...

                    $job->release(5);
                });
    }
}

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

use App\Jobs\Middleware\RateLimited;

/**
 * Get the middleware the job should pass through.
 *
 * @return array
 */
public function middleware()
{
    return [new RateLimited];
}


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

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

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

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) {
    // Process the log entry...
});

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

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

Однако начиная с Laravel 6.0 метод cursor в конструкторе запросов был обновлен и теперь возвращает экземпляр LazyCollection. Это позволяет сохранять в память всего одну модель, оставляя неизменным количество запросов.

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

foreach ($users as $user) {
    echo $user->id;
}


Расширение подзапросов Eloquent

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

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

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

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

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


Laravel UI

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

Для восстановления традиционных шаблонов вы можете доустановить пакет и использовать команду artisan ui.

composer require laravel/ui

php artisan ui vue --auth


Изменения существующего функционала

Я не буду углубляться в изменения, просто пробегусь поверхностно. Подробней читайте в Upgrade Guide.

  • Минимальная версия PHP - 7.2.

Авторизация

  • Политики авторизации, связанные с контроллерами c использованием метода authorizeResource должны определять метод viewAny, вызываемый в момент обращения к index.
  • Если вы переопределили методы register и registered контроллера RegisterController и не вызываете соответствующие родительские методы - обновите логику, иначе регистрация будет неудачной.
  • Список аргументов __construct класса Illuminate\Auth\Access\Response был изменен.
  • В контракт Illuminate\Contracts\Auth\Access\Gate добавлен новый метод inspect.

Carbon

  • Carbon 1.x больше не поддерживается.

Конфигурация

  • Если вы планируете использовать Laravel Vapor - измените все вхождения AWS_REGION в конфигах на AWS_DEFAULT_REGION, .env также должен содержать новое имя переменной.

База данных

  • Аргументы метода table класса Illuminate\Database\Capsule\Manager обновлены для указания псевдонима таблицы вторым аргументом - public static function table($table, $as = null, $connection = null)
  • Метод cursor теперь возвращает экземпляр Illuminate\Support\LazyCollection.

Eloquent

  • Метод update для отношений belongsTo теперь работает как ah-doc запрос, то есть не обеспечивает защиту от массовых назначений или запуск событий Eloquent.
  • Метод Eloquent toArray теперь будет приводить любые атрибуты, реализующие Illuminate\Contracts\Support\Arrayable в массив.
  • Из-за оптимизации производительности целочисленных типов ключей если в качестве ключа вы используете строку - необходимо указать это в свойстве protected $keyType = 'string';

Верификация email

  • Роут email/resend изменен с GET на POST.
  • В контракт Illuminate\Contracts\Auth\MustVerifyEmail добавлен метод getEmailForVerification, возвращающий адрес email, связанный с объектом (не актуально для App\User, так как изменения уже реализованы в трейте).

Хелперы

  • Все str_ и array_ хелперы перемещены в пакет composer laravel/helpers и удалены из фреймворка.

Переводы

  • Методы Lang::trans и Lang::transChoice переводчика переименованы в Lang::get и Lang::choice. Аналогичные изменения содержатся в контракте Illuminate\Contracts\Translation\Translator.
  • Методы Lang::get и Lang::getFromJson были объединены.

Почта

  • Удалены драйвера mandrill и sparkpost.

Уведомления

  • Удалена устаревшая часть канала уведомлений Nexmo.

Сброс пароля

  • PasswordBroker больше не занимается проверкой и ограничением пароля, все происходит в классе ResetPasswordController.

Очереди

  • Команда queue:work теперь пытается выполнить задание только 1 раз в случае ошибки (ранее - бесконечно).

Requests

  • Фасад Input, дубликатор Request, удален.

Планировщик задач

  • Метод between теперь запускает задачу каждую минуту в течении указанного промежутка времени (раньше - каждую минуту между указанными промежутками).

Storage

  • Удален драйвер rackspace.

Report Page