Ce este nou în PHP 8: Tot ce trebuie să știți!

Publicat: 2021-01-06

Vom lua legătura cu PHP8 pe 26 noiembrie 2020 și, cu siguranță, sunt multe scrise despre caracteristicile viitoare din această versiune apreciată.

PHP 8

Deoarece este o versiune majoră, vor exista modificări de ultimă oră și funcții noi, de asemenea, va face important să fiți conștienți de ceea ce se schimbă totul. Vă va face convenabil să vă gândiți la modul în care PHP8 vă va afecta aplicațiile și ce acțiuni vor fi necesare pentru a vă asigura că puteți face upgrade convenabil, fără incidente.

Am trecut prin câteva dintre cele mai considerabile modificări pentru a ne da seama ce vom obține în următoarea versiune PHP și ce merită criticat.

să începem cu privirea de ansamblu!

Prezentare generală PHP 8

După cum am menționat mai sus, PHP 8 introduce un pachet de noi caracteristici, îmbunătățiri, funcții și deprecieri pentru limbaj. Dintre toate acestea, cea mai discutată caracteristică este compilatorul JIT. Cu toate acestea, funcțiile de îmbunătățire a performanței, cum ar fi JIT, merită lumina reflectoarelor, dar se așteaptă că îmbunătățirile sintactice vor avea mai mult un adevărat zgomot pentru practicienii PHP, am spune noi, „cel puțin pe termen scurt”.

O istorie a schimbării

Câteva modificări PHP sunt propuse, dezbătute, implementate și aprobate în continuare în scurt timp. Sunt populare, necontroversate și au o metodă naturală de a le implementa.

Și după aceea vin cei care sunt încercați, eșuează și revin de mai multe ori înainte să le acceptăm în sfârșit. De câteva ori, implementarea consumă mult timp pentru a rezolva, iar uneori ideea în sine este doar pe jumătate coaptă, iar uneori comunitatea în sine nu s-a încălzit încă la idee — „nu este încă timpul”.

Creditele se încadrează direct în categoria tip. Ele au fost propuse pentru prima dată în anul 2016 pentru PHP 7.1. Cu toate acestea, s-au întâmpinat cu o rezistență încăpățânată și au pierdut votul de acceptare cu o marjă mare. Acum, înainte rapid cu patru ani, și o propunere destul de similară, chiar dacă cu un domeniu de aplicare ușor redus, a fost aprobată de un singur disident. Este evident o idee al cărei timp a venit cu siguranță!

Care sunt problemele cu vechiul cod?

Întrucât PHP 8 este o nouă versiune uriașă, ar trebui să ne așteptăm ca vechiul cod să nu mai fie compatibil. Cu toate acestea, majoritatea modificărilor care ar putea prezenta complicații au fost deja transmise în versiunile 7.2 , 7.3 și 7.4 . Să vorbim acum despre ultimele modificări. Ei sunt:

Citate magice moștenire

  • Tipul adevărat
  • FILTER_SANITIZE_MAGIC_QUOTES filtru
  • Dezlegarea $this de la închiderile non-statice
  • array_key_exists() cu obiecte
  • mb_strrpos() cu codificare ca al treilea argument
  • Metode reflection export() .
  • funcția convert_cyr_string() .
  • parametrul implode() amestec de ordine
  • funcția restore_include_path() .
  • funcția hebrevc() .
  • funcția money_format() .
  • directiva allow_url_include ini
  • funcția ezmlm_hash() .

Funcții noi în PHP 8

str_contains

Dacă un șir conține altul, atunci există numeroase modalități de a afla.

În general, veți folosi strpos(). După cum știți, strpos() ia un car de fân lângă acul pe care doriți să-l căutați. Returnează un număr întreg care arată prima poziție în care vedeți acul.

Acum, deoarece returnează poziția unui șir în altul, pur și simplu nu puteți verifica dacă strpos() l-a descoperit sau nu; dacă returnează „0” (pozițiile sunt indexate la zero și încep cu 0 mai degrabă decât cu 1), atunci condiționalul îl va trata ca o valoare falsă și indică că nu a fost găsit.

Ce inseamna asta?

Va trebui să scrieți condițional – „strpos($haystack, $needle) !== false.” False indică faptul că nu a putut găsi poziția șirului. Aceasta este o metodă netransparentă și ezoterică de a căuta un șir într-un șir! Ei bine, nu atât de confuz.

Pentru a evita acest lucru, PHP 8 aduce str_contains(). Sarcina lui str_contains() este să returneze un simplu boolean care să arate dacă acul este sau nu prezent în carul de fân. Este mult mai ușor de scris, pe lângă asta, înțeles ca cineva care întreține codul, nu-i așa?

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

PHP 8: Caracteristici și modificări ale motorului

Există câteva caracteristici noi ale motorului și modificări observate în PHP 8. Caracteristica principală, fără îndoială, este noul compilator JIT.

Compilatorul JIT

  • Aplicarea LSP
  • Erori fatale la semnăturile metodelor incompatibile
  • Resursa „Clasuri”
  • XML-RPC este acum în PECL
  • Comportament de afirmare
  • Reflecția se schimbă

De dragul scopului principal al acestui blog, ne vom concentra pe compilatorul JIT, „clasele” de resurse și, în final, pe modificările API-ului de reflecție.

Compilator Just-In-Time ( RFC )

Datorită îmbunătățirilor de viteză făcute înainte de lansarea PHP7, a avut loc nașterea compilatorului Just-In-Time (sau JIT). Este introdus în PHP8 deoarece aproape că nu mai există îmbunătățiri ale vitezei care pot fi aduse fără a utiliza un JIT. Ideea este că va îmbunătăți performanța PHP.

Codul PHP este tradus în coduri de octet atunci când este executat, iar acele coduri de octet sunt utilizate în continuare pentru a executa pașii din program.

PHP va analiza codul pe care l-ați executat, asta înseamnă un JIT. În plus, poate lua decizii în timp real, altele decât îmbunătățirea performanței codului pe măsură ce îl executați. Va fi foarte utilizabil în aplicațiile cu consum mare de CPU și nu doar atunci când este utilizat în scenarii bazate pe web.

Acest lucru reflectă, cu siguranță, aplicațiile PHP de pe partea de server pot fi mai răspândite cu sistemul JIT încorporat în PHP.

Mai întâi trebuie să activați JIT dacă doriți să îl utilizați. Pe sistemul nostru de testare (Ubuntu 20.04), avem deja instalat modulul PHP opcache, pe care l-am instalat cu pachetul de bază PHP8. Am configurat în fișierul plasat la /etc/php/8.0/cli/conf.d/10-opcache.ini.

Acum, sunteți gata să activați JIT, nu?  

  • Activați opcache-ul

Puteți atribui spațiu de stocare în memorie setării opcache.jit_buffer_size . Fișierul dvs. va apărea astfel pe sistemul meu.

  1. zend_extension=opcache.so
  2. opcache.enable_cli=1
  3. ; configurație pentru modulul php opcache
  4. opcache.jit_buffer_size=256M

În plus, utilizați funcția opcache_get_status() pentru a vă asigura că este activ. Întoarceți-vă privirea peste partea „jit” a acestei matrice și obțineți informații despre starea curentă a JIT.


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

Dacă JIT a fost activat perfect, acesta ar trebui să se imprime așa cum se arată acolo.

  1. matrice (7) {
  2. [„activat”] =>
  3. bool (adevărat)
  4. [„pornit”] =>
  5. bool (adevărat)
  6. [„bună”] =>
  7. int(5)
  8. [„opt_level”] =>
  9. int(4)
  10. [“opt_flags”] =>
  11. int(6)
  12. [„buffer_size”] =>
  13. int(268435440)
  14. [„buffer_free”] =>
  15. int(268432880)
  16. }

Deci a fost mai rapid? Într-un cuvânt, am exclama un „da” cald.

Am observat câțiva oameni care fac benchmark-uri cu ajutorul unui set mandelbrot, așa că am decis să folosim o bibliotecă pe care am creat-o cu ceva timp în urmă, care desenează diferite tipuri de fractali în PHP. Tot ce am făcut a fost să generăm trei fractali și să urmărim cât timp a durat utilizând funcția microtome(). Am afișat mai jos rezultatele pentru PHP 7.4.8.

  • Burningship – 84.20269203186
  • Mandlebrot – 21.552599906921
  • Tricorn – 32.685042858124

Când am rulat același cod pe PHP8, a fost destul de rapid. Cifrele vor vorbi de la sine. .

  • Burningship – 15.272277116776
  • Mandlebrot -3.7528541088104
  • Tricorn -4.4957919120789

Această creștere uriașă a vitezei este destul de interesantă. Codul pe care l-am folosit aici creează fractali de dimensiuni uriașe, dar când am creat codul ne amintim că cea mai mare parte a timpului nostru a fost petrecut așteptând generarea de fractali.

Această adăugare este interesantă pentru noi, deoarece am împins PHP la limitele sale în unele ocazii (în afara generării de fractali). Putem observa că acest lucru este de mare beneficiu pentru viitorul PHP și va permite alegerea limbii pentru situații în afara limbajului obișnuit al site-ului web.

Nu ne-am uitat la creșterea vitezei pentru aplicații precum WordPress sau Drupal, dar din ceea ce am citit, cu siguranță există o mică diferență între astfel de aplicații. În viitor, vom rula benchmark-uri pe aceste platforme pentru a ne da seama ce fel de diferență marchează JIT acolo.

Tipuri de uniuni ( RFC )

De la PHP7, se stipulează ce fel de valori returnate și tipuri de argumente au fost posibile. Acest lucru va permite PHP să arunce o eroare în cazul în care tipul de argument pe care îl transmiteți nu este identic cu tipul așteptat. Este esențial să ne asigurăm că funcțiile primesc și produc tipurile perfecte de valoare într-un limbaj cu tastare vag, cum ar fi PHP.

În PHP8, acum este posibil să se stipuleze diverse sortări pentru argumente și valori returnate, împărțite printr-un caracter pipe.

Am arătat mai jos o funcție care este capabilă să accepte fie o valoare flotantă, fie o valoare întreagă.

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

Anterior, o funcție identică cu aceasta ar trebui să fie generată fără nicio indicație de tip, deoarece PHP ar putea prezenta tipul în tăcere în cazul în care argumentul transmis nu era corect. Însemna că, în cazul în care setăm tipul de argument ca un număr întreg, PHP ar prezenta orice valoare flotantă într-un număr întreg. Cu siguranță poate duce la câteva erori dificile de prins în cazul în care nu testați unitatea.

Îl numim ca oricare altul pentru a folosi funcția de mai sus

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

În cazul în care încercăm să trecem un șir la funcția identică:

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

Vom primi o eroare PHP Fatal care exclamă că trebuie să trecem fie un float, fie un „int” în funcție.

Nu puteți utiliza tipul void ca tip de unire, deoarece stipulează că funcția nu va returna nimic. Cu cuvinte simple, nu puteți exclama că o funcție va returna un gol sau un întreg; veți primi o eroare fatală PHP.

Deși o schimbare normală pe care o putem vedea, această caracteristică a fost folosită puțin, deoarece mai devreme a fost posibil doar să se stipuleze diferite tipuri de valori în comentarii, ceea ce a dus la comentariile blocului de documente care devin mai detaliate decât codul.

Operatorul Nullsafe (RFC)

Pe lângă operatorul de coalescere nulă, abilitatea de a detecta valorile returnate nul este posibilă direct din metode. Dacă nu erați conștient, operatorul de coalescere nul vă permite să obțineți o valoare și nu trebuie să testați în cazul în care valoarea este prezentă pe lângă returnarea unei alte valori în cazul în care prima valoare este nulă.

Deci, putem face acest lucru pentru a prelua o valoare din – „$_GET superglobal”. iar în cazul în care acea valoare nu este prezentă, atunci „0”.


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

2. echo $pagina;

Funcționarea operatorului de siguranță nul este aceeași, dar vă permite să creați o comandă rapidă la îndemână și să testați o întoarcere nulă dintr-un mod înainte de a încerca să utilizați acea valoare.

Am observat că acest lucru va fi în cele din urmă util în Drupal, unde avem tendința de a scrie o mare parte din codul de verificare pentru a ne asigura că „întoarcerile de la metode” sau „proprietățile obiectului” au lucruri în ele înainte de a le utiliza. Acest lucru este obligatoriu din cauza stării contextuale a obiectelor din Drupal din cauza conținutului pe care îl conțin. Această modificare va simplifica cu siguranță unele dintre verificări.

Argumente numite ( RFC )

Argumentele numite vă permit să specificați o ordine diferită a argumentelor și a funcțiilor de apelare. Luați următoarea funcție normală care are doi parametri. Umple o matrice la lungimea dată.

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

Putem trece argumentele în aranjamentul pe care sunt definite, poate numi această tehnică în mod normal.

 $newArray = fillArray([], 2);

Începând cu PHP8, puteți denumi parametrii pe măsură ce îi transmiteți funcției. De asemenea, vă permite să trimiteți parametrii în orice ordine dorim.

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

Un exemplu normal, dar poate face și codul mai lizibil.

Această tehnică funcționează cu toate funcțiile din PHP, nu doar cu cele definite de utilizator. În limbajul PHP, funcțiile matrice și șir au ordine de parametri neidentice. Deci, este un plus cu adevărat binevenit.

Atribute V2 ( RFC1 RFC2 RFC3 )

Atributele furnizează un mecanism de alăturare a metadatelor la clasele, funcțiile, proprietățile clasei, parametrii funcției și constantele PHP. Ele nu pot fi accesibile direct prin cod și trebuie să le scoateți cu ajutorul claselor de reflecție construite în PHP.

Clasa ReflectionClass este în PHP încă din PHP5; cu toate acestea, metoda getAttribute() este nouă pentru PHP8. Această metodă returnează o serie de obiecte ReflectionAttribute care vor cuprinde informații despre atribute.

Această adăugare s-a confruntat cu câteva modificări (după cum putem observa din multiplele RFC-uri de mai sus). În cazul în care instanțiați clasa, puteți apoi să utilizați ReflectionClass și să tipăriți informațiile despre atribut conținute la nivel de clasă. Există destul de multe atribute în PHP8, așa că vă recomandăm să citiți RFC-urile și să vă familiarizați cu ceea ce sunt acestea de fapt și cum le puteți integra în codul dvs.

Potrivire expresie ( RFC )

În PHP 8, putem compara noua expresie de potrivire cu o instrucțiune scurtă switch.

Pare puțin ca o declarație de funcție care va returna o valoare pe baza valorii transmise.

Declarația switch în PHP este uimitoare atunci când doriți să verificați starea expresiei identice fără a include mai multe instrucțiuni if ​​cu totul.

Aici aducem o comparație de bază dacă-altfel pe o expresie identică.

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

Și așa ar arăta declarația switch echivalentă din exemplul nostru anterior

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

Resursa „Clasuri”

„Clasele” de resurse apar în lista modificărilor majore din PHP 8 și servesc ca înlocuitori neinstanțiabili pentru anumite tipuri de resurse. Vedeți mai jos pentru a afla înlocuitorii disponibile includ:

  • CurlHandle — curl_init() returnează acum CurlHandle, relaționând o resursă curl.
  • Socket / AddressInfo — Dat de extensia socket-urilor; cantitatea de funcții socket_*() returnează un Socket, în timp ce funcția socket_address_info_lookup() returnează o instanță AddressInfo.
  • GdImage — Reprezintă o resursă GD, restaurată de numeroasele funcții imagecreatefrom*().

De asemenea, este esențial să rețineți că resursele nu sunt distruse de funcții precum curl_close(). Mai degrabă, trebuie să unset() instanța pentru a-l dereferi, deoarece acum este o instanță de clasă.
Obțineți capacitatea de a specifica clasele ca indicații de tip în funcțiile și metodele dvs.
Mai devreme, a trebuit să returnăm valorile netipizate sau să lăsăm argumente de resurse și să le documentăm prin adnotări, dar acum, puteți avea tipuri explicite, iar asta nu face doar codul mai ușor de citit, ci și mai sigur de tip.
Care este compromisul aici?
Acum va trebui să vă actualizați codul dacă doriți să distrugeți resurse cu ajutorul unset() în locul funcțiilor anterioare utilizate pentru a demola resurse. Acest lucru poate fi realizat în mod normal prin căutare și înlocuire.

Modificări API Reflection

Un alt mic, dar o schimbare vitală în PHP 8 este legată de Reflection API. În timp ce utilizați sistemul de atribute, puteți prelua în mod convenabil acele atribute prin API-ul Reflection pe orice clase de reflectare.
Odată cu adăugarea de tipuri mixte și de unire, tehnicile ReflectionParameter getClass(), isCallable() și isArray() sunt acum depreciate.
Scenariul este așa, deoarece utilizarea getType(), este mult mai bună și obțineți lista completă de tipuri pe care le satisface un anumit parametru.

Îmbunătățiri de sintaxă PHP 8

După cum observăm, JIT fură titlurile; îmbunătățirile sintactice PHP 8 oferă avantaje uriașe de calitate a vieții pentru dezvoltatorii PHP.
Indiferent de faptul că este vorba de eliminarea boilerplate comune dintre argumentele constructorului promovat sau de gestionarea îmbunătățită a excepțiilor și erorilor, dezvoltatorii trebuie să se simtă încântați.

  • pseudotip „mixt”.
  • Tipuri de uniuni
  • Promovarea proprietății Class Constructor
  • Aruncarea excepții de la expresii
  • Atribute
  • ::ubicuitatea clasei
  • Captură numai după tip
  • Potriviți expresii

Pentru menținerea acestui blog, ne concentrăm pe tipuri de uniuni, atribute și expresii de potrivire.

Tipuri de uniuni

Tipurile de unire arată că o valoare este una dintre două sau mai multe sorturi specificate. Se face cu o bară verticală plasată între fiecare tip permis. Pentru mai mulți dezvoltatori care sunt aprofundați în adnotările PHP pentru a returna valori sau a-ți specifica parametrii, ați făcut deja acest lucru, cel mai probabil.
Tipurile de uniuni pot aduce multă complexitate și dificultăți în înțelegere pentru cei care acceptă o mulțime de tipuri diferite sau returnează o mulțime de tipuri diferite.
Totuși, acest lucru va fi foarte util de mai multe ori. De exemplu, în cazul în care puteți accepta sau un obiect care implementează noua interfață Stringable („string|Stringable”) sau un șir, sau dacă puteți accepta fie un obiect care implementează interfața Traversable („array|Traversable”), fie o matrice .

Potriviți expresii

Expresiile de potrivire opresc presupunerile legate de a afla dacă eșecul de a întrerupe într-un anumit caz de comutare este intenționat sau nu. De asemenea, simplifică tiparul normal de atribuire a unei valori pe baza unei potriviri.
Când este folosită, valoarea pe care o transmitem la match() va fi comparată direct cu orice expresie se află în partea stângă. Indiferent că este o expresie sau o valoare, valoarea pe care o transmiteți la match() ar trebui să se potrivească cu ea pentru ca aceasta să fie aleasă.
Când se potrivesc, expresia prezentă în dreapta este estimată și valoarea returnată a acesteia este returnată, în timp ce expresiile pot fi numai funcții Lambda sau apelabile și nu sunt permise închideri pe mai multe linii.

Atribute

PHP 8 integrează atribute și la nivel de limbă. În timp ce atributele sunt prezente de mai bine de 15 ani prin intermediul adnotărilor docblock, integrarea lor în limbaj oferă o performanță mai bună și, cu siguranță, mai multă putere și mai multă consecvență. Probabil că vom vedea atributele foarte utilizate în dezvoltarea de scule și aplicații rapide.

Concluzie

Cu siguranță, există câteva modificări în PHP8. Totuși, se pare că majoritatea codului învechit eliminat este pentru funcții mai vechi pe care nu le-am văzut folosite în ultima vreme.
Suntem destul de interesați să observăm ce impact va avea motorul JIT asupra bazelor de cod pe care le folosim și, de asemenea, asupra comunității PHP mai largi, spunând că vă recomandăm să scanați baza de cod pentru incompatibilități cu PHP8 și să rulați teste unitare pentru a ne asigura că PHP-ul dvs. aplicațiile funcționează perfect înainte de a spune „da” upgrade-ului.