Wprowadzenie do PHP 7: co nowego i co zniknęło
Opublikowany: 2022-03-11Jednym z najbardziej ekscytujących wydarzeń w 2015 roku w świecie PHP było wydanie PHP 7, 10 lat po wydaniu ostatniej głównej wersji, PHP 5. Jako duży krok naprzód, PHP 7 wprowadza wiele nowych funkcji i ulepszeń wydajności .
Usuwa jednak również stare, przestarzałe funkcje, które wprowadzają pewne przerwy w kompatybilności, co utrudnia migrację starszych aplikacji do nowej wersji. Ten przewodnik powinien służyć jako krótki przewodnik po tym, czego możesz się spodziewać, jeśli planujesz przenieść istniejące aplikacje lub zbudować nowe, na PHP 7.
Ale czekaj, gdzie się podział PHP 6?
Jeśli ostatnio nie pracowałeś z PHP, możesz się zastanawiać, co się stało z PHP 6, dlaczego przeskoczyłeś z PHP 5 do PHP 7? Krótko mówiąc, PHP 6 było porażką. Główną cechą wersji 6 była natywna obsługa znaków Unicode, ponieważ PHP jest używane głównie w tworzeniu stron internetowych, a sieć potrzebuje Unicode, więc przeniesienie Unicode do PHP miało sens.
Pomysł polegał na wprowadzeniu pełnej obsługi Unicode do samego rdzenia. Przyniosłoby to rozszerzone możliwości językowi, od możliwości używania głupich emotikonów jako nazw zmiennych i funkcji, po potężną międzynarodową funkcjonalność ciągów. Na przykład, gdy inny język używa wielkich i małych liter inaczej niż w języku angielskim lub gdy imię i nazwisko w chińskich znakach musi zostać przekonwertowane na angielski.
Niestety ten ambitny plan okazał się większym problemem, niż przewidywano. Duża część kodu musiała zostać przeniesiona, aby wspierać Unicode zarówno dla podstawowych, jak i ważnych rozszerzeń, co okazało się nużące i trudne. Spowolniło to rozwój innych funkcji języka, frustrując wielu programistów PHP. Pojawiły się dodatkowe przeszkody, które spowodowały mniejsze zainteresowanie rozwojem natywnej obsługi Unicode, co ostatecznie doprowadziło do porzucenia projektu.
Ponieważ zasoby, takie jak książki i artykuły, zostały napisane dla PHP 6 i jego obsługi Unicode, nowa wersja zostanie przemianowana na PHP 7, aby uniknąć nieporozumień.
W każdym razie, dość rozpamiętywania smutnej przeszłości, zobaczmy, co PHP 7 wnosi na imprezę.
Bitwa wydajnościowa, PHP 7 kontra PHP 5
W przypadku praktycznie wszystkich aktualizacji należy spodziewać się niewielkich ulepszeń wydajności. Jednak tym razem PHP przynosi znaczną poprawę w stosunku do wcześniejszych wersji, czyniąc samą wydajność jedną z najbardziej atrakcyjnych funkcji PHP 7. Jest to część projektu „PHPNG”, który zajmuje się wewnętrznymi częściami samego silnika Zend.
Dzięki refaktoryzacji wewnętrznych struktur danych i dodaniu kroku pośredniego do kompilacji kodu w postaci abstrakcyjnego drzewa składni (AST) uzyskuje się lepszą wydajność i efektywniejszą alokację pamięci. Same liczby wyglądają bardzo obiecująco; testy porównawcze wykonane w rzeczywistych aplikacjach pokazują, że PHP 7 jest średnio dwa razy szybsze niż PHP 5.6 i powoduje o 50% mniejsze zużycie pamięci podczas żądań, co czyni PHP 7 silnym rywalem dla kompilatora Facebooka HHVM JIT. Spójrz na tę infografikę firmy Zend przedstawiającą wydajność niektórych popularnych CMS i frameworków.
Zmniejszenie zużycia pamięci umożliwia również mniejszym maszynom lepszą obsługę żądań wraz z możliwością budowania mikrousług wokół PHP. Zmiany wewnętrzne, w szczególności wdrożenie AST, otwierają również możliwości przyszłych optymalizacji, które mogą jeszcze bardziej zwiększyć wydajność. W przyszłych wersjach rozważana jest nowa, wewnętrzna implementacja kompilatora JIT.
PHP 7 Cukier syntaktyczny
PHP 7 zawiera nowe funkcje składni. Chociaż nie rozszerzają możliwości samego języka, zapewniają lepszy lub łatwiejszy sposób na uczynienie kodu przyjemniejszym do pisania i przyjemnym dla oka.
Grupowe deklaracje importowe
Teraz możemy zgrupować deklaracje importu dla klas pochodzących z tej samej przestrzeni nazw w pojedynczy wiersz use
. Powinno to pomóc w uporządkowaniu deklaracji w sensowny sposób lub po prostu zapisać kilka bajtów w twoich plikach.
use Framework\Module\Foo; use Framework\Module\Bar; use Framework\Module\Baz;
W PHP 7 możemy użyć:
use Framework\Module\{Foo, Bar, Baz};
Lub, jeśli wolisz styl wielowierszowy:
use Framework\Module{ Foo, Bar, Baz };
Operator zerowego łączenia
Rozwiązuje to powszechny problem w programowaniu PHP, gdzie chcemy przypisać wartość do zmiennej z innej zmiennej, jeśli ta ostatnia jest rzeczywiście ustawiona, lub w inny sposób podać jej inną wartość. Jest powszechnie używany, gdy pracujemy z danymi wejściowymi dostarczonymi przez użytkownika.
Przed PHP 7:
if (isset($foo)) { $bar = $foo; } else { $bar = 'default'; // we would give $bar the value 'default' if $foo is NULL }
Po PHP 7:
$bar = $foo ?? 'default';
Można to również powiązać z wieloma zmiennymi:
$bar = $foo ?? $baz ?? 'default';
Operator statku kosmicznego
Operator statku kosmicznego <=>
pozwala na trójstronne porównanie dwóch wartości, nie tylko wskazując, czy są one równe, ale także, która z nich jest większa, w przypadku nierówności, zwracając 1,0 lub -1.
Tutaj możemy podjąć różne działania w zależności od tego, jak różnią się wartości:
switch ($bar <=> $foo) { case 0: echo '$bar and $foo are equal'; case -1: echo '$foo is bigger'; case 1: echo '$bar is bigger'; }
Porównywane wartości mogą być liczbami całkowitymi, pływakami, łańcuchami, a nawet tablicami. Sprawdź dokumentację, aby dowiedzieć się, jak różne wartości są ze sobą porównywane. [https://wiki.php.net/rfc/combined-comparison-operator]
Nowe funkcje w PHP 7
Ale oczywiście PHP 7 oferuje również nowe i ekscytujące funkcje.
Skalarne typy parametrów i wskazówki dotyczące typów zwrotów
PHP 7 rozszerza poprzednie deklaracje typów parametrów w metodach (klasy, interfejsy i tablice) poprzez dodanie czterech typów skalarnych; Integers ( int
), floats ( float
), wartości logiczne ( bool
) i strings ( string
) jako możliwe typy parametrów.
Ponadto możemy opcjonalnie określić, jaki typ zwracają metody i funkcje. Obsługiwane typy to bool , int , float , string , array , callable , nazwa klasy lub interfejsu , self i parent ( dla metod klasy )
class Calculator { // We declare that the parameters provided are of type integer public function addTwoInts(int $x, int $y): int { return $x + $y; // We also explicitly say that this method will return an integer } }
Deklaracje typu umożliwiają budowanie bardziej niezawodnych aplikacji i unikanie przekazywania i zwracania błędnych wartości z funkcji. Inne korzyści obejmują statyczne analizatory kodu i IDE, które zapewniają lepszy wgląd w bazę kodu, jeśli brakuje bloków DocBlock.
Ponieważ PHP jest słabo typizowanym językiem, pewne wartości parametrów i typów zwracanych będą rzutowane na podstawie kontekstu. Jeśli przekażemy wartość „3” w funkcji, która ma zadeklarowany parametr typu int
, interpreter zaakceptuje ją jako liczbę całkowitą i nie wyrzuci żadnych błędów. Jeśli nie chcesz tego, możesz włączyć strict mode
dodając dyrektywę declare
.
declare(strict_types=1);
Jest to ustawiane na podstawie pliku, ponieważ opcja globalna podzieliłaby repozytoria kodu na te, które są zbudowane z globalną ścisłością i te, które nie są, co skutkuje nieoczekiwanym zachowaniem, gdy połączymy kod z obu.
Wyjątki dotyczące silnika
Dzięki dodaniu wyjątków silnika, krytyczne błędy, które mogłyby spowodować zakończenie skryptu, mogą być łatwo wychwycone i obsłużone.
Błędy, takie jak wywołanie nieistniejącej metody, nie powodują zakończenia skryptu, zamiast tego generują wyjątek, który może być obsługiwany przez blok try catch, co poprawia obsługę błędów w aplikacjach. Jest to ważne w przypadku niektórych typów aplikacji, serwerów i demonów, ponieważ w przeciwnym razie krytyczne błędy wymagałyby ponownego uruchomienia. Testy w PHPUnit powinny również stać się bardziej użyteczne, ponieważ błędy krytyczne usuwają cały zestaw testów. Wyjątki, a nie błędy, będą obsługiwane na podstawie każdego przypadku testowego.
PHP 7 dodaje kilka nowych klas wyjątków w oparciu o typ błędów, które mogą się pojawić. Aby zachować zgodność między wersjami, dodano nowy interfejs Throwable
, który można zaimplementować zarówno z wyjątków silnika, jak i wyjątków użytkownika. Było to konieczne, aby uniknąć wyjątków silnika w celu rozszerzenia podstawowej klasy wyjątków, co skutkowało starszymi wyjątkami przechwytującymi kod, których wcześniej nie było.
Przed PHP 7 spowodowałoby to zakończenie skryptu z błędem krytycznym:
try { thisFunctionDoesNotEvenExist(); } catch (\EngineException $e) { // Clean things up and log error echo $e->getMessage(); }
Zajęcia anonimowe
Klasy anonimowe są kuzynami funkcji anonimowych, których można użyć w prostej, krótkoterminowej instancji. Klasy anonimowe można łatwo tworzyć i używać tak jak zwykłych obiektów. Oto przykład z dokumentów.
Przed PHP 7
class MyLogger { public function log($msg) { print_r($msg . "\n"); } } $pusher->setLogger( new MyLogger() );
Z anonimową klasą:
$pusher->setLogger(new class { public function log($msg) { print_r($msg . "\n"); } });
Klasy anonimowe są przydatne w testach jednostkowych, szczególnie w podszywaniu obiektów i usług testowych. Pomaga nam to uniknąć ciężkiego fałszowania bibliotek i frameworków, tworząc prosty obiekt, który zapewnia interfejs, który chcemy zakpić.
Funkcje CSPRNG
Dodano dwie nowe funkcje do generowania kryptograficznie bezpiecznych łańcuchów i liczb całkowitych.

random_bytes(int $len);
Zwraca losowy ciąg znaków o długości $len
.
random_int(int $min, int $max);
Zwraca liczbę z przedziału od $min
do $max
.
Składnia ucieczki punktu kodowego Unicode
W przeciwieństwie do wielu innych języków, przed PHP 7, PHP nie miało możliwości ucieczki od punktu kodowego Unicode w literałach łańcuchowych, . Ta funkcja dodaje sekwencję ucieczki \u
, aby utworzyć takie znaki przy użyciu ich punktu kodowego UTF-8. Jest to lepsze niż bezpośrednie wstawianie znaków, co pozwala na lepszą obsługę niewidocznych znaków, a także znaków, które mają tę samą reprezentację graficzną, ale różnią się znaczeniem.
echo "\u{1F602}"; // outputs ‚
Zauważ, że to przerywa istniejący kod z sekwencją \u
, ponieważ zmienia zachowanie.
Generatory zostaną zmodernizowane
Generatory w PHP mają też kilka fajnych funkcji dodatkowych. Teraz generatory mają instrukcję return, której można użyć, aby umożliwić wyprowadzenie wartości końcowej po iteracji. Może to służyć do sprawdzania, czy generator został wykonany bez błędów i pozwala kodowi, który wywołał generator, odpowiednio obsłużyć różne scenariusze.
Ponadto generatory mogą zwracać i zwracać wyrażenia z innych generatorów. Pozwala im to podzielić złożone operacje na prostsze i modułowe jednostki.
function genA() { yield 2; yield 3; yield 4; } function genB() { yield 1; yield from genA(); // 'genA' gets called here and iterated over yield 5; return 'success'; // This is a final result we can check later } foreach (genB() as $val) { echo "\n $val"; // This will output values 1 to 5 in order } $genB()->getReturn(); // This should return 'success' when there are no errors.
Oczekiwania
Oczekiwania są ulepszeniem funkcji assert()
przy zachowaniu kompatybilności wstecznej. Pozwalają na bezkosztowe potwierdzenia w kodzie produkcyjnym i zapewniają możliwość zgłaszania niestandardowych wyjątków, gdy potwierdzenie nie powiedzie się, co może być przydatne podczas programowania.
assert()
staje się konstrukcją językową w PHP 7. Asercje powinny być używane do celów debugowania tylko w środowiskach programistycznych i testowych. Aby skonfigurować jego zachowanie, mamy dwie nowe dyrektywy.
-
zend.assertions
-
1
: wygeneruj i wykonaj kod (tryb programistyczny) (wartość domyślna) -
0
: generuje kod, ale przeskakuje go w czasie wykonywania -
-1
: nie generuje kodu, dzięki czemu jest zerowy (tryb produkcyjny)
-
-
assert.exception
-
1
: wyrzuć, gdy asercja nie powiedzie się, albo przez zgłoszenie obiektu dostarczonego jako wyjątek, albo przez zgłoszenie nowego obiektu AssertionError , jeśli nie podano wyjątku -
0
: użyj lub wygeneruj Throwable , jak opisano powyżej, ale generuj ostrzeżenie tylko na podstawie tego obiektu, zamiast go wyrzucać (kompatybilne z zachowaniem PHP 5)
-
Przygotowanie do przejścia z PHP 5 na PHP 7
Wprowadzenie głównego wydania daje możliwość zmiany/aktualizacji starszych funkcjonalności, a nawet ich usunięcia, jeśli zostaną uznane za zbyt stare lub od jakiegoś czasu są przestarzałe. Takie zmiany mogą powodować przerwy w kompatybilności w starszych aplikacjach.
Inną kwestią, która wynika z takich skoków wersji, jest to, że ważne biblioteki i frameworki, na których polegasz, mogły nie zostać jeszcze zaktualizowane, aby obsługiwały najnowszą wersję. Zespół PHP starał się, aby nowe zmiany były jak najbardziej kompatybilne wstecz i aby migracja do nowej wersji była jak najbardziej bezbolesna. Nowszym i bardziej aktualnym aplikacjom powinno być łatwiej przejść na nową wersję, podczas gdy starsze aplikacje mogą być zmuszone zdecydować, czy korzyści przewyższają koszty, być może zrezygnując z aktualizacji.
Większość przerw jest niewielka i można je łatwo złagodzić, podczas gdy inne mogą wymagać więcej wysiłku i czasu. Zasadniczo, jeśli przed instalacją PHP 7 miałeś w swojej aplikacji ostrzeżenia o deprecjacji, prawdopodobnie otrzymasz błędy, które spowodują uszkodzenie aplikacji do czasu jej naprawienia. Zostałeś ostrzeżony, prawda?
Stare interfejsy SAPI i rozszerzenia
Co najważniejsze, stare i przestarzałe interfejsy SAPI zostały usunięte, podobnie jak rozszerzenie mysql
(ale nie powinieneś używać tego w pierwszej kolejności, prawda?). Pełną listę rozszerzeń i usuniętych funkcji można znaleźć w tych dokumentach RFC tutaj i tutaj.
Ponadto inne interfejsy SAPI są przenoszone do PHP 7.
Jednolita składnia zmiennej
Ta aktualizacja wprowadziła pewne zmiany na korzyść spójności konstrukcji ze zmienną zmienną. Pozwala to na bardziej zaawansowane wyrażenia ze zmiennymi, ale wprowadza zmiany w zachowaniu w niektórych innych przypadkach, jak pokazano poniżej.
// old meaning // new meaning $$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz'] $foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz'] $foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']() Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()
Zepsułoby to zachowanie aplikacji uzyskujących dostęp do takich wartości. Z drugiej strony możesz zrobić kilka fajnych rzeczy takich jak:.
// Nested () foo()(); // Calls the return of foo() $foo->bar()(); // IIFE syntax like JavaScript (function() { // Function body })(); // Nested :: $foo::$bar::$baz
Usunięto tagi starego stylu
Tagi otwierające/zamykające <% ... %>
, <%= ... %>
, <script language="php"> ... </script>
zostały usunięte i nie są już ważne. Zastąpienie ich prawidłowymi powinno być łatwe, ale co w ogóle robisz używając ich, Dziwaku?
Nieprawidłowe nazwy klas, interfejsów i cech
Wynikające z dodatków, takich jak typy parametrów i typów zwracanych, klasy, interfejsy i cechy nie mogą już mieć następujących nazw:
- głupota
- int
- pływak
- strunowy
- zero
- prawda
- fałszywe
Powodują one przerwy w istniejących aplikacjach i bibliotekach, które ich używają, ale powinny być łatwe do naprawienia. Ponadto, chociaż nie powodują one żadnych błędów i są prawidłowe, nie należy ich używać, ponieważ są one zarezerwowane do wykorzystania w przyszłości:
- ratunek
- obiekt
- mieszany
- numeryczny
Powstrzymanie się od ich używania powinno oszczędzić ci pracy nad ich zmianą w przyszłości.
Pełną listę zmian, które mogą spowodować naruszenie kompatybilności, znajdziesz w tym dokumencie.
Możesz także użyć php7cc, które sprawdza twój kod i może wykryć potencjalne problemy, które mogą się pojawić po przejściu na PHP 7. Ale oczywiście nie ma lepszego sposobu niż zainstalowanie PHP 7 i zobaczenie go na własne oczy.
Potencjalne problemy z kompatybilnością PHP 7
Kompatybilność infrastruktury PHP 7
Wiele usług hostingowych zaczęło dodawać obsługę PHP 7. To dobra wiadomość dla dostawców hostingu współdzielonego, ponieważ wzrost wydajności pozwoli im zwiększyć liczbę witryn klienckich na ich sprzęcie, zmniejszając koszty operacyjne i zwiększając marże. Jeśli chodzi o samych klientów, nie powinni oczekiwać zbyt dużego wzrostu w tych warunkach, ale szczerze mówiąc, współdzielony hosting i tak nie jest wyborem zorientowanym na wydajność.
Z drugiej strony usługi oferujące wirtualne serwery prywatne lub serwery dedykowane będą czerpać pełne korzyści z tego skoku wydajności. Niektóre usługi PaaS, takie jak Heroku, wcześnie obsługiwały PHP 7, ale inne usługi, takie jak AWS Beanstalk i Oracle OpenShift, pozostają w tyle. Sprawdź witrynę dostawcy PaaS, aby sprawdzić, czy PHP 7 jest już obsługiwane lub czy wsparcie to nastąpi w najbliższej przyszłości.
Oczywiście dostawcy IaaS pozwalają przejąć kontrolę nad sprzętem i zainstalować PHP 7 (lub skompilować, jeśli bardziej Ci odpowiada). Pakiety PHP 7 są już dostępne dla głównych środowisk IaaS.
Kompatybilność oprogramowania PHP 7
Oprócz zgodności infrastruktury należy również pamiętać o potencjalnych problemach ze zgodnością oprogramowania. Popularne systemy zarządzania treścią, takie jak WordPress, Joomla i Drupal, dodały obsługę PHP 7 w swoich najnowszych wydaniach. Duże platformy, takie jak Symfony i Laravel, również cieszą się pełnym wsparciem.
Czas jednak na słowo ostrzeżenia. Ta obsługa nie obejmuje kodu stron trzecich w postaci dodatków, wtyczek, pakietów lub czegokolwiek, co nazywa je Twój CMS lub framework. Mogą cierpieć z powodu problemów ze zgodnością i Twoim obowiązkiem jest upewnienie się, że wszystko jest gotowe na PHP 7.
W przypadku aktywnych, utrzymywanych repozytoriów nie powinno to stanowić problemu. Jednak starsze i nieobsługiwane repozytoria bez obsługi PHP 7 mogą uniemożliwić korzystanie z całej aplikacji.
Przyszłość PHP
Wydanie PHP 7 usunęło stary i przestarzały kod i utorowało drogę do nowych funkcji i ulepszeń wydajności w przyszłości. Ponadto oczekuje się, że PHP wkrótce uzyska dodatkową optymalizację wydajności. Pomimo pewnych przerw w kompatybilności z poprzednimi wydaniami, większość problemów jest łatwa do rozwiązania.
Biblioteki i frameworki migrują teraz swój kod do PHP 7, udostępniając w ten sposób najnowsze wersje. Zachęcam do wypróbowania i zobaczenia efektów na własne oczy. Może Twoja aplikacja jest już kompatybilna i czeka na użycie PHP 7.