PHP 7 … Prace nad nową główną wersją PHP, nazwaną PHP 7 rozpoczęły się oficjalnie w roku 2014. Wśród twórców rozgorzały dyskusje na temat nazwy następnego wydania PHP. Chociaż eksperymentalna wersja PHP 6, której celem było wprowadzenie wsparcia dla Unicode, nie została nigdy wydana, wiele artykułów i książek odwoływało się do starej nazwy PHP 6. Mogłoby to prowadzić do nieporozumień, gdyby nowe wydanie, zawierające inne funkcje, a niezawierające wsparcia dla Unicode, również nazywało się PHP 6. W wyniku głosowania wybrano nazwę PHP 7.
Bazą PHP 7 stała się eksperymentalna gałąź, oryginalnie nazwana PHPNG (PHP Next Generation), mająca na celu optymalizację wydajności PHP przez refaktoryzację Zend Engine, zachowując niemal całkowitą zgodność języka. Począwszy od 14 lipca 2014 r., główny punkt odniesienia testowania wydajności PHPNG, którym jest WordPress, wskazuje niemal 100% wzrost wydajności. Zmiany wprowadzone w PHPNG powinny również ułatwiać implementowanie usprawnień wydajności w przyszłości, ponieważ bardziej zwarte struktury danych oraz inne zmiany uważane są za lepiej nadające się do pomyślnej migracji do kompilacji Just-in-time.
Funkcjonalności, sprawiające, że PHP7 jest rewolucyjny, szybki, warty polecenia:

PHP 7 – Wydajność.

 

 

 

 

 

Dymitry Stogov, który jest jednym z twórców PHP, w udzielonym niedawno wywiadzie poinformował, że wersja 7.0 jest w benchmarkach 14x szybsza niż wersja 5.0, dla przypomnienia: wydana w 2004 roku. W realnych testach najpopularniejsze frameworki okazują się działać około 70% szybciej, w porównaniu do ostatniej stabilnej wersji. Ja osobiście testowałem na różnych płaszczyznach i w różny sposób tą sławną wydajność, no wychodziło mi nie 14x tylko 4x ale to i tak uważam, jest coś na rzeczy.

Poniższy obrazek –  test sprawdza operacje na bazie danych – jeden insert z użyciem standardowego narzędzia do obsługi bazy danych dostarczonego z testowanym frameworkiem. Dla Symfony jest to Doctrine (implementacja Object Relational Mapper), w przypadku Laravel mamy Eloqent (implementacja Active Record):

 

 

 

 

W popularnym benchmarku, polegającym na generowaniu zbioru Mandelbrota, najnowsza wersja PHP okazuje się bić na głowę języki takie jak: Python, Ruby czy Perl.

Ujednolicenie składni

Jednym z głównych zarzutów, stawianych od zawsze jako argument przeciwko językowi PHP jest brak konsekwecji w jego składni. Jedne operacje były dozwolone, podobne do nich powodowały błędy składniowe. Na przykład od wersji 5.4 umożliwiono natychmiastową dereferencję tablicy zwracanej z metody, jednak dalej nie było możliwe natychmiastowe wywołanie zwracanej funkcji. PHP7 wprowadza przełom w tej kwestii. Dodano wiele operacji, które sprawiają, że składnia staje się bardziej spójna i jednolita, pozwoli to między innymi na pełniejsze wykorzystanie programowania funkcyjnego. Poniższe przykłady najlepiej zilustrują zmiany, które zostały wprowadzone.

// zagnieżdżenie wywoływania funkcji - funkcje wyższego rzędu
$apply = function ($fun) {
    return function ($a) use ($fun) {
        return $fun($a);
    };
};

$add = function ($x) {
    return function ($y) use ($x) {
        return $x + $y;
    };
};

echo $apply($add)(2)(3);

PHP 7: 5
PHP 5.6: Parse error: syntax error, unexpected ‚(‚, expecting ‚,’ or ‚;’ in …

echo (function ($a) {
    return $a + 3;
})(2);

PHP 7: 5
PHP 5.6: Parse error: syntax error, unexpected ‚(‚, expecting ‚,’ or ‚;’ in …

Warto zwrócić uwagę, że ta zmiana powoduje złamanie kompatybilności wstecznej, stary kod musi zostać przeglądnięty i dostosowany do nowych realiów. Więcej przeczytać można w RFC: Uniform Variable Syntax.

Wyjątki zamiast błędów krytycznych

PHP7 wprowadza bardzo istotną zmianę w wewnętrznej obsłudze błędów. Od wersji 7 błędy krytyczne są zgłaszane jako wyjątki silnika, które będą mogły być łapane i obsługiwane jak wszystkie pozostałe wyjątki. Rozwiązanie to powoduje szereg usprawnień względem klasycznej obsługi błędów. Przede wszystkim pozwala na przechwytywanie błędów, które wcześniej powodowały natychmiastowe zatrzymanie wykonania programu. Przykładem, który dobrze ilustruje problem jest błąd krytyczny podczas wykonywania testów, obecnie błąd krytyczny w jednym z przypadków testowych powoduje zatrzymanie całej procedury testowania. Co więcej, wyjątki dostarczą ślad stosu, który ułatwi debugowanie źródła błędów.

function add(int $a, int $b) : int
{
    return $a + $b;
}

try {
    echo add(2, "trzy");
} catch (EngineException $e) {
    //Argument 2 passed to add() must be of the type integer, string given ...
    echo $e->getMessage(); 
}

Wprowadzone zostają dwa nowe typy wyjątków, dla wewnętrznych EngineException błędów silnika oraz ParseException dla błędów składniowych, więcej informacji można znaleźć w RFC: Exceptions in the engine.

Deklaracje dla typów skalarnych

Jedną z największych zmian w PHP7 jest dodanie deklaracji dla typów skalarnych, deklarowane będą mogły być łańcuchy znaków (string), liczby całkowite (int) i zmiennoprzecinkowe (float) oraz typy logiczne (boolean). Uzupełniają one dodane w poprzednich wersjach deklaracje dla klas, interfejsów, tablic i typu callable.

Sprawdzanie typów dostępne będzie w dwóch wersjach, domyślnym coercive – dopuszczającym rzutowanie  i strict – dopuszczająca tylko dokładny typ. Sprawdzanie typów konfiguruje się dla każdego pliku osobno, w celu odblokowania trybu strict należy w na samej górze pliku umieścić linię:

declare(strict_types=1);

Gdy dopasowanie typu nie powiedzie się, zostanie rzucony wyjątek TypeError, co także jest nowością wprowadzoną w PHP7.

declare(strict_types=1);

function multiply(float $x, float $y)
{
    return $x * $y;
}

function add(int $x, int $y)
{
    return $x + $y;
}

var_dump(multiply(2, 3.5)); // float(7)
var_dump(add('2', 3)); // Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type integer, string given...

Deklaracje dla typów zwracanych

Kolejną przełomową zmianą w PHP7 jest wprowadzenie deklaracji dla typów zwracanych. Dostępny jest szereg typów, które są obsługiwane: ciągi znaków (string), liczby całkowite (int) i zmiennoprzecinkowe (float), typy logiczne (bool),  tablice (array), typ callable, typ self (tylko dla metod), typ parent (tylko dla metod), domknięcia (Closure), a także klasy i interfejsy.

Deklaracje dla typów zwracanych, podobnie jak dla typów skalarnych posiadają dwa tryby: coercive – dopuszczającym rzutowanie  i strict – tylko dokładny typ, konfigurowane analogicznie jak w poprzednim przypadku.

Deklaracji typu zwracanego dokonuje się poprzez umieszczenie dwukropka i nazwy typu po liście argumentów funkcji:

function add(int $x, int $y) : int
{
    return $x + $y;
}

 

Gdy dopasowanie typu nie powiedzie się, podobnie jak w przypadku deklaracji dla typów statycznych, zostanie rzucony wyjątek TypeError.

 

declare(strict_types=1);

function multiply(float $x, float $y) : float
{
    return $x * $y;
}

function add(int $x, int $y) : string
{
    return $x + $y;
}

var_dump(multiply(2, 3.5)); // float(7)

var_dump(add(2, 3)); // Fatal error: Uncaught TypeError: Return value of add() must be of the type string, integer returned

Klasy anonimowe

Klasy anonimowe, znane między innymi z języka Java są także dostępne w PHP7. Pozwalają one na utworzenie instancji klasy w miejscu i natychmiastowe przekazanie obiektu, na przykład do funkcji. Są wyjątkowo użyteczne gdy instancja obiektu wykorzystywana jest tylko i wyłącznie w jednym miejscu.

 

interface Comparator {
    public function compare($a, $b);
}

// PHP5+
class SimpleComparator implements Comparator
{
    public function compare($a, $b)
    {
        return $a === $b;
    }
}

$system->setComparator(new SimpleComparator());

// PHP7
$system->setComparator(
    new class implements Comparator {
        public function compare($a, $b)
        {
            return $a === $b;
        }
    }
);

Nowe operatory: połączonego porównania (Combined Comparison / Spaceship) oraz trójkowy isset (Trenary isset / Null Coalesce)

PHP7 wprowadza dwa nowe operatory, które pozwalają łatwiej przeprowadzać typowe operacje.

Pierwszy z nich, operator połączonego porównania, nazywany też spaceship (statek kosmiczny) pozwala na skrócone trójkowe (większy, równy, mniejszy) porównywanie wartości.

 

var_dump(1 <=> 2); // int(-1)

var_dump(‘PHP7’ <=> ‘PHP7’); // int(0)

var_dump(‘PHP7’ <=> ‘PHP6’); // int(1)

var_dump([1,2,3] <=> [3,4,5]); // int(-1)

Dla ciągów znaków wykonywanie jest porównanie leksykalne. Dla obiektów zachowanie tego operatora nie zostało zdefiniowane.

Drugi z operatorów, trójkowy isset, pozwala na szybkie sprawdzenie czy wartość istnieje i nie jest równa null, w przeciwnym przypadku pozwala zwrócić wartość domyślną.

 

$page = $_GET['page'] ?? 1; // $page = isset($_GET['page']) ? $_GET['page'] : 1;

Operator ten może być łączony w łańcuchy:

$email = $_POST['email'] ?? $user['email'] ?? 'user@esky.pl';

 

Inne przykłady:

echo 1 <=> 1; // 0 - dla równych wartości
echo 1 <=> 0; // 1 - jeśli prawa wartość jest większa od wartości po lewej
echo 0 <=> 1; // -1 - jeśli prawa wartość jest mniejsza od wartości po lewej

działa też dla napisów:

echo "x" <=> "x"; // 0
echo "y" <=> "x"; // 1
echo "y" <=> "z"; // -1

dla tablic i obiektów:

echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> [1, 2]; // 1
echo [1, 2, 4] <=> [1, 2, 3]; // 1
echo [1, 2] <=> [1, 2, 3]; // -1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
$a = (object) ["field" => "abc"]; 
$b = (object) ["field" => "abc"]; 
echo $a <=> $b; // 0
$a = (object) ["other_field" => "cba"]; 
$b = (object) ["other_field" => "abc"]; 
echo $a <=> $b; // 1
$a = (object) ["one_another" => "abc"]; 
$b = (object) ["one_another" => "cba"]; 
echo $a <=> $b; // -1

Grupowanie deklaracji use

Grupowanie deklaracji use pozwala w wygodny, skrócony sposób importować nazwy z tej samej przestrzeni nazw.

// PHP5+
use Esky\Blog\Post;
use Esky\Blog\Author as User;
use Esky\Blog\Comment;

// PHP7
use Esky\Blog\{Post, Author as User, Comment};

Stała tablicowa via define()

Od wersji 5.6 tablice mogą być także stałymi:

<?php
const MY_ARRAY = [
  'hey',
  'it's',
  'an',
  'array!',
];

ale dopiero wersja 7 wprowadza możliwość definiowania takiej stałej przy pomocy funkcji define()

define()
<?php
define('MY_ARRAY', [
  'I'm',
  'an array',
  'too!',
]);

WYRAŻENIA PO NOWEMU

Szybkość nowej wersji wzięła się m. in. z wprowadzenia AST, co wpłynęło również na sposób interpretowania zapisanych wyrażeń:

Wyrażenie

Działanie w PHP 5

Działanie w PHP 7

$$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’]()

ZMIANY NIEKOMPATYBILNE WSTECZ

Niestety nie udało się uniknąć kilku zmian, które spowodują niekompatybilność kodu wstecz.  Główną zmianą opisaną wyżej jest Uniform Variable Syntax. Dodatkowo:

    • usunięto obsługę tagów ASP (<%, <%=, <script language=”php”>)
    • usunięto wszystkie funkcje oznaczone jako depracated (po więcej danych odsyłam do RFC)
    • usunięto składnie POSIX
    • usunięto rozszerzenie ext/mysql
    • usunięto możliwość definiowania więcej niż jednego warunku default w switch 

Warto odwiedzić:

https://www.zend.com/en/resources/php-7

https://github.com/tpunt/PHP7-Reference

https://www.zend.com/en/resources/php7_infographic

https://kinsta.com/blog/hhvm-vs-php-7/

https://blog.amasty.com/php-7-and-script-languages-future-insights-from-lead-zend-com-developer/


			

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *