Laravel 7 - Co nowego wprowadza kolejna wersja frameworka?
Wczoraj została oficjalnie wydana nowa wersja Laravela o numerze 7, przyjrzyjmy się więc modyfikacjom, jakie czekają na nas w tej aktualizacji. W związku z ostatnią zmianą numeracji (od wydania 6.0, czyli września poprzedniego roku, Laravel używa Semantic Versioning) od razu wiemy, że w nowej wersji są tzw. breaking changes, czyli aktualizacje, które powodują zmianę działania frameworka w sposób znaczący. Przyjrzymy się zatem tym zmianom, omówimy nowe funkcjonalności oraz sprawdzimy, czy warto przenieść się na najnowszą wersję.
Laravel Airlock
Laravel Airlock jest kolejną oficjalną paczką Laravela, stworzoną przez twórcę frameworka, Taylora Otwella. Stanowi ona alternatywę dla Laravel Passport, którą możemy wykorzystywać gdy potrzebujemy uwierzytelnić użytkowników API, ale nie potrzebujemy do tego wykorzystywać wszystkich funkcji OAuth2. Przykładem takich aplikacji są m.in. SPA (Single Page Application) czy aplikacje mobilne. Dotychczas, aby poradzić sobie z identyfikowaniem i autoryzowaniem użytkowników odpytujących naszą aplikację przez API zmuszeni byliśmy albo pisać własne rozwiązania, albo używać paczki Passport, która miała w sobie wszystkie funkcjonalności OAuth2, co często było zupełnie niepotrzebne i korzystaliśmy tylko z ułamka jej funkcji.
Programowalne rzutowanie atrybutów w Eloquencie
Nowość ta pozwala nam na zdefiniowanie własnych funkcji rzutujących atrybuty w Eloquentowym modelu. Do wersji 7 jedynymi możliwościami, jakie mieliśmy, były: rzutowanie na podstawowe typy PHP, kolekcje oraz obiekty Carbona. Obecnie możemy zdefiniować dowolną metodę rzutowania atrybutów, implementując interfejs CastsAttributes.
Przykładowa implementacja klasy:
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);
}
}
Oraz przykład jak jej używać:
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,
];
}
Komponenty Blade’a
Jeśli w trakcie swojej pracy oprócz Laravela używacie również Vue i (tak jak ja) kochacie w nim koncept komponentów, to bardzo spodoba wam się ten feature. Kompletnie przebudowany został system komponentów w Blade. Stara konstrukcja @component (co jest pierwszym breaking change’em w tej wersji), została zastąpiona kompletnie nową, przypominającą tą znaną z Vue. Komponenty są po prostu klasami, w których możemy implementować dowolne metody oraz decydować jakie widoki mają się wyświetlać.
Ten feature bardziej szczegółowo pokryjemy w przyszłych artykułach, natomiast na razie możecie zapoznać się, jak to wygląda w dokumentacji.
Fasada Http
Aby ułatwić pracę z zapytaniami do zewnętrznych serwisów w nowej wersji Laravela, pojawia się klasa Illuminate\Support\Facades\Http będąca prostym wrapperem dookoła paczki GuzzleHttp.
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-First' => 'foo'
'X-Second' => 'bar'
])->post('http://test.com/users', [
'name' => 'Taylor',
]);
return $response['id'];
Poza samym wywoływaniem zapytań fasada ta ułatwia również ich testowanie.
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),
]);
Łatwiejsze operacje na stringach
Aby uprościć korzystanie z helpera Str:: wprowadzona została klasa Stringable, dzięki której możemy w bardziej obiektowy sposób wykonywać operacje na stringach. Dzięki temu rozwiązaniu, zamiast używać tradycyjnego podejścia, przypisując wyniki funkcji do kolejnych zmiennych, możemy wywołać łańcuch funkcji, dzięki czemu nasz kod staje się bardziej czytelny.
return (string) Str::of(' Laravel Framework 6.x ')
->trim()
->replace('6.x', '7.x')
->slug();
Zmiany w routingu
W nowej wersji Laravela przepisane zostały części frameworka odpowiedzialne za routing. Dzięki temu uzyskaliśmy nowe możliwości oraz zwiększona została wydajność znajdowania routów. Jedną z głównych nowości jest możliwość definiowania nazwy kolumny, po której działa route model binding. Do tej pory, aby używać route bindingu po innym kluczu niż ID, musieliśmy zdefiniować dla całości danego modelu, przez co zawsze używana była dana kolumna. Po najnowszych zmianach będzie to możliwe per dany route, co zwiększa elastyczność rozwiązania.
Route::get('api/posts/{post:slug}', function (App\Post $post) {
return $post;
});
Kolejną nowością jest automatyczne wykrywanie relacji. Jeśli użyjemy dwóch modeli, w jednym route Laravel spróbuje wyszukać czy są one powiązane jakąś relacją oraz pozwoli odpytać tylko te modele, które są ze sobą powiązane.
Route::get('api/users/{user}/posts/{post:slug}', function (User $user, Post $post) {
return $post;
});
Przy okazji przepisywania części routingu poprawione również zostało cache’owanie, dzięki czemu w niektórych sytuacjach aplikacja może działać dwukrotnie szybciej.
Wsparcie CORS
Do tej pory API pisane w Laravelu wiązało się z problemami z Cross-Origin Resource Sharing. Jeśli nasze API znajdowało się na innej domenie niż aplikacja konsumująca je, to requesty nie były przyjmowane. Aby poradzić sobie z tym problemem należało użyć zewnętrznych paczek. Od teraz zapytania OPTIONS są obsługiwane z każdą nową instalacją Laravela.
Wsparcie MySQL 8
Po kilku latach w końcu doczekaliśmy się możliwości używania MySQL8 z Laravel. Największym plusem tego jest to, że znacząco poprawi to wydajność pracy z bazą danych. Obecna wersja jest znacząco szybsza przy operacjach zapisu do i odczytu z bazy względem wersji 5.7. Jeśli chcesz poznać więcej danych na temat wydajności obu baz danych, proponuję zapoznać się z tym artykułem. Osobiście podoba mi się usunięcie możliwości cachowania zapytań. Niestety mechanizm ten najczęściej powodował więcej problemów niż korzyści. Obecnie w Laravel mamy o wiele bardziej efektywne rozwiązania, które zastępują ten mechanizm już od dłuższego czasu.
Oczywiście wersja 8 niesie ze sobą mnóstwo ulepszeń i nowych mechanizmów. Jest znacznie lepszym rozwiązaniem do stosowanie w bardziej wymagających projektach. Najciekawszą propozycją z mojego punktu widzenia jest wprowadzenie wsparcia dla UUID oraz mechanizmu Common Table Expressions (CTE), który obecny jest w PostgreSQL i MariaDB. Z takimi zmianami baza MySQL jest jeszcze bardziej wydajna i umożliwia tworzenie w oparciu o nią jeszcze bardziej złożonych rozwiązań. Jeśli chcesz poznać więcej możliwości nowej wersji bazy, to odsyłam do tego artykułu.
Jeśli potrzebujesz doświadczonego software house'u pracującego w PHP