Co nowego w PHP 8: Wszystko, co musisz wiedzieć!

Opublikowany: 2021-01-06

Skontaktujemy się z PHP8 26 listopada 2020 r. i na pewno jest wiele do napisania na temat nadchodzących funkcji w tym cenionym wydaniu.

PHP 8

Ponieważ jest to główna wersja, pojawią się przełomowe zmiany i nowe funkcje, a także ważne jest, aby być świadomym tego, co się zmienia. Ułatwi to zastanowienie się, w jaki sposób PHP8 wpłynie na twoje aplikacje i jakie działania należy podjąć, aby zapewnić wygodną aktualizację bez incydentów.

Przeszliśmy przez kilka najbardziej znaczących zmian, aby dowiedzieć się, co otrzymamy w następnym wydaniu PHP i co warto krytykować.

zacznijmy od przeglądu!

Przegląd PHP 8

Jak wspomniano powyżej, PHP 8 wprowadza do języka pakiet nowych funkcji, ulepszeń, funkcji i przestarzałych wersji. Wśród nich najczęściej omawianą funkcją jest kompilator JIT. Jednak funkcje poprawiające wydajność, takie jak JIT, zasługują na światło reflektorów, ale oczekuje się, że ulepszenia syntaktyczne będą bardziej prawdziwe dla praktyków PHP, powiedzielibyśmy „przynajmniej w krótkim okresie”.

Historia zmian

Kilka zmian PHP jest proponowanych, omawianych, wdrażanych i następnie zatwierdzanych w krótkim czasie. Są popularne, niekontrowersyjne i mają naturalną metodę ich realizacji.

A potem przychodzą ci, którzy są wypróbowywani, zawodzą i wracają wiele razy, zanim w końcu ich zaakceptujemy. Kilka razy wdrożenie zajmuje dużo czasu, aby uporządkować, a czasami sam pomysł jest po prostu niedopracowany, a czasami sama społeczność jeszcze się do niego nie rozgrzała – „jeszcze nie czas”.

Kredyty należą do kategorii typu. Zostały one po raz pierwszy zaproponowane w 2016 roku dla PHP 7.1. Jednak spotkali się z upartym oporem i przegrali głos na akceptację z dużym marginesem. Teraz, cztery lata do przodu, całkiem podobna propozycja, choć nieco zmniejszona, pojawiła się z tylko jednym dysydentem. To ewidentnie pomysł, którego czas na pewno nadszedł!

Jakie są problemy ze starym kodem?

Ponieważ PHP 8 jest ogromnym nowym wydaniem, powinniśmy oczekiwać, że stary kod nie będzie już kompatybilny. Jednak większość zmian, które mogły sugerować komplikacje, została przekazana już w wersjach 7.2 , 7.3 i 7.4 . Porozmawiajmy teraz o ostatnich zmianach. Są to:

Dziedzictwo magicznych cytatów

  • Prawdziwy typ
  • Filtr FILTER_SANITIZE_MAGIC_QUOTES
  • Rozpinanie $this od niestatycznych zamknięć
  • array_key_exists() z obiektami
  • mb_strrpos() z kodowaniem jako 3 argument
  • Metody eksportu odbić()
  • Funkcja convert_cyr_string()
  • implode() kolejność parametrów mix
  • funkcja restore_include_path()
  • funkcja hebrevc()
  • funkcja money_format()
  • dyrektywa allow_url_include ini
  • Funkcja ezmlm_hash()

Nowe funkcje w PHP 8

str_zawiera

Jeśli jeden ciąg zawiera inny, istnieje wiele sposobów, aby się tego dowiedzieć.

Generalnie będziesz używać strpos(). Jak wiesz, strpos() pobiera stog siana obok igły, której chcesz szukać. Zwraca liczbę całkowitą wskazującą pierwszą pozycję, w której widzisz igłę.

Teraz, gdy zwraca pozycję ciągu w innym, po prostu nie możesz sprawdzić, czy strpos() go wykrył; jeśli zwróci „0” (pozycje są indeksowane zerami i zaczynają się od 0, a nie od 1), to warunek potraktuje ją jako wartość fałszywą i wskazuje, że nie została znaleziona.

Co to znaczy?

Będziesz musiał napisać warunkowe –„strpos($stóg siana, $igła) !== false.” False oznacza, że ​​nie mógł znaleźć pozycji ciągu. Jest to nieprzejrzysta i ezoteryczna metoda wyszukiwania ciągu w ciągu! Cóż, nie takie mylące.

Aby tego uniknąć, PHP 8 wprowadza str_contains(). Zadaniem str_contains() jest zwrócenie prostej wartości logicznej pokazującej, czy igła jest obecna w stogu siana. O wiele łatwiej to napisać, poza tym rozumieć jako ktoś utrzymujący kod, prawda?

 if (str_contains( 'Foo Bar Baz' , 'Foo' )) { // FOUND }

PHP 8: Funkcje i zmiany silnika

Jest kilka nowych funkcji silnika i zmiany zauważone w PHP 8. Główną cechą jest niewątpliwie nowy kompilator JIT.

Kompilator JIT

  • Egzekwowanie LSP
  • Błędy krytyczne w niezgodnych podpisach metod
  • Zasób „Klasy”
  • XML-RPC jest teraz w PECL
  • Zachowanie asercyjne
  • Zmiany odbicia

Ze względu na główny cel tego bloga skupimy się na kompilatorze JIT, „klasach” zasobów i wreszcie na zmianach interfejsu API odbić.

Kompilator Just-In-Time ( RFC )

Ze względu na ulepszenia szybkości wprowadzone przed wydaniem PHP7, narodził się kompilator Just-In-Time (lub JIT). Jest wprowadzany do PHP8, ponieważ nie ma prawie żadnych ulepszeń szybkości, które można wprowadzić bez użycia JIT. Chodzi o to, że poprawi to wydajność PHP.

Kod PHP jest tłumaczony na kody bajtowe, gdy jest wykonywany, a te kody bajtowe są dalej wykorzystywane do wykonywania kroków w programie.

PHP przeanalizuje kod, który wykonałeś, to właśnie oznacza JIT. Co więcej, może podejmować decyzje w czasie rzeczywistym inne niż poprawa wydajności kodu podczas jego wykonywania. Będzie wysoce użyteczny w aplikacjach intensywnie korzystających z procesora, a nie tylko w scenariuszach internetowych.

Odzwierciedla to, że aplikacje PHP po stronie serwera z pewnością mogą być bardziej rozpowszechnione dzięki wbudowanemu w PHP systemowi JIT.

Najpierw musisz aktywować JIT, jeśli chcesz z niego korzystać. W naszym systemie testowym (Ubuntu 20.04) zainstalowaliśmy już moduł PHP opcache, który zainstalowaliśmy z pakietem core PHP8. Skonfigurowaliśmy w pliku umieszczonym w /etc/php/8.0/cli/conf.d/10-opcache.ini.

Teraz wszystko gotowe do aktywacji JIT, prawda?  

  • Włącz opcache

Możesz przypisać pamięć do ustawienia opcache.jit_buffer_size . Twój plik będzie wyglądał tak w moim systemie.

  1. zend_extension=opcache.so
  2. opcache.enable_cli=1
  3. ; konfiguracja modułu php opcache
  4. opcache.jit_buffer_size=256M

Ponadto użyj funkcji opcache_get_status(), aby upewnić się, że jest aktywna. Rzuć wzrokiem na część „jit” tej tablicy i uzyskaj informacje dotyczące aktualnego stanu JIT.


var_dump(opcache_get_status()['jit']);

Jeśli JIT został doskonale aktywowany, powinien zostać wydrukowany, jak pokazano na dole.

  1. tablica(7) {
  2. [„włączone”]=>
  3. logiczne (prawda)
  4. [„wł.”]=>
  5. logiczne (prawda)
  6. [„dobry”]=>
  7. wewn(5)
  8. [„poziom_opcji”]=>
  9. wewn(4)
  10. [“opt_flagi”]=>
  11. wewn(6)
  12. ["rozmiar_bufora"]=>
  13. wewn.(268435440)
  14. [„Bez_bufora”]=>
  15. wewn.(268432880)
  16. }

Więc czy było szybciej? Jednym słowem wykrzykowaliśmy ciepłe „tak”.

Zauważyliśmy, że kilka osób robi testy porównawcze za pomocą zestawu mandelbrota, więc zdecydowaliśmy się użyć biblioteki, którą stworzyliśmy jakiś czas temu, która rysuje różne rodzaje fraktali w PHP. Wszystko, co zrobiliśmy, to wygenerowanie trzech fraktali i prześledzenie, jak długo to trwało, korzystając z funkcji microtome(). Poniżej pokazaliśmy wyniki dla PHP 7.4.8.

  • Płonący statek – 84.20269203186
  • Mandlebrot – 21.552599906921
  • Trójrożec – 32.685042858124

Kiedy uruchomiliśmy ten sam kod na PHP8, było to całkiem szybsze. Liczby będą mówić same za siebie. .

  • Płonący statek – 15.272277116776
  • Mandlebrot -3,7528541088104
  • Trójrożec -4.4957919120789

Ten ogromny wzrost prędkości jest całkiem interesujący. Kod, którego tu użyliśmy, tworzy fraktale ogromnych rozmiarów, ale pamiętamy, tworząc kod, że większość czasu spędziliśmy czekając na wygenerowanie fraktali.

Ten dodatek jest dla nas interesujący, ponieważ czasami przesuwaliśmy PHP do granic możliwości (poza generowaniem fraktali). Możemy zauważyć, że jest to bardzo korzystne dla przyszłości PHP i pozwoli na wybór języka w sytuacjach poza zwykłym językiem witryny.

Nie przyglądaliśmy się przyrostowi prędkości dla aplikacji takich jak WordPress czy Drupal, ale z tego, co przeczytaliśmy, z pewnością nie ma dużej różnicy w tego typu aplikacjach. W przyszłości będziemy przeprowadzać testy porównawcze na tych platformach, aby dowiedzieć się, jaką różnicę oznacza tam JIT.

Typy Unii ( RFC )

Od PHP7 określanie, jakie wartości zwracane i typy argumentów są możliwe. Pozwoli to PHP na zgłoszenie błędu w przypadku, gdy typ argumentu, który przekazujesz, jest sortowaniem nieidentycznym do oczekiwanego typu. Istotne jest, aby funkcje otrzymywały i produkowały doskonałe typy wartości w luźno typowanym języku, takim jak PHP.

W PHP8 można teraz określić różne rodzaje argumentów i wartości zwracanych, podzielone przez znak potoku.

Poniżej pokazaliśmy funkcję, która jest zdolna do przyjmowania wartości zmiennoprzecinkowych lub całkowitych.

 function addNumbers(int|float $number1, int|float $number2) : int|float { return $number1 + $number2; }

Poprzednio funkcja identyczna jak ta wymagałaby wygenerowania bez podpowiedzi o typie, ponieważ PHP mogło po cichu pokazać typ w przypadku, gdy przekazany argument nie był poprawny. Oznaczało to, że w przypadku, gdy ustawimy typ argumentu jako liczbę całkowitą, PHP pokaże dowolne wartości zmiennoprzecinkowe jako liczbę całkowitą. Z pewnością może to prowadzić do kilku trudnych błędów do wyłapania, jeśli nie przeprowadzasz testów jednostkowych.

Po prostu nazywamy to jak każdy inny, aby użyć powyższej funkcji

 echo addNumbers(1, 1); // prints 2 echo addNumbers(1.1, 1.1); // prints 2.2

W przypadku, gdy próbujemy przekazać ciąg do identycznej funkcji:

 echo addNumbers('one', 'two');

Otrzymamy błąd krytyczny PHP z informacją, że musimy przekazać do funkcji liczbę zmiennoprzecinkową lub „int”.

Nie możesz użyć typu void jako typu unii, ponieważ przewiduje on, że funkcja nie zwróci nic. W prostych słowach nie można wykrzyknąć, że funkcja zwróci pustkę lub liczbę całkowitą; otrzymasz błąd krytyczny PHP.

Chociaż normalną zmianą, którą widzimy, było użycie tej funkcji, ponieważ wcześniej było możliwe tylko określanie różnych typów wartości w komentarzach, co spowodowało, że komentarze bloków dokumentów stały się bardziej szczegółowe niż kod.

Operator Nullsafe (RFC)

Oprócz operatora koalescencji zerowej, możliwość wykrywania wartości zwracanych zerowych jest możliwa bezpośrednio z metod. Jeśli nie byłeś świadomy, operator łączenia wartości null pozwala uzyskać wartość i nie musisz testować, czy wartość jest obecna, oprócz zwracania innej wartości w przypadku, gdy pierwsza wartość jest null.

Możemy więc to zrobić, aby pobrać wartość z „$_GET superglobal”. a jeśli ta wartość nie jest obecna, to „0”.


1. $page = $_GET['page'] ?? 0;

2. echo $strona;

Działanie operatora bezpiecznego dla wartości null jest takie samo, ale umożliwia utworzenie poręcznego skrótu i ​​przetestowanie zwrotu zerowego z drogi przed próbą użycia tej wartości.

Zauważyliśmy, że będzie to ostatecznie przydatne w Drupalu, gdzie zwykle piszemy dużo sprawdzania kodu, aby upewnić się, że „zwroty z metod” lub „właściwości obiektu” mają w sobie coś przed ich użyciem. Jest to obowiązkowe ze względu na kontekstowy stan obiektów w Drupalu ze względu na zawartość, jaką zawierają. Ta zmiana z pewnością uprości niektóre kontrole.

Nazwane argumenty ( RFC )

Nazwane argumenty pozwalają określić inną kolejność argumentów i wywołać funkcje. Weź następującą normalną funkcję, która ma dwa parametry. Wypełnia tablicę do podanej długości.

 function fillArray(array $arrayToFill, int $number) : array { for ($i = 0 $i < $number; ++$i) { $arrayToFill[$i] =1; } return $arrayToFill; }

Możemy przekazać argumenty w układzie, w jakim są one zdefiniowane, mogą nazywać tę technikę w normalny sposób.

 $newArray = fillArray([], 2);

Od PHP8 możesz teraz nazwać parametry podczas przekazywania ich do funkcji. Pozwala również na przesłanie parametrów w dowolnej kolejności.

 $newArray = fillArray(number: 2, arrayToFill: []);

Normalny przykład, ale może również sprawić, że kod będzie bardziej czytelny.

Ta technika działa ze wszystkimi funkcjami w PHP, nie tylko tymi zdefiniowanymi przez użytkownika. W języku PHP funkcje tablic i łańcuchów mają nieidentyczne porządki parametrów. Jest to więc naprawdę mile widziany dodatek.

Atrybuty V2 ( RFC1 RFC2 RFC3 )

Atrybuty dostarczają mechanizmu do dołączania metadanych do klas PHP, funkcji, właściwości klas, parametrów funkcji i stałych. Nie mogą być bezpośrednio dostępne przez kod i musisz je wyciągnąć za pomocą wbudowanych klas odbicia PHP.

Klasa ReflectionClass jest obecna w PHP od PHP5; jednak metoda getAttribute() jest nowością w PHP8. Ta metoda zwraca zakres obiektów ReflectionAttribute, które będą zawierać informacje o atrybutach.

Ten dodatek został poddany kilku zmianom (jak możemy zauważyć z wielu powyższych specyfikacji RFC). Jeśli tworzysz instancję klasy, możesz użyć ReflectionClass i wydrukować informacje o atrybucie zawarte na poziomie klasy. W PHP8 jest dużo atrybutów, więc zalecamy przeczytanie specyfikacji RFC i zapoznanie się z tym, czym one naprawdę są i jak można je zintegrować z kodem.

Wyrażenie dopasowania ( RFC )

W PHP 8 możemy porównać nowe wyrażenie match do skróconej instrukcji switch.

Wygląda to trochę jak deklaracja funkcji, która zwróci wartość na podstawie przekazanej wartości.

Instrukcja switch w PHP jest niesamowita, gdy chcesz sprawdzić warunek na identycznym wyrażeniu bez dołączania wielu instrukcji if .

Tutaj wprowadzamy podstawowe porównanie if-else na identycznym wyrażeniu.

 <?php if ($i == 'apple') { echo 'i is apple'; } elseif ($i == 'cake') { echo 'i is cake'; } else { echo 'i is pizza'; }

I tak wyglądałaby równoważna instrukcja switch z naszego poprzedniego przykładu

 <?php switch ($i) { case 'apple': echo 'i is apple'; break; case 'cake': echo 'i is cake'; break; default: echo 'i is pizza'; }

Zasób „Klasy”

„Klasy” zasobów znajdują się na liście głównych zmian w PHP 8 i służą jako nieinstancyjne zamienniki dla danych typów zasobów. Zobacz poniżej, aby poznać dostępne zamienniki:

  • CurlHandle — curl_init() teraz zwraca CurlHandle, odnoszący się do zasobu curl.
  • Socket / AddressInfo — Podane przez rozszerzenie sockets; liczba funkcji socket_*() zwraca Socket, a funkcja socket_address_info_lookup() zwraca instancję AddressInfo.
  • GdImage — Reprezentuje zasób GD, przywrócony przez liczne funkcje imagecreatefrom*().

Należy również pamiętać, że zasoby nie są niszczone przez funkcje takie jak curl_close(). Zamiast tego musisz wyłączyć () instancję, aby usunąć odwołanie, ponieważ jest to teraz instancja klasy.
Uzyskujesz możliwość określania klas jako wskazówek w swoich funkcjach i metodach.
Wcześniej musieliśmy zwracać wartości bez typu lub zostawiać argumenty zasobów i dokumentować je za pomocą adnotacji, ale teraz możesz mieć typy jawne, a to nie tylko czyni kod bardziej czytelnym, ale także bardziej bezpiecznym dla typów.
Jaki jest tutaj kompromis?
Musisz teraz zaktualizować swój kod, jeśli chcesz niszczyć zasoby za pomocą unset() zamiast poprzednich funkcji używanych do niszczenia zasobów. Zwykle można to osiągnąć poprzez wyszukiwanie i zastępowanie.

Zmiany w interfejsie API refleksji

Kolejna mała, ale istotna zmiana w PHP 8 jest związana z Reflection API. Korzystając z systemu atrybutów, możesz wygodnie pobrać te atrybuty za pomocą interfejsu API odbicia w dowolnych klasach odbicia.
Po dodaniu typów mieszanych i typu union techniki ReflectionParameter getClass(), isCallable() i isArray() są teraz przestarzałe.
Scenariusz jest taki, ponieważ użycie getType() jest znacznie lepsze i otrzymujesz pełną listę typów, które spełnia określony parametr.

Ulepszenia składni PHP 8

Jak zauważamy, JIT kradnie nagłówki; Ulepszenia składni PHP 8 zapewniają ogromną poprawę jakości życia programistom PHP.
Bez względu na to, czy chodzi o eliminację wspólnego szablonu z promowanych argumentów konstruktora, czy ulepszoną obsługę wyjątków i błędów, deweloperzy mogą się ekscytować.

  • pseudotyp „mieszany”
  • Typy Unii
  • Promocja własności Class Constructor
  • Zgłaszanie wyjątków od wyrażeń
  • Atrybuty
  • ::wszechobecność klas
  • Złap tylko według typu
  • Dopasuj wyrażenia

Na potrzeby tego bloga skupiamy się na typach związków, atrybutach i wyrażeniach dopasowania.

Typy Unii

Typy Unii pokazują, że wartość jest jedną z dwóch lub więcej określonych rodzajów. Odbywa się to za pomocą pionowego paska umieszczonego pomiędzy każdym dozwolonym typem. Dla kilku programistów, którzy zagłębiają się w adnotacje PHP, aby zwracać wartości lub określać parametry, najprawdopodobniej już to robiłeś.
Typy Unii mogą przynieść dużo złożoności i trudności w zrozumieniu dla tych, którzy akceptują wiele różnych typów lub zwracają wiele różnych typów.
Mimo to przy kilku okazjach będzie to bardzo przydatne. Na przykład w przypadku, gdy możesz zaakceptować obiekt implementujący nowy interfejs Stringable („ciąg|Stringable”) lub ciąg, lub jeśli możesz zaakceptować obiekt implementujący interfejs Traversable („array|Traversable”) lub tablicę .

Dopasuj wyrażenia

Wyrażenia dopasowania odcinają zgadywanie związane z ustaleniem, czy niepowodzenie przerwania w danym przypadku przełącznika jest zamierzone, czy nie. Upraszcza również normalny wzorzec przypisywania wartości na podstawie dopasowania.
W przypadku użycia wartość, którą przekazujemy do match(), będzie bezpośrednio porównywana z tym, co znajduje się w wyrażeniu po lewej stronie. Bez względu na to, czy jest to wyrażenie, czy wartość, wartość przekazana do funkcji match() powinna ją dopasować, aby została wybrana.
Po dopasowaniu wyrażenie znajdujące się po prawej stronie jest szacowane i zwracana jest jego wartość, podczas gdy wyrażenia mogą być tylko funkcjami Lambda lub funkcjami callables i nie są dozwolone domknięcia wielowierszowe.

Atrybuty

PHP 8 integruje również atrybuty na poziomie języka. Chociaż atrybuty są obecne przez ponad 15 lat za pośrednictwem adnotacji docblock, wbudowanie ich w język zapewnia lepszą wydajność i na pewno większą moc i większą spójność. Prawdopodobnie zobaczymy, że atrybuty są często używane w rozwoju narzędzi i szybkich aplikacji.

Wniosek

Oczywiście w PHP8 zaszły pewne zmiany. Wygląda jednak na to, że większość przestarzałego kodu, który jest eliminowany, dotyczy starszych funkcji, których ostatnio nie używaliśmy.
Jesteśmy bardzo zainteresowani zauważeniem, jaki wpływ będzie miał silnik JIT na używane przez nas bazy kodu, a także na szerszą społeczność PHP—mówiąc, że zdecydowanie zalecamy przeskanowanie bazy kodu pod kątem niezgodności z PHP8 i przeprowadzenie testów jednostkowych, aby upewnić się, że PHP aplikacje działają doskonale przed powiedzeniem „tak” aktualizacji.