- Published on
DTO w Laravel – Strukturyzacja danych i typy w PHP
Dlaczego strukturyzacja danych ma znaczenie?
W świecie Laravela dane są wszędzie: formularze, API, bazy danych, pliki konfiguracyjne. W małych projektach możesz pozwolić sobie na swobodę – np. używać tablic z kluczami jak $data['user_name']
. Ale gdy aplikacja rośnie, chaos narasta:
- Nowy developer nie wie, jakie pola istnieją w tablicy
$validated
z żądania. - Zmiana typu pola (np. z
string
naint
) powoduje błędy w nieoczekiwanych miejscach. - Testy stają się koszmarem przez brak gwarancji struktury danych.
Strukturyzacja danych to fundament dla przewidywalności. Dzięki niej:
- Każdy fragment kodu wie, czego może się spodziewać.
- IDE podpowiada dostępne pola i typy.
- Zmniejszasz ryzyko błędów „na produkcji”.
System typów w PHP
PHP jest elastyczny i pozwala na wiele, ale czasem płacisz za to cenę.
- Słabe typowanie:
$value = "100"; // string
$value = $value + 5; // teraz to int (105)
Brak kontroli nad typami prowadzi do niespodzianek, np. gdy "abc"
zamienia się w 0
w obliczeniach.
- Dynamiczne typowanie: Błędy typów (np. przekazanie
string
zamiastint
) wykrywane są dopiero w runtime’ie. To oznacza, że aplikacja może crashować w nieprzewidzianych momentach.
Ratunek? Wykorzystaj statyczne analizatory jak PHPStan lub Psalm, które działają jak „czujniki typów” przed uruchomieniem kodu. Potrafią wykryć problemy z typami, podobnie jak proces kompilacji w językach silnie typowanych.
Wyzwanie nieustrukturyzowanych danych
Wyobraź sobie endpoint API, który przyjmuje dane użytkownika:
public function updateUser(Request $request) {
$data = $request->all();
User::find($data['id'])->update($data);
}
Problemy:
- Co jeśli
$data['id']
nie istnieje? - Czy
$data['birthday']
jest stringiem, czy obiektemCarbon
? - Gdy dodasz nowe pole
phone_number
, musisz przeszukać cały kod, aby znaleźć miejsca, gdzie jest używane.
Rozwiązanie? Zastąp tablice obiektami danych, które wymuszają strukturę i typy.
Obiekty danych (DTOs) – ratunek dla czytelności kodu
DTO (Data Transfer Object) to klasa, która:
- Definiuje konkretne pola (np.
name
,email
). - Wymusza określone typy (np.
string
,Carbon
). - Może zawierać logikę walidacji (np. sprawdzanie formatu emaila).
Przykład:
class UserProfileData {
public function __construct(
public string $name,
public string $email,
public Carbon $birthday,
public ?string $phone = null
) {}
}
Dlaczego to działa?
- Każdy, kto używa
UserProfileData
, wie, żebirthday
jest obiektemCarbon
. - IDE podpowie wszystkie dostępne pola.
- Błędy literówek (np.
emial
zamiastemail
) znikają.
Tworzenie obiektów danych w praktyce
Mapowanie żądania HTTP na DTO:
public function update(UserProfileRequest $request) {
$data = new UserProfileData(
name: $request->input('name'),
email: $request->input('email'),
birthday: Carbon::parse($request->input('birthday')),
phone: $request->input('phone')
);
// ... użyj $data
}
Wyzwanie: Ręczne parsowanie pól (np. Carbon::parse()
) jest uciążliwe. Rozwiązanie: Użyj metody fabrykującej w DTO:
class UserProfileData {
public static function fromRequest(UserProfileRequest $request): self {
return new self(
$request->input('name'),
$request->input('email'),
Carbon::parse($request->input('birthday')),
$request->input('phone')
);
}
}
Laravel Data – ułatwiaj sobie życie
Paczka spatie/laravel-data automatyzuje tworzenie DTOs w Laravelu.
Kluczowe funkcje:
- Automatyczna konwersja typów (np. string → Carbon).
- Integracja z walidacją Laravela:
use Spatie\LaravelData\Attributes\Validation\Email;
use Spatie\LaravelData\Data;
class UserData extends Data {
public function __construct(
public string $name,
#[Email]
public string $email
) {}
}
// W kontrolerze:
public function store(UserData $data) {
// $data jest już zwalidowane!
}
- Generowanie typowania TypeScript – idealne dla frontendu.
Bonus: DTOs mogą być używane jako zasoby API (API Resources), co utrzymuje spójność między backendem a frontendem.
Podsumowanie: Korzyści ze strukturyzacji danych
- Mniej błędów – typy są sprawdzane na etapie tworzenia DTO.
- Lepsza dokumentacja – struktura danych jest jawna w kodzie.
- Łatwiejsze testy – mockowanie danych staje się przewidywalne.
- Bezpieczeństwo – unikasz SQL injection przez przypadkowe przekazanie nieoczekiwanych pól.
Jak zacząć?
- W małych projektach: Zacznij od ręcznego tworzenia DTO dla kluczowych żądań.
- W dużych aplikacjach: Zintegruj Laravel Data, aby zautomatyzować proces.
Pamiętaj: DTOs to nie tylko „kolejna warstwa abstrakcji”. To inwestycja w długoterminowe zdrowie kodu – szczególnie, gdy pracujesz w zespole lub projekt ma żyć latami. 🛠️