Laravel 7.x – co nowego?
Zgodnie z kalendarzem, 3-go marca 2020 została wydana nowa wersja Laravel-a. Co nowego zaproponowali twórcy tego niezwykle popularnego frameworka PHP? Zapraszam do przeczytania tego artykułu.
Zmiany w Eloquent Casts
Tworząc modele Eloquent, mamy możliwość zdefiniowania rzutowania typu dla wybranych pól w bazie danych. Przykładowo, możemy określić, że wartość dla danego pola ma być typu boolean i dla tak zdefiniowanego pola po pobraniu lub zapisie jego wartości, nastąpi automatyczna konwersja na podany typ.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { protected $casts = [ 'is_admin' => 'boolean', ]; } |
Laravel posiada szereg wbudowanych modyfikatorów: integer, real, float, double, decimal:<digits>, string, boolean, object, array, collection, date, datetime, timestamp.
Nowa wersja frameworka umożliwia jednak definiowanie własnych klas, modyfikujących wskazane pola w odpowiedni sposób. Taka klasa implementuje interfejs CastAttributes i powinna definiować dwie metody: get i set – zostana one automatycznie wywołane podczas odczytu i zapisu wartości wskazanego pola w bazie danych.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php 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); } } |
Po utworzeniu takiej klasy wystarczy ją użyć na wybranym polu modelu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php 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, ]; } |
Dodano również możliwość ustawienia rzutowania typu pola bezpośrednio podczas definiowania zapytania do bazy danych.
1 2 3 4 5 6 7 |
$users = User::select([ 'users.*', 'last_posted_at' => Post::selectRaw('MAX(created_at)') ->whereColumn('user_id', 'users.id') ])->withCasts([ 'last_posted_at' => 'date' ])->get(); |
Klient HTTP
Wprowadzona została nowa biblioteka użyteczna przy komunikacji poprzez protokół HTTP. Nowy klient jest nakładką na bibliotekę Guzzle i pozwala wykonywać zapytania przy minimalnej konieczności ustawień i linijek kodu.
1 2 3 4 5 6 7 8 9 10 |
use Illuminate\Support\Facades\Http; $response = Http::withHeaders([ 'X-First' => 'foo', 'X-Second' => 'bar' ])->post('http://test.com/users', [ 'name' => 'Taylor', ]); return $response['id']; |
Ponadto została wprowadzona funkcjonalność ułatwiająca testy, korzystające z zapytań HTTP. Daje możliwość zdefiniowania zasobów, dla których po wykonaniu żądania zostanie zwrócona z góry przygotowana odpowiedź testowa.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Http::fake([ // Stub a JSON response for GitHub endpoints... 'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']), // Stub a string response for Google endpoints... 'google.com/*' => Http::response('Hello World', 200, ['Headers']), // Stub a series of responses for Facebook endpoints... 'facebook.com/*' => Http::sequence() ->push('Hello World', 200) ->push(['foo' => 'bar'], 200) ->pushStatus(404), ]); |
Ułatwienia w Route
Od teraz, definiując ścieżkę route, możemy podać nazwę pola w bazie danych, po którym zwracany będzie model (domyślnie jest to pole „id”). W poniższym przykładzie, model będzie wyszukiwany uwzględniając pole „slug”.
1 2 3 |
Route::get('api/posts/{post:slug}', function (App\Post $post) { return $post; }); |
Dodatkowo, jeżeli w ścieżce podamy dwa modele, to Eloquent domyślnie założy że drugi model jest w relacji do pierwszego i że jego „dzieckiem”. Innymi słowy przy odpytaniu bazy danych o drugi model, do zapytania zostanie dodany warunek przynależności do pierwszego modelu.
1 2 3 4 5 6 |
use App\Post; use App\User; Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) { return $post; }); |
Dla powyższego przykładu model „post” musi należeć do modelu „user”.
Konfiguracji kilku bibliotek mailingowych w jednej aplikacji
Laravel 7 umożliwia konfiguracje wielu „mailer-ów” w jednej aplikacji, a następnie ich użycie dla różnych funkcjonalności. Przykładowo możemy mieć skonfigurowany mailer SendGrid dla wiadomości reklamowych, a domyślny mailer dla wiadomości związanych z obsługa użytkowników (rejestracja, zmiana, hasła, itp.).
1 2 3 |
Mail::mailer('postmark') ->to($request->user()) ->send(new OrderShipped($order)); |
Za pomocą metody „mailer” możemy wskazać, z której konfiguracji chcemy skorzystać podczas wysyłki.
Konfiguracja maksymalnej liczby wyjątków dla kolejki
Dodana została możliwość konfiguracji liczby nieobsłużonych wyjątków, po osiągnięciu której zadanie dla zostanie uznane za niewykonane.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php namespace App\Jobs; class ProcessPodcast implements ShouldQueue { /** * The number of times the job may be attempted. * * @var int */ public $tries = 25; /** * The maximum number of exceptions to allow before failing. * * @var int */ public $maxExceptions = 3; /** * Execute the job. * * @return void */ public function handle() { Redis::throttle('key')->allow(10)->every(60)->then(function () { // Lock obtained, process the podcast... }, function () { // Unable to obtain lock... return $this->release(10); }); } } |
W powyższym przykładzie, status zadania zostanie zmienione na „failed”, jeżeli 3 razy zostanie wyrzucony wyjątek.
Pozostałe zmiany
- Laravel Sanctum – została wprowadzona biblioteka ułatwiająca implementacje procesu uwierzytelnienia użytkownika za pomocą API oraz wprowadzająca szereg użytecznych funkcjonalności.
- Dodatkowe funkcjonalności helper-a Str ułatwiającego manipulacje na stringach.
- Ulepszona funkcjonalność cache-owania route-ów, co może nieco przyśpieszyć działanie aplikacji. Tak naprawdę różnica może być w jakiś sposób zauważalna dla bardzo dużej ilości route-ów (np. powyżej 1000).
- Możliwość prostej konfiguracji polityki CORS (Cross-Origin Resource Sharing) dla zapytań z zewnętrznych aplikacji.
- Poprawiona obsługa kolejki dla bazy danych MySQL 8+.
- Dodanie komendy Artisan test, do testowania aplikacji.
- Odświeżony domyślny szablon dla wiadomości e-mail.
- Możliwość konfiguracji i zmiany szablonów tzw. stub dla polecenia make.
- Ulepszenia w komponentach dla systemu szablonów Blade.
Powyżej opisane zostały jedynie niektóre, najważniejsze zmiany i udogodnienia. Oczywiście jest ich znacznie więcej. Zachęcam do sprawdzenia zmian i nowych funkcjonalności frameworka Laravel w wersji 7.x.