Closed dbojdo closed 3 years ago
@jacekkow Trzeba jeszcze coś zmienić, czy jest ok?
Jeśli nie masz nic przeciwko, to zmieniłbym w wszędzie w polach DateTime na DateTimeImmutable (a w metodach przyjmujących parametr typu DateTime, zmieniłbym go na DateTimeInterface). Dodatkowo godzina i minuta byłaby ustawiana na zero. Wrzucę pull request wieczorem.
@jacekkow Nie zmieniać tego w tej wersji, bo to łamie kompatybilność wsteczną. Można pomyśleć o porządnej zmianie na PHP 7.1+ z silnym typowaniem / zwracanymi wartościami i wtedy możnaby zamienić wszystkie sygnatury na DateTimeInterface
, a wewnątrz używać DateTimeImmutable
. Ale to jest grubsza przeróbka na wersję 3.x
Pierwsza wersja ten biblioteki była pod PHP 5, stąd DateTime
, później zrobiłem wersję 2.0 pod PHP 7 (usunąłem rzeczy przestarzałe, pozwoliłem na nowsze wersji dependencji), ale nie miałem czasu na zmianę sygnatur, itd.
Dlaczego łamie?
Coś bardzo Cię uwiera ten DateTime
. Jak rozumiem pracujesz na \DateTimeImmutable
stąd chcesz zmiany na DateTimeInterface
? \DateTimeImmutable
w wersji PHP 7.3 ma fajną metodę \DateTime::createFromImmutable
, którą łatwo możesz użyć przed przekazaniem argumentów do API.
Zgadzam się, że ta zmiana może nie łamie BC sensu stricto, ale zmienia sygnatury metod (typy), co (moim zdaniem) nie powinno mieć miejsca w "minor" release. Taką refaktoryzację widziałbym w całym projekcie, nie tylko w Payments, dodatkowo ze wsparciem dla typów prostych w sygnaturach. Możemy zrobić nowy issue i popracować nad tym.
O wiele bardziej niż brak DateTimeInterface
boli mnie to, że za każdym pobraniem zmienia się czas, więc dwa DateTime
zwrócone z metody date()
będą równe (==
) lub nie w zależności od "czynników zewnętrznych" (m.in. tego kiedy zostały wykonane zapytania). Tak samo może niestety nie mieć sensu porównywanie dwóch obiektów Payment
(mimo że po stronie API zostanie zwrócony identyczny obiekt, to tutaj porównanie może nie zadziałać). Trochę szkoda, że PHP nie ma klasy na samą datę.
I tak, mogłoby mnie zaboleć gdyby przekazany DateTime
został przez klasę zmieniony - tutaj DateTimeImmutable
dawałoby gwarancję, że to się nie stanie.
Rozumiem problem. Niestety PHP nie daje dobrej metody na ogóle rozwiązanie tego problemu. Nawet jeśli chodzi o API, to używanie \DateTimeImmutable
rozwiąże tylko częściowo problem. Zobacz poniższy przykład:
$date = new \DateTimeImmutable();
$payment = new Payment(..., $date, ...);
$payment->date() == $date; // (jeżeli pomijamy ->setTime(0,0), to wszystko ok w tym miejscu
$createdPayment = $paymentsApi->add($payment);
$createdPayment->date() == $date; // tu już mamy problem, ponieważ zwrotka z API została zdeserializowana, a więc obiekt daty został utworzony ponownie z 1 - 2 sekundowym opóźnieniem (w zależności jak długo trwa komunikacja z API).
Niestety, PHP to nie Java i nie ma jak ogólnie zaimplementować metody .equlas
. Można taką metodę stworzyć, ale wtedy trzeba ją wywołał explicite (== nie tego łyknie). Może kiedyś doczekamy się jakiegoś ogólnego interfejsu Comparable
czy coś w tym stylu.
Można w jakiś sposób ograniczyć problem, przez tworzenie dat zawsze z zerowym czasem (w trakcie rdeserializacji), ale żeby porównanie działało, data "z zewnątrz", z którą porównujesz, również musiałaby być tak utworzona. Więc, tak czy inaczej, gwarancji na poprawne działanie porównania nie ma :(
Chyba, że czegoś nie zrozumiałem?
Wszystko "w punkt".
…tibility fixes.