Laravel 7 — Что нового?

Laravel 7 вышел 3 марта 2020 года и содержит следующие нововедения и улучшения.

Laravel Sanctum

Автор: Taylor Otwell

Laravel Sanctum предоставляет легковесную систему аутентификации для SPA (одностраничных приложений), мобильных приложений и простых API на основе токенов. Sanctum позволяет каждому пользователю вашего приложения сгенерировать несколько токенов API для своей учетной записи. Этим токенам могут быть предоставлены способности/области действия, которые определяют, какие действия токенам разрешено выполнять. Ранее пакет назывался Airlock.

Для получения дополнительной информации о Laravel Sanctum обратитесь к документации.

Пользовательские Eloquent Касты (Custom Eloquent Casts)

Автор: Taylor Otwell

У Laravel есть множество полезных встроенных типов приведения (кастов), но иногда вам может понадобиться сделать свои собственные. Теперь можно это сделать, реализовав интерфейс CastsAttributes.

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

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Json implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return array
     */
    public function get($model, $key, $value, $attributes)
    {
        return json_decode($value, true);
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  array  $value
     * @param  array  $attributes
     * @return string
     */
    public function set($model, $key, $value, $attributes)
    {
        return json_encode($value);
    }
}

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

namespace App;

use App\Casts\Json;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => Json::class,
    ];
}

Чтобы научиться создавать свои собственные Eloquent касты, включая касты к значениям объектов, обратитесь к документации Eloquent.

Теги и улучшения для Blade-компонентов

Авторы: Spatie, Marcel Pociot, Caleb Porzio, Dries Vints, Taylor Otwell

Blade-компоненты были переработаны, чтобы получить возможность рендера на основе тегов, управления атрибутами, классами компонентов, встроенными компонентами и многого другого. Поскольку изменения были значительны, то рекомендуем ознакомиться с полной документацией по компонентам Blade

Таким образом, теперь компонент может иметь связанный с ним класс, который указывает принимаемые данные. Все публичные свойства и методы, определенные в классе компонента, будут автоматически доступны для шаблона компонента. Любые дополнительные HTML-атрибуты, указанные в компоненте, могут управляться через автоматически вставляемую переменную $attribute, являющейся экземпляром пакета атрибутов.

Предположим, что App\View\Components\Alert определен следующим образом:

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    /**
     * Тип alert.
     *
     * @var string
     */
    public $type;

    /**
     * Создание экземпляра компонента.
     *
     * @param  string  $type
     * @return void
     */
    public function __construct($type)
    {
        $this->type = $type;
    }

    /**
     * Получение класса для данного типа alert.
     *
     * @return string
     */
    public function classForType()
    {
        return $this->type == 'danger' ? 'alert-danger' : 'alert-warning';
    }

    /**
     * Получение шаблона/содержимого компонента
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.alert');
    }
}

А шаблон Blade-компонента определен так:

<!-- /resources/views/components/alert.blade.php -->

<div class="alert {{ $classForType() }}" {{ $attributes }}>
    {{ $heading }}

    {{ $slot }}
</div>

Компонент может быть отрендерен в другом Blade-шаблоне через тег компонента:

<x-alert type="error" class="mb-4">
    <x-slot name="heading">
        Содержимое Alert...
    </x-slot>

    Содержимое слота по умолчанию...
</x-alert>

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

Предыдущий синтаксис @component для Blade-компонентов не был и не будет удален.

HTTP-клиент

HTTP-клиент является оберткой над Guzzle и сделан: Adam Wathan, Jason McCreary, Taylor Otwell.

Laravel теперь предоставляет выразительный минималистичный API для Guzzle HTTP-клиента, позволяющий быстро создавать HTTP-запросы для связи с другими веб-приложениями. Обертка над Guzzle сфокусирована на наиболее распространенных сценариях использования и опыте разработчиков. Например, клиент делает быстрый POST и взаимодействует с JSON-данными:

use Illuminate\Support\Facades\Http;

$response = Http::withHeaders([
    'X-First' => 'foo'
    'X-Second' => 'bar'
])->post('http://test.com/users', [
    'name' => 'Taylor',
]);

return $response['id'];

Кроме того, HTTP-клиент предоставляет фантастический и эргономичный функционал для тестирования:

Http::fake([
    // Заглушка для JSON ответа конечных точек GitHub...
    'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),

    // Заглушка для ответа от конечных точек Google...
    'google.com/*' => Http::response('Hello World', 200, ['Headers']),

    // Заглушка для ответов от конечных точек Facebook...
    'facebook.com/*' => Http::sequence()
                            ->push('Hello World', 200)
                            ->push(['foo' => 'bar'], 200)
                            ->pushStatus(404),
]);

Чтобы узнать больше обо всех функциях HTTP-клиента, обратитесь к документации.

Быстрые операции со Строками

Автор: Taylor Otwell

Вы, вероятно, знакомы с имеющимся Laravel-классом Illuminate\Support\Str, предоставляющий множество полезных функций для работы со строками. Laravel 7 теперь предлагает более объектно-ориентированную библиотеку для работы со строками, построенную поверх этих функций. Вы можете создать объект Illuminate\Support\Stringable используя метод Str::of. Затем к объекту можно цепочкой применить множество методов для работы со строкой:

return (string) Str::of('  Laravel Framework 6.x ')
                    ->trim()
                    ->replace('6.x', '7.x')
                    ->slug();

Для получения дополнительной информации о методах работы со строками, пожалуйста, обратитесь к полной документации.

Улучшенная привязка модели к маршруту

Автор: Taylor Otwell

Кастомизация ключа

Иногда вы хотите получить eloquent-модель по столбцу отличному от id. Laravel 7 позволяет вам указать нужный столбец в определении параметра маршрута:

Route::get('api/posts/{post:slug}', function (App\Post $post) {
    return $post;
});

Автоматический скоупинг

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

use App\Post;
use App\User;

Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
    return $post;
});

При использовании кастомной неявной привязки с ключом в качестве параметра вложенного маршрута Laravel 7 автоматически сделает запрос, чтобы получить вложенную модель по ее родителю, используя соглашения, позволяющие угадать имя отношения для родителя. Предполагается, что модель User имеет отношение с именем posts (множественное число от имени параметра маршрута), которое можно использовать для получения модели Post.

Для получения дополнительной информации о привязке модели к маршруту, пожалуйста, обратитесь к документации по маршрутизации.

Множественные почтовые драйвера

Автор: Taylor Otwell

Laravel 7 позволяет сконфигурировать несколько «почтовиков» для одного приложения. Каждый почтовик, настроенный в конфигурационном файле mail может иметь свои собственные параметры и даже свой собственный уникальный «транспорт», позволяющий вашему приложению использовать различные почтовые службы для отправки определенных почтовых сообщений. Например, ваше приложение может использовать Postmark для отправки транзакционной почты, а Amazon SES — для массовых рассылок.

По умолчанию Laravel будет использовать почтовик, настроенный как default. Однако вы можете использовать метод mailer для отправки сообщений, используя нужную конфигурацию:

Mail::mailer('postmark')
        ->to($request->user())
        ->send(new OrderShipped($order));

Улучшения скорости кеширования маршрутов

Авторы: разработчики Symfony и Dries Vints.

Laravel 7 включает новый метод сопоставления скомпилированных кэшированных маршрутов, которые были кэшированы с помощью artisan-команды route:cache. В больших приложениях (например, в приложениях с 800 или более маршрутами) эти улучшения могут привести к двукратному увеличению скорости на простом тесте «Hello World». Никаких изменений в вашем приложении это не требует.

CORS Support

Автор: Matt Barlow

Laravel 7 включает в себя поддержку Cross-Origin Resource Sharing (CORS — совместное использование ресурсов между разными источниками) интегрируя популярный пакет Laravel CORS, написанный Barry vd. Heuvel. Новая конфигурация cors включена в дефолтный скелет приложения Laravel.

Для получения дополнительной информации о поддержке CORS в Laravel 7.x, пожалуйста, обратитесь к документации CORS.

Касты времени в запросах

Автор: Matt Barlow

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

use App\Post;
use App\User;

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
            ->whereColumn('user_id', 'users.id')
])->get();

Аттрибут last_posted_at в результатах этого запроса будет необработанной строкой. Было бы удобно, если бы мы могли применить каст date к этому атрибуту при выполнении запроса. Для этого мы можем использовать метод withCasts предоставленный Laravel 7:

$users = User::select([
    'users.*',
    'last_posted_at' => Post::selectRaw('MAX(created_at)')
            ->whereColumn('user_id', 'users.id')
])->withCasts([
    'last_posted_at' => 'date'
])->get();

Улучшения очереди базы данных MySQL 8+

Автор: Mohamed Said

В предыдущих выпусках Laravel очередь database не считалась достаточно надежной для использования на боевых серверах из-за взаимных блокировок. Тем не менее, Laravel 7 предоставляет улучшения для приложений, использующих MySQL 8+ в качестве очереди. Используя оператор FOR UPDATE SKIP LOCKED и другие усовершенствования SQL, драйвер database теперь можно безопасно использовать на крупномасштабных боевых серверах.

Artisan-команда test

Автор: Nuno Maduro

В дополнение к команде phpunit вы можете теперь использовать artisan-команду test для запуска ваших тестов. Artisan-тестировщик предоставляет прекрасную UX-консоль и множество информации о выполняемом тесте. Кроме того, он автоматически остановится при первом проваленном тесте:

php artisan test

Laravel 7 - что нового

Любые аргументы, которые могут быть переданы команде phpunit также могут быть переданы и artisan-команде test:

php artisan test --group=feature

Улучшения почтового шаблона Markdown

Автор: Taylor Otwell

Дефолтный почтовый шаблон Markdown получил новый, более современный дизайн, основанный на цветовой палитре Tailwind CSS. Конечно, этот шаблон может быть настроен и использован в соответствии с вашими потребностями:

Laravel 7 - что нового

Для получения дополнительной информации о Markdown, пожалуйста, обратитесь к документации.

Настройка заглушек

Автор: Taylor Otwell

Консольные artisan-команды make используются для создания различных классов, таких как контроллеры, задачи, миграции и тесты. Эти классы создаются с использованием файлов-«заглушек», заполняемых значениями на основе вашего ввода. Однако иногда вы можете захотеть внести какие-либо изменения в эти файлы. Для этого Laravel 7 предоставляет команду stub:publish, публикующей наиболее распространенные заглушки для последующей их настройки:

php artisan stub:publish

Опубликованные заглушки будут находиться в каталоге stubs в корне вашего приложения. Любые изменения, внесенные в эти заглушки, будут отражены при создании соответствующих классов с помощью artisan-команд make.

Настройка maxExceptions для Очереди

Автор: Mohamed Said

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

namespace App\Jobs;

class ProcessPodcast implements ShouldQueue
{
    /**
     * Количество попыток выполнения задачи
     *
     * @var int
     */
    public $tries = 25;

    /**
     * Максимальное количество исключений разрешенных до отказа
     *
     * @var int
     */
    public $maxExceptions = 3;

    /**
     * Выполнение задачи
     *
     * @return void
     */
    public function handle()
    {
        Redis::throttle('key')->allow(10)->every(60)->then(function () {
            // Получена блокировка, обрабатываем подкаст... 
        }, function () {
            // Невозможно получить блокировку...
            return $this->release(10);
        });
    }
}

В этом примере задача откладывается на десять секунд, если приложение не может получить блокировку Redis и это будет повторяться до 25 раз. Тем не менее, задача провалится, если сгенерирует три необработанных исключения.

Автор: Laravel
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.