Статьи

Каковы новые функции в Laravel 5.5?

Laravel 5.5 потребует PHP 7.0+. О возможностях этой современной версии PHP вы можете прочитать в нашем резюме .

Laravel Logo с 5,5 рядом

Laravel 5.5 также станет следующим выпуском LTS (Long Term Support). Это означает исправления ошибок за два года и три года обновлений безопасности. Так было и с Laravel 5.1, но его двухлетнее окно исправлений ошибок подходит к концу в этом году. Без дальнейших церемоний, давайте посмотрим, что может предложить эта новая версия.

Создание нового проекта Laravel 5.5

Поскольку релиз еще не произошел официально, мы можем установить версию релиза dev, выполнив команду:

laravel new laravel55 --dev cd laravel55 php artisan key:generate 

Если вы предпочитаете не использовать установщик Laravel, вы также можете воспользоваться подходом Composer :

 composer create-project --prefer-dist --stability=dev laravel/laravel:dev-master cd laravel php artisan key:generate 

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

Рендеринг почтовых отправлений в браузер

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

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

 php artisan make:mail Welcome --markdown=emails.welcome 

Я предпочитаю подход уценки, так как мы получим шаблон с некоторым содержанием. Давайте откроем наш файл web.php и создадим тестовый маршрут для проверки макета электронной почты:

 Route::get('/email', function () { return new App\Mail\Welcome(); }); 

routes/web.php

Посещая маршрут /email мы сможем просмотреть шаблон электронной почты:

Предварительный просмотр электронной почты

Что на самом деле происходит под капотом, так это то, что в Laravel 5.5 класс Mailable реализует контракт Mailable который имеет метод render() . Это реализация метода render() внутри lluminate/Mail/Mailable.php :

 public function render() { Container::getInstance()->call([$this, 'build']); return Container::getInstance()->make('mailer')->render( $this->buildView(), $this->buildViewData() ); } 

lluminate/Mail/Mailable.php

Это метод, который позволяет получить представление. Если бы мы попытались вернуть экземпляр класса, который не реализует контракт Renderable в наших маршрутах, мы бы получили UnexpectedValueException .

Пользовательские темы электронной почты

При использовании Markdown для электронной почты Laravel будет предоставлять тему по умолчанию. Тем не менее, некоторые люди могут предпочесть использовать собственные стили в своих шаблонах электронной почты для брендинга.

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

 touch resources/views/vendor/mail/html/themes/custom.css 

Затем мы указываем это имя файла как свойство в классе Mailable:

 class Welcome extends Mailable { protected $theme = 'custom'; [...] } 

app/Mail/Welcome.php

Таким образом, макет электронной почты будет основан на стилях, которые мы определили в файле custom.css . Преимущество такого подхода в том, что у нас могут быть разные темы для разных почтовых сообщений.

Вспомогательные функции исключения

Laravel 5.5 поставляется с двумя вспомогательными функциями исключений, которые помогут нам написать более выразительный код. Двумя помощниками являются методы throw_if и throw_unless . Оба принимают три аргумента, третий аргумент является необязательным.

Давайте посмотрим на различные реализации этих исключений:

 $number = 2; throw_if($number !== 3, new NotThreeException('Number is not three')); // or throw_if($number !== 3, NotThreeException::class, 'Number is not three'); 

С помощником throw_if исключение, если первый аргумент оценивается как true.

Реализация хелпера throw_unless ничем не отличается от того, что мы делали выше, с той лишь разницей, что исключение будет throw_unless только в том случае, если первый аргумент оценивается как false:

 $number = 2; throw_unless($number === 3, new NotThreeException('Number is not three')); // or throw_unless($number === 3, NotThreeException::class, 'Number is not three'); 

Не лучший пример, но служит нашим демонстрационным целям.

Представляем миграцию: свежая команда

Вы, вероятно, оказались в ситуации, когда вам потребовалось восстановить базу данных. В предыдущих версиях Laravel мы достигли этого, выполнив команду php artisan migrate:refresh . Команда migrate:refresh откатывает все миграции на основе того, что указано в методе down для каждого файла миграции, а затем снова запускает миграции:

Миграция Обновить

Но вы, вероятно, сталкивались с проблемами с этой командой пару раз, особенно при работе с ограничениями внешнего ключа или если у вас есть метод down() в одной из ваших миграций, который не был четко определен. Когда это происходит, мы прибегаем к удалению проблем с поднятием таблицы в большинстве случаев вручную (может быть из CLI или некоторого GUI) . Вот где migrate:fresh приходит к нам на помощь. Эта команда удаляет все таблицы, затем снова запускает существующие миграции:

Migrate Fresh

Трассировки стека ошибок JSON

Не очень большое изменение, но тогда в предыдущих версиях Laravel мы видели HTML-разметку от клиента API, такого как Postman, каждый раз, когда возникали ошибки при создании API. В Laravel 5.5 мы получаем трассировку стека JSON, а не разметку HTML, если возникает ошибка, которая выглядит аккуратнее и проще для отслеживания:

Трассировка стека JSON

Автоматическое обнаружение пакетов

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

  • Установить пакет
  • Зарегистрируйте поставщика услуг пакета
  • Зарегистрировать фасады, если есть

Как видите, это может быть проще. Теперь есть.

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

Глядя на пакет отладки Laravel, который уже был обновлен для автоматического обнаружения пакетов, мы видим, что в файле composer.json есть extra раздел:

 "extra": { "laravel": { "providers": [ "Foo\\Bar\\ServiceProvider" ], "aliases": { "Bar": "Foo\\Bar\\Facade" } } } 

Поставщики пакетов должны будут обновить файл composer.json с дополнительным разделом, а затем указать поставщиков и любые псевдонимы для пакета.

Еще одна полезная вещь при автоматическом обнаружении пакетов — это то, что после удаления зависимости ничего не сломается. Как правило, даже после удаления пакета у нас все еще есть провайдеры услуг и фасады config/app.php файле config/app.php и в некоторых случаях это может вызвать проблемы.

При автоматическом обнаружении пакетов, когда пакет удаляется через Composer , все, что связано с пакетом, также удаляется.

Изменения в поставщике: команда publish

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

С Laravel 5.5 мы должны быть немного более точными в том, что мы хотим опубликовать при запуске этой команды. Если мы запустим php artisan vendor:publish без каких-либо флагов, нам будет предложено выбрать поставщика или тег, чтобы было проще публиковать только то, что мы хотим. Смотрите скриншот ниже:

продавец: опубликовать подсказку

Мы можем обойти приглашение, указав флаг --all или --provider при запуске команды publish :

 php artisan vendor:publish --all 

Разнообразие предварительных настроек интерфейса

В Laravel 5.3 и 5.4 у нас были некоторые леса Vue и Bootstrap по умолчанию, чтобы помочь нам с интерфейсным битом. В этой новой версии React был включен в микс. Это не там по умолчанию, хотя.

Существует новая команда для управления предварительными настройками внешнего интерфейса. Это означает, что у нас будут только леса для того пресета, с которым мы хотим работать. Но тогда не все хотят использовать стандартные предварительные настройки внешнего интерфейса — то есть Vue, Bootstrap и React — и могут выбрать что-то еще, возможно, другую внешнюю среду. И Ларавел уже учел это:

 php artisan preset none 

Приведенная выше команда удалит все существующие внешние леса. Если бы мы хотели использовать React для нашего интерфейса, команда ниже дала бы нам некоторые леса React:

 php artisan preset react 

Ниже приведен скриншот этой новой команды в действии:

Пресеты внешнего интерфейса

К сожалению, вернулся!

Laravel 5.5 принес Ой! назад, изменив способ отображения ошибок. С упс! Каждый раз, когда у нас возникает ошибка в разработке, мы сможем увидеть строку кода, которая привела к ошибке в виде скриншота, а также сообщение об ошибке.

На мой взгляд, сообщения об ошибках выглядят лучше с этим новым обработчиком, а тот факт, что мы получаем скриншот со строкой кода, которая привела к ошибке, делает отладку еще проще:

Пример ошибки Whoops:
ошибка упс

Еще одна интересная вещь: у Whoops есть возможность открывать ссылочные файлы прямо в вашей IDE или редакторе. Эта функция работает только в том случае, если ваши исходные PHP-файлы локально доступны для компьютера, на котором установлен редактор. Для этого перейдите в app / Exceptions / Handler.php и добавьте этот фрагмент:

 [...] use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Arr; use Whoops\Handler\PrettyPageHandler; [...] class Handler extends ExceptionHandler { [...] protected function whoopsHandler() { return tap(new PrettyPageHandler, function ($handler) { $files = new Filesystem; $handler->setEditor('sublime'); $handler->handleUnconditionally(true); $handler->setApplicationPaths( array_flip(Arr::except( array_flip($files->directories(base_path())), [base_path('vendor')] )) ); }); } } 

app\Exceptions\Handler.php

Приведенный выше фрагмент переопределяет метод whoopsHandler() из базового класса, добавив строку: $handler->setEditor('sublime') , в результате чего ссылка открывается в Sublime Text. Если вы используете другой редактор, перейдите по этой ссылке, чтобы увидеть список поддерживаемых редакторов, а также узнать, как добавить свой собственный редактор. Пользователи Mac, не забудьте скачать превосходный протокол URL, чтобы это работало.

Пользовательский метод отчета об исключениях

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

 [...] public function report(Exception $exception) { if ($exception instanceof CustomException) { // Do something } if ($exception instanceof MyOtherException) { // Do something } if ($exception instanceof MyOtherCustomException) { // Do something } return parent::report($exception); } [...] 

app/Exceptions/Handler.php

Скажем, у нас есть около 50 пользовательских исключений — вы можете сказать, что все станет ужасно.

В Laravel 5.5 можно указать, что происходит, когда выбрасывается пользовательское исключение, создав метод report() внутри этого исключения:

 [...] class CustomException extends \Exception { public function report() { // send email } } [...] 

app/Exceptions/CustomException.php

Модельный завод Генераторы

Laravel 5.5 ввел новую команду для создания фабрики моделей. Модельные фабрики пригодятся, когда мы хотим создать поддельные данные или новый экземпляр объекта при написании тестов.

Чтобы сгенерировать фабрику для определенного класса, мы запускаем команду:

 php artisan make:factory Post 

Если мы теперь перейдем к database/factories , мы увидим класс PostFactory :

 [...] $factory->define(App\Post::class, function (Faker $faker) { return [ // ]; }); 

базы данных / фабрики / PostFactory.php

Я считаю этот подход более элегантным из-за разделения интересов. В предыдущих версиях Laravel все фабрики app/factories/ModelFactory.php файл app/factories/ModelFactory.php .

Подтверждение возврата данных

Теперь можно получить данные из валидатора и передать их методу create . В предыдущих версиях Laravel так мы создавали новые объекты:

 public function store() { $this->validate(request(), [ 'title' => 'required', 'body' => 'required' ]); // return Post::create(request()->only(['title', 'body'])); or return Post::create(request()->all()); } 

Laravel 5.5 теперь позволяет нам создавать объекты непосредственно из проверенных данных:

 public function store() { $post = $this->validate(request(), [ 'title' => 'required', 'body' => 'required' ]); return Post::create($post); } 

Также возможно вызвать validate для экземпляра запроса непосредственно в Laravel 5.5:

 public function store() { $post = request()->validate([ 'title' => 'required', 'body' => 'required' ]); return Post::create($post); } 

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

 $post = request()->validate([ 'title' => 'required', 'body' => 'required', 'notRequiredField' => '', ]); return Post::create($post); 

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

Пользовательские правила проверки

Это было все еще возможно в предыдущих версиях Laravel, используя метод Validator::extend . Однако вещи не были централизованы. У нас было правило перейти в файл AppServiceProvider , а затем сообщение в файле resources/lang/en/validation.php . См. Документацию Laravel о том, как этого добиться в Laravel 5.4.

В Laravel 5.5 у нас есть новая команда для определения пользовательской проверки. Эта команда сгенерирует новый класс, реализующий контракт Rule . Давайте сгенерируем новое правило, чтобы увидеть, что находится внутри этого сгенерированного файла:

 php artisan make:rule CustomRule 

Если мы посмотрим в app/Rules/CustomRule.php , мы увидим два метода, то есть метод app/Rules/CustomRule.php и метод message . Метод passes принимает два аргумента, т.е. attribute и value , и возвращает логическое значение. Если вы не уверены, $attribute — это поле, которое нужно проверить, а $value — это фактическое значение, передаваемое этому атрибуту.

В качестве примера, скажем, мы не хотим, чтобы наше приложение получило определенное имя, тогда наше правило будет выглядеть так:

 class CustomRule implements Rule { [...] public function passes($attribute, $value) { return $value !== 'unwantedname'; } public function message() { return 'You cannot use that as your username'; } [...] } 

app/Rules/CustomRule.php

Затем, используя новое правило для проверки нашего атрибута username :

 use App\Rules\CustomRule; request()->validate([ 'username' => [ 'required', new CustomRule() ], 'anotherfield' => 'required|min:5' ]); 

app/Rules/CustomRule.php

Посмотрите пост Тейлора Отвелла, в котором подробно рассказывается, как определить пользовательскую проверку в этой новой версии Laravel.

DD и дамп идут в коллекции

Коллекции теперь имеют метод dump() а также метод dd() . В предыдущих версиях Laravel при отладке коллекций мы назначали переменную для коллекции, а затем продолжали выгружать переменную при изменении коллекции. В Laravel 5.5 этого больше не будет, поскольку теперь мы можем вызывать dd() или dump() непосредственно для коллекции, что значительно упрощает отладку.

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

  $posts = Post::all(); $posts ->dump() ->sorBy('title') ->dump() ->pluck('title') ->dump(); 

И вывод:

 Collection {#284 ▼ #items: array:3 [▼ 0 => Post {#285 } 1 => Post {#286 } 2 => Post {#287 } ] } Collection {#272 ▼ #items: array:3 [▼ 0 => Post {#285 } 2 => Post {#287 } 1 => Post {#286 } ] } Collection {#268 ▼ #items: array:3 [▼ 0 => "Aida Bosco" 1 => "Madge Leuschke" 2 => "Miss Bulah Armstrong Jr." ] } 

Это позволяет легко просматривать содержимое коллекции на каждом этапе. Заметьте, однако, что есть разница между вызовами dump() и dd() для коллекции. dump() выводит результаты в этот момент и затем продолжает обработку, в то время как dd() немедленно останавливает процесс и выдает результаты ( dd обозначает dump and die ). Если бы мы вызывали dd() для коллекции на каждом шаге, то мы получили бы результаты только в самый первый момент, когда мы вызывали dd() для коллекции. Учти это:

  $posts = Post::all(); $posts ->dump() ->sorBy('title') ->dd() ->pluck('title') ->dump(); 

Вывод будет другим:

 Collection {#284 ▼ #items: array:3 [▼ 0 => Post {#285 } 1 => Post {#286 } 2 => Post {#287 } ] } array:3 [▼ 0 => Post {#285 } 2 => Post {#287 } 1 => Post {#286 } ] 

Кастинг сводных таблиц во многих отношениях

Обычно можно объявить свойство casts в модели, которое определяет, как атрибут должен быть сохранен или прочитан. Допустим, у нас есть модель Post и среди полей мы хотим, чтобы одно поле было сериализовано как JSON во время чтения и записи, тогда приведенный ниже фрагмент кода поможет нам достичь этого:

 class Post extends Model { [...] protected $casts = [ 'somefield' => 'array', ]; [...] } 

В Laravel 5.4 они даже позволяли приводить настраиваемые стержни в отношениях «многие ко многим», но это ограничивалось только чтением данных. Если бы мы хотели выполнить операции записи данных, мы сначала должны были привести значения атрибутов вручную, прежде чем наконец сохранить. Это больше не будет иметь место, поскольку свойство $casts Eloquent\Relations\Pivot классах Eloquent\Model и Eloquent\Relations\Pivot будет вести себя одинаково, делая методы attach , sync и save доступными для моделей Eloquent\Relations\Pivot .

Custom Blade :: if () Директивы

Длинные повторяющиеся проверки в шаблонах блэйдов могут сделать наши шаблоны некрасивыми. Хорошей новостью является то, что теперь стало возможным абстрагировать повторяющиеся проверки от шаблонов, в результате чего наши шаблоны выглядят чище и более читабельными. Проверки как:

 @if (auth()->check() && auth()->user()->isSubscribed()) <p>Subscribed</p> @else <p>Not Subscribed</p> @endif С @if (auth()->check() && auth()->user()->isSubscribed()) <p>Subscribed</p> @else <p>Not Subscribed</p> @endif 

Можно заменить на:

 @subscribed <p>Subscribed</p> @else <p>Not Subscribed</p> @endsubscribed С @subscribed <p>Subscribed</p> @else <p>Not Subscribed</p> @endsubscribed 

Логика создания пользовательской директивы blade-системы находится внутри boot метода класса AppServiceProvider :

 [...] use Illuminate\Support\Facades\Blade; class AppServiceProvider extends ServiceProvider { [...] public function boot() { Blade::if('subscribed', function () { return auth()->check() && auth()->user()->isSubscribed(); }); } [...] } 

app/Providers/AppServiceProvider.php

Некоторые проверки могут требовать передачи аргумента в какой-либо метод. В этом случае мы передаем аргумент нашему закрытию, когда создаем пользовательскую директиву blade-сервера.

 @if (auth()->check() && auth()->user()->isFollowing($user->id)) 

Используя приведенное выше условие в качестве примера, мы видим, что нам нужно, чтобы $user->id передан isFollowing() . Чтобы создать пользовательскую директиву blade-сервера, которая принимает в качестве аргумента $user->id :

 Blade::if('following', function (User $user) { return auth()->check() && auth()->user()->isFollowing($user->id) }); 

Затем использовать эту новую директиву в наших шаблонах:

 @following($user) <p>Following</p> @else <p>Not Following</p> @endfollowing 

Авторегистрация новых команд Artisan в ядре

Обычно мы запускаем команду php artisam make:command command-name для создания новых ремесленных команд. После этого мы объявляем нашу подпись внутри класса командой, затем переходим к ядру и вручную регистрируем команду.

Регистрация новых команд в Ядре больше не будет требованием. Внутри файла app/Console/kernel.php у нас есть новый метод, который просматривает каталог команд и превращает все пути к файлам в путь в пространстве имен:

 [...] protected function commands() { $this->load(__DIR__.'Commands'); require base_path('routes/console.php'); } [...] 

Предполагая, что мы ссылаемся на команду, которая еще не была зарегистрирована в ядре, метод commands() разрешит команду автоматически.

Новые методы маршрутизации

Не очень большая особенность, но теперь у нас есть два дополнительных метода маршрутизации:

 Route::view('/welcome', 'welcome'); Route::redirect('home', 'dashboard'); 

Первый маршрут отобразит welcome view на /welcome path а второй перенаправит все запросы, сделанные в /home на /dashboard .

Представляем Laravel Horizon

Это новый пакет Laravel, который предоставляет панель управления и систему конфигурации на основе кода для очередей Laravel Redis:

Панель инструментов Horizon

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

Некоторые из функций, которые идут с Horizon, включают:

  • Аналитика высокого уровня для рабочих мест — такие вещи, как количество рабочих мест в минуту и ​​количество рабочих мест за последний час
  • Аналитика работы и очереди
  • Теги и мониторинг — можно добавлять теги к заданиям, а также отслеживать определенные теги.
  • Последние вакансии — Мы можем получить информацию о самых последних вакансиях
  • Стратегии балансировки очереди — Horizon может автоматически балансировать рабочие процессы в очереди по вашим очередям в зависимости от загруженности этих очередей

Посмотрите пост Тейлора Отвелла, в котором подробно рассказывается, как настроить Horizon, и все функции, которыми обладает Horizon. У нас также будет специальный пост в Horizon, так что следите за обновлениями.

Новая черта миграции базы данных

Это черта RefreshDatabase . Кто-то может задаться вопросом, действительно ли нам это нужно, но шаг вперед в этом вопросе имеет смысл. Изначально у нас были черты DatabaseMigrations и DatabaseTransactions .

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

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

Вывод

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

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