SlideShare a Scribd company logo
POINT TECHNIQUE
PHP 8: Process
& Fixing Insanity
George Peter Banyard
● Mathematics student at Imperial
College London
● Currently hired by The Coding Machine
to work on php-src, i.e. the PHP Engine
● Find me on Twitter and elsewhere
@Girgias
● https://gpb.moe
2
Me at 3AM realising I need a photo for the presentation
How I got involved with the PHP project
• French translation PHP documentation
• PHP internal mailing list
• Proposed the “Deprecate PHP Short open tags” PHP RFC
• Started tinkering with PHP’s source code
• PoC: declare statement which promote warnings to Exceptions
• Made multiple patches
• php-src VCS karma granted
3
PHP a truly open source language: PHP RFCs
A PHP RFC is a proposal which affects the PHP engine:
Behaviour change, feature addition, deprecations, extensions
Anyone can propose a PHP RFC, from QoL to Advanced feature
• Minimum 2 week discussion period
• 2 week voting period
• Everyone with a PHP VCS account can vote (1000+ people!)
PHP 8 is 30+ accepted RFCs from over 15 people
Many more which have been declined
See them all at: https://wiki.php.net/rfc
4
QoL
Trailing commas in parameter list and closure use list
$longArgs_longVars = function (
$longArgument,
$longerArgument ,
$muchLongerArgument ,
) use (
$longVar1,
$longerVar2,
$muchLongerVar3 ,
) {
// body
};
5
Allowed!
QoL
::class notation on variables
$class = $object::class;
// Identical to
$class = get_class($object);
DateTimeInterface::createFromInterface
public static function createFromInterface (DateTimeInterface $object): DateTime
public static function createFromInterface (DateTimeInterface $object): DateTimeImmutable
6
QoL
Non-capturing catches
try {
doStuffWhichMightThrow ();
} catch (Exception) { // The intention is clear: exception details are irrelevant
echo "Some error message" ;
}
Null safe operator ?->
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
// do something with $country
7
$country =
$session?->user?->getAddress()?-> country;
// do something with $country
Becomes
QoL
JSON Extension always enabled
Stable sorting
Functions:
function str_contains(string $haystack, string $needle): bool {}
function str_starts_with (string $haystack, string $needle): bool {}
function str_ends_with(string $haystack, string $needle): bool {}
function fdiv(float $dividend, float $divisor): float {} // IEEE 754 semantics
8
New features
Just In Time Compiler (JIT)
• Compiles PHP code into machine language for x86 (Intel/AMD)
• Performance gain for CPU bounded (i.e. math)
• ⚠ May lead to performance loss on more “traditional” code
Part of OpCache:
• opcache.jit=on
• opache.jit_buffer_size=128M
10
Match
Similar to the switch statement
Major differences:
• Exhaustive, if value not matched throws UnhandledMatchError
• Uses strict comparison (===)
• No fallthrough
• Returns a value
• Match condition can be any expression
• Match statement must be a single expression (like arrow functions)
11
Match: a simple example
PHP 7.x
switch (1) {
case 0:
$result = 'Foo';
break;
case 1:
$result = 'Bar';
break;
case 2:
case 3:
$result = 'Baz';
break;
default:
$result = 'FooBar';
break;
}
echo $result;
//> Bar
PHP 8.0
echo match (1) {
0 => 'Foo',
1 => 'Bar',
2, 3 => 'Baz',
default => 'FooBar',
};
//> Bar
12
Match: complex example
echo match ($x) {
3, 5 => throw new Exception('Cannot be 3 or 5'),
foo() => "foo",
$this->bar() => "bar() check", // bar() isn't called if foo() matched with $x
};
If nothing is matched a UnhandledMatchError is thrown
13
Possible because throw is an
expression in PHP 8
Constructor promotion
PHP 7.x
class Point {
public float $x;
public float $y;
public float $z;
public function __construct(
float $x = 0.0,
float $y = 0.0,
float $z = 0.0,
) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
PHP 8.0
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) { }
}
14
Attributes: syntax TBD
Using doc comments
/** @Entity */
class User {
/**
* @Id
* @Column(type="integer")
* @GenerateValue
*/
private $id;
}
Attributes with Rust-like syntax
use DoctrineORMAttributes as ORM;
#[ORMEntity]
class User {
#[ORMId]
#[ORMColumn("integer")]
#[ORMGenerateValue]
private $id;
}
15
Class name
Constructor argument
Attributes: syntax TBD
Hack-style
use DoctrineORMAttributes as ORM;
<<ORMEntity>>
class User {
<<ORMId>>
<<ORMColumn("integer")>>
<<ORMGenerateValue>>
private $id;
}
@@-style
use DoctrineORMAttributes as ORM;
@@ORMEntity
class User {
@@ORMId
@@ORMColumn("integer")
@@ORMGenerateValue
private $id;
}
16
Attributes
$rc = new ReflectionClass (User::class);
foreach ($rc->getAttributes() as $attr) {
var_dump($attr->getName());
// => "DoctrineORMAttributesEntity"
var_dump($attr->getArguments());
// => []
var_dump($attr->newInstance());
// object(DoctrineORMAttributesEntity) ...
}
17
Attribute validation happens here
Named arguments
// Using positional arguments:
array_fill(0, 100, 50);
// Using named arguments:
array_fill(start_index: 0, num: 100, value: 50);
array_fill(value: 50, num: 100, start_index: 0);
// Skip default values
htmlspecialchars ($string, double_encode: false);
// Same as
htmlspecialchars ($string, ENT_COMPAT|ENT_HTML401, 'UTF-8', false);
Combined with Constructor promotion: Object Initialization
Named arguments work with attributes
Renaming internal function args and matching the documentation
18
Type System Improvements
Union types, mixed, static return, internal functions, opaque objects
19
Existing union types
• ?Type = Type|null
• iterable = Traversable|array
20
Union types
PHP 7.4
class Number {
/** @var int|float */
private $number;
/** @return float|int */
public function getNumber()
{
return $this->number;
}
/** @param float|int $number */
public function setNumber($number): void
{
$this->number = $number;
}
}
PHP 8.0
class Number {
private float|int $number;
public function getNumber(): float|int
{
return $this->number;
}
public function setNumber(float|int $number): void
{
$this->number = $number;
}
}
21
Union types: exotic types
function shell_exec(string $command): string|false|null {}
22
Common in
standard library
?Type is a shorthand to
Type|null
Union types: handling in weak mode
In weak mode the handling is a bit tricky:
• Type is part of the union
• Scalars are coerced to int, float, string, bool in order of preference
23
Union types: weak and strict mode
declare(strict_types=0);
function test(int|float|bool $arg) {
var_dump($arg);
}
test(45); // int(45)
test(45.8); // float(45.8)
test("45"); // int(45)
test("45.8"); // float(45.8)
test(""); // bool(false)
test("X"); // bool(true)
test([]); // TypeError
declare(strict_types=1);
function test(int|float|bool $arg) {
var_dump($arg);
}
test(45); // int(45)
test(45.8); // float(45.8)
test("45"); // TypeError
test("45.8"); // TypeError
test(""); // TypeError
test("X"); // TypeError
test([]); // TypeError
24
mixed
Distinguish between:
• Type is missing because it wasn’t yet added
• This function accepts/returns anything
25
function var_dump(mixed $value, mixed ...$value): void {}
function unserialize(string $value, array $options = []): mixed {}
mixed
// For argument types:
// No type is equivalent to mixed
class Parent {
public function foo(mixed $arg) {}
}
class Child extends Parent {
public function foo($arg) {}
}
// For return types:
// No type means mixed|void
class Parent {
public function foo(): mixed {}
}
class Child extends Parent {
public function foo() {}
}
26
Forbidden: widening type
Static return type
// Named constructor
class ParentClass {
public static function createFromWhatever($whatever): static {
return new static($whatever);
}
}
class ChildClass extends ParentClass {}
var_dump(ChildClass::createFromWhatever(null));
//object(ChildClass)#1 (0) {
//}
27
Static return type
// Named constructor
class ParentClass {
public static function createFromWhatever($whatever): static {
return new self($whatever);
}
}
class ChildClass extends ParentClass {}
var_dump(ChildClass::createFromWhatever(null));
// TypeError: ParentClass::createFromWhatever(): Return value must be of type
ChildClass, ParentClass returned
28
self vs static
PHP Stubs
PHP stubs specify signature for internal functions/methods
● Becomes the source of truth
● Generates C code function registration with arg info
● Data is now available through Reflection
○ ReflectionFunction::getReturnType();
○ ReflectionParameter::getType();
○ ReflectionParameter::getDefaultValue();
29
PHP Stubs: what it means for you
// Stub
class DateTime implements DateTimeInterface
{
/** @return DateTime */
public function add(DateInterval $interval) { }
}
// Your code
class MyDateTime extends DateTime
{
public function add(DateInterval $interval): DateTime { }
}
30
Now allowed!
A real return type would force all
extending classes to specify it due
to covariance, BC Break!
Resource to object conversion
Why?
• Better type safety
• Better internal support
• Long term: convert all resources to objects
• That’s why there is no ‘resource’ type
• Opaque objects with no API
• Oriented Object API might be added later
31
Resource to object conversion
Notable conversions in PHP 8
• GdImage
• Curl
• ZIP
• Inflate/Deflate from Zlib
• OpenSSL (W.I.P.)
32
Resource to object conversion
PHP 7.x only
$curlHandler = curl_init($url);
if (!is_resource($curlHandler))
{
throw new Exception();
}
PHP 7.x and PHP 8.0
$curlHandler = curl_init($url);
if ($curlHandler !== false) {
throw new Exception();
}
33
This is an Object in case of
success or false on failure
Notable Backward
Compatibility (BC) breaks
Notable BC breaks: error handling
• E_ALL by default
• Might need to adjust error handler and INI settings
• PDO now throws exception by default
• Might break application not using PDO’s throw mode
• Can de disabled by passing: PDO::ERRMODE_SILENT during construction
35
Notable BC breaks: locale
• Default locale is now always the C locale
• Float to string conversions are now locale independent
36
Notable BC breaks: locale
PHP 7.4
setlocale(LC_ALL, "de_DE");
$f = 3.14;
(string) $f; // 3,14
strval($f); // 3,14
print_r($f); // 3,14
var_dump($f); // float(3,14)
debug_zval_dump($f); // float(3,14)
settype($f, "string"); // 3,14
implode([$f]); // 3,14
xmlrpc_encode($f); // 3,14
PHP 8.0
setlocale(LC_ALL, "de_DE");
$f = 3.14;
(string) $f; // 3.14
strval($f); // 3.14
print_r($f); // 3.14
var_dump($f); // float(3.14)
debug_zval_dump($f); // float(3.14)
settype($f, "string"); // 3.14
implode([$f]); // 3.14
xmlrpc_encode($f); // 3.14
37
Notable BC breaks: warning promotion
• Consistent TypeError for internal functions
• This allows the PHP Stubs to exist
• LSP errors always throw (type safety)
• Engine notices and warnings reclassified
• Complete list at: https://wiki.php.net/rfc/engine_warnings
• ValueErrors
• A good attempt to list all affected functions:
https://nahan.fr/nouvelle-erreur-valueerror-dans-php-8/
These only affect programming errors
Handling the error is nonsensical, code needs to be fixed
38
Warning promotion: what benefits?
var_dump(strlen([]));
// Warning: strlen() expects parameter 1 to be string, array given
// NULL
function strlen(string $str): int|null {}
var_dump(array_fill(0, -100, 'foobar'));
// Warning: array_fill(): Number of elements can't be negative
// bool(false)
function array_fill(int $start_key, int $num, mixed $val): array|false {}
39
Warning promotion: what benefits?
var_dump(strlen([]));
// Fatal error: Uncaught TypeError: strlen():
// Argument #1 ($str) must be of type string, array given
function strlen(string $str): int {}
var_dump(array_fill(0, -100, 'foobar'));
// Fatal error: Uncaught ValueError: array_fill():
// Argument #2 ($num) must be greater than or equal to 0
function array_fill(int $start_key, int $num, mixed $val): array {}
40
Warning promotion: what stays the same
var_dump(fopen("does_not_exist.txt", "r'"));
// Warning: fopen(does_not_exist.txt): Failed to open stream: Operation not
permitted
// bool(false)
41
Actually I lied, this is capitalized in PHP 8.0
Numeric strings
Numeric strings: “12”, “15.6”, “5e6”, “ 10”
Leading-numeric strings: “10 ”, “14abc”
Non-numeric strings: “string”
42
Emit E_NOTICE "A non well formed
numeric value encountered"
Leading white-spaces are
considered more numeric
than trailing white-spaces
Numeric strings
Where are numeric strings used?
• Type declarations in weak mode
• is_numeric() function
• String to string comparisons
• Arithmetic and bitwise operations
• Increment/Decrement operation (++ and --)
• String offsets
• NOT array offsets, they have different semantics
43
Numeric strings: bringing back sanity
All details: Saner Numeric Strings RFC:
https://wiki.php.net/rfc/saner-numeric-strings
TL;DR:
• E_NOTICE "A non well formed numeric value encountered" to
E_WARNING "A non-numeric value encountered" with value
preserved
• Other E_WARNINGs promoted to TypeError
44
Numeric strings: bringing back sanity
PHP 7.4
function foo(int $i) { var_dump($i); }
foo(" 123"); // int(123)
foo("123 "); // int(123) with E_NOTICE
foo("123abc"); // int(123) with E_NOTICE
var_dump(123 + "123 ");// int(246) with E_NOTICE
var_dump(123 + "123abc");// int(246) with E_NOTICE
var_dump(123 + "str"); // int(123) with E_WARNING
var_dump("123" == " 123"); // bool(true)
var_dump("123" == "123 "); // bool(false)
var_dump("123" == "123abc"); // bool(false)
PHP 8.0
function foo(int $i) { var_dump($i); }
foo(" 123"); // int(123)
foo("123 "); // int(123)
foo("123abc"); // int(123) with E_WARNING
var_dump(123 + "123 ");
var_dump(123 + "123abc"); // int(246) with E_WARNING
var_dump(123 + "str"); // TypeError
var_dump("123" == " 123"); // bool(true)
var_dump("123" == "123 "); // bool(true)
var_dump("123" == "123abc"); // bool(false)
45
String to number comparisons
$validValues = ["foo", "bar", "baz"];
$value = 0;
var_dump(in_array($value, $validValues));
// bool(true) WTF???
var_dump(0 == "foo");
// bool(true) WTF???
Are always performed numerically
46
String to number comparisons: sanity at last
Comparison | PHP 7.4 | PHP 8.0
----------------------------------
0 == "0" | true | true
0 == "0.0" | true | true
0 == "foo" | true | false
0 == "" | true | false
42 == " 42" | true | true
42 == "42 " | true | true
42 == "42foo" | true | false
47
Other BC breaks:
• Precedence of the concatenation operator .
• Default values before mandatory ones are now deprecated
• final on private methods (except on __construct())
• Treat namespaces names as a single token
• Full list in the UPGRADING document
https://github.com/php/php-src/blob/master/UPGRADING
48
Performance gain
• strtolower() now uses a SIMD implementation when using the "C"
LC_CTYPE locale
• array_slice() on an array without gaps will no longer scan the
whole array to find the start offset. This may significantly reduce
the runtime of the function with large offsets and small lengths
• Removal of old style constructor in PHP 8.0 seems to yield 20%
performance increase in WordPress
https://idk.dev/improving-performance-of-php-for-arm64-and-im
pact-on-amazon-ec2-m6g-instances/
49
Micro-optimizations
DISCLAIMER:
I have not tested the performance of the
following changes, these are just tidbits I
remember which have been committed
to php-src
50
Micro-optimizations
• Optimize $x === null into is_null($x)
https://github.com/php/php-src/commit/36afe4e39ec724eab19c54c1492db030721d0ec1
• Yes is_null() generated a “better” TYPE_CHECK OpCode
• Optimize instanceof checks
https://github.com/php/php-src/commit/c858d17f06179aa25f6e8aa06965313fd519d8e9
https://github.com/php/php-src/commit/c63a0e005abe4b00ab097dc47ca53d20788a6361
• Optimize int === int/float === float
https://github.com/php/php-src/commit/e8525c2f68d938162af055fd843239778a13565d
• Weirdly enough by copying the implementation of ==
• Optimize is_scalar($x) into a TYPE_CHECK opcode
https://github.com/php/php-src/commit/937fa6d9e2f38b5e70a2a510b87ce0be4839a404
• Optimize return type checking
https://github.com/php/php-src/commit/0bac7854779595603e0431521c60744665641734
51
Thank you

More Related Content

What's hot (20)

PDF
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
ODP
OpenGurukul : Language : PHP
Open Gurukul
 
PPTX
002. Introducere in type script
Dmitrii Stoian
 
PPT
Cocoa for Web Developers
georgebrock
 
PDF
Java 8
Robert Bachmann
 
PDF
Patterns for JVM languages JokerConf
Jaroslaw Palka
 
PPTX
Typescript tips & tricks
Ori Calvo
 
PPT
Basic Javascript
Bunlong Van
 
PDF
Crystal presentation in NY
Crystal Language
 
PPT
OOP
thinkphp
 
PDF
Creating Domain Specific Languages in Python
Siddhi
 
PPT
Groovy presentation
Manav Prasad
 
PDF
Java Full Throttle
José Paumard
 
PDF
Advanced PHP Simplified - Sunshine PHP 2018
Mark Niebergall
 
PDF
Kotlin Developer Starter in Android projects
Bartosz Kosarzycki
 
PDF
Clean coding-practices
John Ferguson Smart Limited
 
PPTX
Clojure 7-Languages
Pierre de Lacaze
 
PDF
Crystal internals (part 1)
Ary Borenszweig
 
PDF
Introduction to web programming with JavaScript
T11 Sessions
 
PPTX
Kotlin as a Better Java
Garth Gilmour
 
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
OpenGurukul : Language : PHP
Open Gurukul
 
002. Introducere in type script
Dmitrii Stoian
 
Cocoa for Web Developers
georgebrock
 
Patterns for JVM languages JokerConf
Jaroslaw Palka
 
Typescript tips & tricks
Ori Calvo
 
Basic Javascript
Bunlong Van
 
Crystal presentation in NY
Crystal Language
 
Creating Domain Specific Languages in Python
Siddhi
 
Groovy presentation
Manav Prasad
 
Java Full Throttle
José Paumard
 
Advanced PHP Simplified - Sunshine PHP 2018
Mark Niebergall
 
Kotlin Developer Starter in Android projects
Bartosz Kosarzycki
 
Clean coding-practices
John Ferguson Smart Limited
 
Clojure 7-Languages
Pierre de Lacaze
 
Crystal internals (part 1)
Ary Borenszweig
 
Introduction to web programming with JavaScript
T11 Sessions
 
Kotlin as a Better Java
Garth Gilmour
 

Similar to PHP 8: Process & Fixing Insanity (20)

PDF
What's new in PHP 8.0?
Nikita Popov
 
PDF
Living With Legacy Code
Rowan Merewood
 
PPTX
Introducing PHP Latest Updates
Iftekhar Eather
 
PDF
PHP 7.0 new features (and new interpreter)
Andrea Telatin
 
PDF
Drupaljam xl 2019 presentation multilingualism makes better programmers
Alexander Varwijk
 
PDF
Giới thiệu PHP 7
ZendVN
 
PPTX
PHP in one presentation
Milad Rahimi
 
PPTX
PHP7 Presentation
David Sanchez
 
PDF
Beauty & the Beast - Java VS TypeScript
Hendrik Ebbers
 
PPT
Php training100%placement-in-mumbai
vibrantuser
 
PDF
Framework agnostic application Will it fit with Symfony? - Symfony live warsa...
Dariusz Drobisz
 
PPTX
Unit 4-6 sem 7 Web Technologies.pptx
prathameshp9922
 
PDF
Building Testable PHP Applications
chartjes
 
PPTX
C++ theory
Shyam Khant
 
ODP
Lambda Chops - Recipes for Simpler, More Expressive Code
Ian Robertson
 
PPTX
Hardcore PHP
Roberto Luis Bisbé
 
PDF
Create your own PHP extension, step by step - phpDay 2012 Verona
Patrick Allaert
 
PDF
Static Analysis of PHP Code – IPC Berlin 2016
Rouven Weßling
 
PDF
Groovy On Trading Desk (2010)
Jonathan Felch
 
What's new in PHP 8.0?
Nikita Popov
 
Living With Legacy Code
Rowan Merewood
 
Introducing PHP Latest Updates
Iftekhar Eather
 
PHP 7.0 new features (and new interpreter)
Andrea Telatin
 
Drupaljam xl 2019 presentation multilingualism makes better programmers
Alexander Varwijk
 
Giới thiệu PHP 7
ZendVN
 
PHP in one presentation
Milad Rahimi
 
PHP7 Presentation
David Sanchez
 
Beauty & the Beast - Java VS TypeScript
Hendrik Ebbers
 
Php training100%placement-in-mumbai
vibrantuser
 
Framework agnostic application Will it fit with Symfony? - Symfony live warsa...
Dariusz Drobisz
 
Unit 4-6 sem 7 Web Technologies.pptx
prathameshp9922
 
Building Testable PHP Applications
chartjes
 
C++ theory
Shyam Khant
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Ian Robertson
 
Hardcore PHP
Roberto Luis Bisbé
 
Create your own PHP extension, step by step - phpDay 2012 Verona
Patrick Allaert
 
Static Analysis of PHP Code – IPC Berlin 2016
Rouven Weßling
 
Groovy On Trading Desk (2010)
Jonathan Felch
 
Ad

Recently uploaded (20)

PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PDF
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
PPTX
Digital Circuits, important subject in CS
contactparinay1
 
PDF
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
PPTX
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
PDF
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
PPT
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
PDF
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
PPTX
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
PDF
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
PDF
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
PPTX
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
PPTX
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
Staying Human in a Machine- Accelerated World
Catalin Jora
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
NASA A Researcher’s Guide to International Space Station : Physical Sciences ...
Dr. PANKAJ DHUSSA
 
PDF
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
PDF
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
Newgen Beyond Frankenstein_Build vs Buy_Digital_version.pdf
darshakparmar
 
Digital Circuits, important subject in CS
contactparinay1
 
“Squinting Vision Pipelines: Detecting and Correcting Errors in Vision Models...
Edge AI and Vision Alliance
 
Agentforce World Tour Toronto '25 - Supercharge MuleSoft Development with Mod...
Alexandra N. Martinez
 
What’s my job again? Slides from Mark Simos talk at 2025 Tampa BSides
Mark Simos
 
Ericsson LTE presentation SEMINAR 2010.ppt
npat3
 
Automating Feature Enrichment and Station Creation in Natural Gas Utility Net...
Safe Software
 
Future Tech Innovations 2025 – A TechLists Insight
TechLists
 
“Voice Interfaces on a Budget: Building Real-time Speech Recognition on Low-c...
Edge AI and Vision Alliance
 
NLJUG Speaker academy 2025 - first session
Bert Jan Schrijver
 
Designing_the_Future_AI_Driven_Product_Experiences_Across_Devices.pptx
presentifyai
 
The Project Compass - GDG on Campus MSIT
dscmsitkol
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
Staying Human in a Machine- Accelerated World
Catalin Jora
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
NASA A Researcher’s Guide to International Space Station : Physical Sciences ...
Dr. PANKAJ DHUSSA
 
UPDF - AI PDF Editor & Converter Key Features
DealFuel
 
LOOPS in C Programming Language - Technology
RishabhDwivedi43
 
Ad

PHP 8: Process & Fixing Insanity

  • 1. POINT TECHNIQUE PHP 8: Process & Fixing Insanity
  • 2. George Peter Banyard ● Mathematics student at Imperial College London ● Currently hired by The Coding Machine to work on php-src, i.e. the PHP Engine ● Find me on Twitter and elsewhere @Girgias ● https://gpb.moe 2 Me at 3AM realising I need a photo for the presentation
  • 3. How I got involved with the PHP project • French translation PHP documentation • PHP internal mailing list • Proposed the “Deprecate PHP Short open tags” PHP RFC • Started tinkering with PHP’s source code • PoC: declare statement which promote warnings to Exceptions • Made multiple patches • php-src VCS karma granted 3
  • 4. PHP a truly open source language: PHP RFCs A PHP RFC is a proposal which affects the PHP engine: Behaviour change, feature addition, deprecations, extensions Anyone can propose a PHP RFC, from QoL to Advanced feature • Minimum 2 week discussion period • 2 week voting period • Everyone with a PHP VCS account can vote (1000+ people!) PHP 8 is 30+ accepted RFCs from over 15 people Many more which have been declined See them all at: https://wiki.php.net/rfc 4
  • 5. QoL Trailing commas in parameter list and closure use list $longArgs_longVars = function ( $longArgument, $longerArgument , $muchLongerArgument , ) use ( $longVar1, $longerVar2, $muchLongerVar3 , ) { // body }; 5 Allowed!
  • 6. QoL ::class notation on variables $class = $object::class; // Identical to $class = get_class($object); DateTimeInterface::createFromInterface public static function createFromInterface (DateTimeInterface $object): DateTime public static function createFromInterface (DateTimeInterface $object): DateTimeImmutable 6
  • 7. QoL Non-capturing catches try { doStuffWhichMightThrow (); } catch (Exception) { // The intention is clear: exception details are irrelevant echo "Some error message" ; } Null safe operator ?-> $country = null; if ($session !== null) { $user = $session->user; if ($user !== null) { $address = $user->getAddress(); if ($address !== null) { $country = $address->country; } } } // do something with $country 7 $country = $session?->user?->getAddress()?-> country; // do something with $country Becomes
  • 8. QoL JSON Extension always enabled Stable sorting Functions: function str_contains(string $haystack, string $needle): bool {} function str_starts_with (string $haystack, string $needle): bool {} function str_ends_with(string $haystack, string $needle): bool {} function fdiv(float $dividend, float $divisor): float {} // IEEE 754 semantics 8
  • 10. Just In Time Compiler (JIT) • Compiles PHP code into machine language for x86 (Intel/AMD) • Performance gain for CPU bounded (i.e. math) • ⚠ May lead to performance loss on more “traditional” code Part of OpCache: • opcache.jit=on • opache.jit_buffer_size=128M 10
  • 11. Match Similar to the switch statement Major differences: • Exhaustive, if value not matched throws UnhandledMatchError • Uses strict comparison (===) • No fallthrough • Returns a value • Match condition can be any expression • Match statement must be a single expression (like arrow functions) 11
  • 12. Match: a simple example PHP 7.x switch (1) { case 0: $result = 'Foo'; break; case 1: $result = 'Bar'; break; case 2: case 3: $result = 'Baz'; break; default: $result = 'FooBar'; break; } echo $result; //> Bar PHP 8.0 echo match (1) { 0 => 'Foo', 1 => 'Bar', 2, 3 => 'Baz', default => 'FooBar', }; //> Bar 12
  • 13. Match: complex example echo match ($x) { 3, 5 => throw new Exception('Cannot be 3 or 5'), foo() => "foo", $this->bar() => "bar() check", // bar() isn't called if foo() matched with $x }; If nothing is matched a UnhandledMatchError is thrown 13 Possible because throw is an expression in PHP 8
  • 14. Constructor promotion PHP 7.x class Point { public float $x; public float $y; public float $z; public function __construct( float $x = 0.0, float $y = 0.0, float $z = 0.0, ) { $this->x = $x; $this->y = $y; $this->z = $z; } } PHP 8.0 class Point { public function __construct( public float $x = 0.0, public float $y = 0.0, public float $z = 0.0, ) { } } 14
  • 15. Attributes: syntax TBD Using doc comments /** @Entity */ class User { /** * @Id * @Column(type="integer") * @GenerateValue */ private $id; } Attributes with Rust-like syntax use DoctrineORMAttributes as ORM; #[ORMEntity] class User { #[ORMId] #[ORMColumn("integer")] #[ORMGenerateValue] private $id; } 15 Class name Constructor argument
  • 16. Attributes: syntax TBD Hack-style use DoctrineORMAttributes as ORM; <<ORMEntity>> class User { <<ORMId>> <<ORMColumn("integer")>> <<ORMGenerateValue>> private $id; } @@-style use DoctrineORMAttributes as ORM; @@ORMEntity class User { @@ORMId @@ORMColumn("integer") @@ORMGenerateValue private $id; } 16
  • 17. Attributes $rc = new ReflectionClass (User::class); foreach ($rc->getAttributes() as $attr) { var_dump($attr->getName()); // => "DoctrineORMAttributesEntity" var_dump($attr->getArguments()); // => [] var_dump($attr->newInstance()); // object(DoctrineORMAttributesEntity) ... } 17 Attribute validation happens here
  • 18. Named arguments // Using positional arguments: array_fill(0, 100, 50); // Using named arguments: array_fill(start_index: 0, num: 100, value: 50); array_fill(value: 50, num: 100, start_index: 0); // Skip default values htmlspecialchars ($string, double_encode: false); // Same as htmlspecialchars ($string, ENT_COMPAT|ENT_HTML401, 'UTF-8', false); Combined with Constructor promotion: Object Initialization Named arguments work with attributes Renaming internal function args and matching the documentation 18
  • 19. Type System Improvements Union types, mixed, static return, internal functions, opaque objects 19
  • 20. Existing union types • ?Type = Type|null • iterable = Traversable|array 20
  • 21. Union types PHP 7.4 class Number { /** @var int|float */ private $number; /** @return float|int */ public function getNumber() { return $this->number; } /** @param float|int $number */ public function setNumber($number): void { $this->number = $number; } } PHP 8.0 class Number { private float|int $number; public function getNumber(): float|int { return $this->number; } public function setNumber(float|int $number): void { $this->number = $number; } } 21
  • 22. Union types: exotic types function shell_exec(string $command): string|false|null {} 22 Common in standard library ?Type is a shorthand to Type|null
  • 23. Union types: handling in weak mode In weak mode the handling is a bit tricky: • Type is part of the union • Scalars are coerced to int, float, string, bool in order of preference 23
  • 24. Union types: weak and strict mode declare(strict_types=0); function test(int|float|bool $arg) { var_dump($arg); } test(45); // int(45) test(45.8); // float(45.8) test("45"); // int(45) test("45.8"); // float(45.8) test(""); // bool(false) test("X"); // bool(true) test([]); // TypeError declare(strict_types=1); function test(int|float|bool $arg) { var_dump($arg); } test(45); // int(45) test(45.8); // float(45.8) test("45"); // TypeError test("45.8"); // TypeError test(""); // TypeError test("X"); // TypeError test([]); // TypeError 24
  • 25. mixed Distinguish between: • Type is missing because it wasn’t yet added • This function accepts/returns anything 25 function var_dump(mixed $value, mixed ...$value): void {} function unserialize(string $value, array $options = []): mixed {}
  • 26. mixed // For argument types: // No type is equivalent to mixed class Parent { public function foo(mixed $arg) {} } class Child extends Parent { public function foo($arg) {} } // For return types: // No type means mixed|void class Parent { public function foo(): mixed {} } class Child extends Parent { public function foo() {} } 26 Forbidden: widening type
  • 27. Static return type // Named constructor class ParentClass { public static function createFromWhatever($whatever): static { return new static($whatever); } } class ChildClass extends ParentClass {} var_dump(ChildClass::createFromWhatever(null)); //object(ChildClass)#1 (0) { //} 27
  • 28. Static return type // Named constructor class ParentClass { public static function createFromWhatever($whatever): static { return new self($whatever); } } class ChildClass extends ParentClass {} var_dump(ChildClass::createFromWhatever(null)); // TypeError: ParentClass::createFromWhatever(): Return value must be of type ChildClass, ParentClass returned 28 self vs static
  • 29. PHP Stubs PHP stubs specify signature for internal functions/methods ● Becomes the source of truth ● Generates C code function registration with arg info ● Data is now available through Reflection ○ ReflectionFunction::getReturnType(); ○ ReflectionParameter::getType(); ○ ReflectionParameter::getDefaultValue(); 29
  • 30. PHP Stubs: what it means for you // Stub class DateTime implements DateTimeInterface { /** @return DateTime */ public function add(DateInterval $interval) { } } // Your code class MyDateTime extends DateTime { public function add(DateInterval $interval): DateTime { } } 30 Now allowed! A real return type would force all extending classes to specify it due to covariance, BC Break!
  • 31. Resource to object conversion Why? • Better type safety • Better internal support • Long term: convert all resources to objects • That’s why there is no ‘resource’ type • Opaque objects with no API • Oriented Object API might be added later 31
  • 32. Resource to object conversion Notable conversions in PHP 8 • GdImage • Curl • ZIP • Inflate/Deflate from Zlib • OpenSSL (W.I.P.) 32
  • 33. Resource to object conversion PHP 7.x only $curlHandler = curl_init($url); if (!is_resource($curlHandler)) { throw new Exception(); } PHP 7.x and PHP 8.0 $curlHandler = curl_init($url); if ($curlHandler !== false) { throw new Exception(); } 33 This is an Object in case of success or false on failure
  • 35. Notable BC breaks: error handling • E_ALL by default • Might need to adjust error handler and INI settings • PDO now throws exception by default • Might break application not using PDO’s throw mode • Can de disabled by passing: PDO::ERRMODE_SILENT during construction 35
  • 36. Notable BC breaks: locale • Default locale is now always the C locale • Float to string conversions are now locale independent 36
  • 37. Notable BC breaks: locale PHP 7.4 setlocale(LC_ALL, "de_DE"); $f = 3.14; (string) $f; // 3,14 strval($f); // 3,14 print_r($f); // 3,14 var_dump($f); // float(3,14) debug_zval_dump($f); // float(3,14) settype($f, "string"); // 3,14 implode([$f]); // 3,14 xmlrpc_encode($f); // 3,14 PHP 8.0 setlocale(LC_ALL, "de_DE"); $f = 3.14; (string) $f; // 3.14 strval($f); // 3.14 print_r($f); // 3.14 var_dump($f); // float(3.14) debug_zval_dump($f); // float(3.14) settype($f, "string"); // 3.14 implode([$f]); // 3.14 xmlrpc_encode($f); // 3.14 37
  • 38. Notable BC breaks: warning promotion • Consistent TypeError for internal functions • This allows the PHP Stubs to exist • LSP errors always throw (type safety) • Engine notices and warnings reclassified • Complete list at: https://wiki.php.net/rfc/engine_warnings • ValueErrors • A good attempt to list all affected functions: https://nahan.fr/nouvelle-erreur-valueerror-dans-php-8/ These only affect programming errors Handling the error is nonsensical, code needs to be fixed 38
  • 39. Warning promotion: what benefits? var_dump(strlen([])); // Warning: strlen() expects parameter 1 to be string, array given // NULL function strlen(string $str): int|null {} var_dump(array_fill(0, -100, 'foobar')); // Warning: array_fill(): Number of elements can't be negative // bool(false) function array_fill(int $start_key, int $num, mixed $val): array|false {} 39
  • 40. Warning promotion: what benefits? var_dump(strlen([])); // Fatal error: Uncaught TypeError: strlen(): // Argument #1 ($str) must be of type string, array given function strlen(string $str): int {} var_dump(array_fill(0, -100, 'foobar')); // Fatal error: Uncaught ValueError: array_fill(): // Argument #2 ($num) must be greater than or equal to 0 function array_fill(int $start_key, int $num, mixed $val): array {} 40
  • 41. Warning promotion: what stays the same var_dump(fopen("does_not_exist.txt", "r'")); // Warning: fopen(does_not_exist.txt): Failed to open stream: Operation not permitted // bool(false) 41 Actually I lied, this is capitalized in PHP 8.0
  • 42. Numeric strings Numeric strings: “12”, “15.6”, “5e6”, “ 10” Leading-numeric strings: “10 ”, “14abc” Non-numeric strings: “string” 42 Emit E_NOTICE "A non well formed numeric value encountered" Leading white-spaces are considered more numeric than trailing white-spaces
  • 43. Numeric strings Where are numeric strings used? • Type declarations in weak mode • is_numeric() function • String to string comparisons • Arithmetic and bitwise operations • Increment/Decrement operation (++ and --) • String offsets • NOT array offsets, they have different semantics 43
  • 44. Numeric strings: bringing back sanity All details: Saner Numeric Strings RFC: https://wiki.php.net/rfc/saner-numeric-strings TL;DR: • E_NOTICE "A non well formed numeric value encountered" to E_WARNING "A non-numeric value encountered" with value preserved • Other E_WARNINGs promoted to TypeError 44
  • 45. Numeric strings: bringing back sanity PHP 7.4 function foo(int $i) { var_dump($i); } foo(" 123"); // int(123) foo("123 "); // int(123) with E_NOTICE foo("123abc"); // int(123) with E_NOTICE var_dump(123 + "123 ");// int(246) with E_NOTICE var_dump(123 + "123abc");// int(246) with E_NOTICE var_dump(123 + "str"); // int(123) with E_WARNING var_dump("123" == " 123"); // bool(true) var_dump("123" == "123 "); // bool(false) var_dump("123" == "123abc"); // bool(false) PHP 8.0 function foo(int $i) { var_dump($i); } foo(" 123"); // int(123) foo("123 "); // int(123) foo("123abc"); // int(123) with E_WARNING var_dump(123 + "123 "); var_dump(123 + "123abc"); // int(246) with E_WARNING var_dump(123 + "str"); // TypeError var_dump("123" == " 123"); // bool(true) var_dump("123" == "123 "); // bool(true) var_dump("123" == "123abc"); // bool(false) 45
  • 46. String to number comparisons $validValues = ["foo", "bar", "baz"]; $value = 0; var_dump(in_array($value, $validValues)); // bool(true) WTF??? var_dump(0 == "foo"); // bool(true) WTF??? Are always performed numerically 46
  • 47. String to number comparisons: sanity at last Comparison | PHP 7.4 | PHP 8.0 ---------------------------------- 0 == "0" | true | true 0 == "0.0" | true | true 0 == "foo" | true | false 0 == "" | true | false 42 == " 42" | true | true 42 == "42 " | true | true 42 == "42foo" | true | false 47
  • 48. Other BC breaks: • Precedence of the concatenation operator . • Default values before mandatory ones are now deprecated • final on private methods (except on __construct()) • Treat namespaces names as a single token • Full list in the UPGRADING document https://github.com/php/php-src/blob/master/UPGRADING 48
  • 49. Performance gain • strtolower() now uses a SIMD implementation when using the "C" LC_CTYPE locale • array_slice() on an array without gaps will no longer scan the whole array to find the start offset. This may significantly reduce the runtime of the function with large offsets and small lengths • Removal of old style constructor in PHP 8.0 seems to yield 20% performance increase in WordPress https://idk.dev/improving-performance-of-php-for-arm64-and-im pact-on-amazon-ec2-m6g-instances/ 49
  • 50. Micro-optimizations DISCLAIMER: I have not tested the performance of the following changes, these are just tidbits I remember which have been committed to php-src 50
  • 51. Micro-optimizations • Optimize $x === null into is_null($x) https://github.com/php/php-src/commit/36afe4e39ec724eab19c54c1492db030721d0ec1 • Yes is_null() generated a “better” TYPE_CHECK OpCode • Optimize instanceof checks https://github.com/php/php-src/commit/c858d17f06179aa25f6e8aa06965313fd519d8e9 https://github.com/php/php-src/commit/c63a0e005abe4b00ab097dc47ca53d20788a6361 • Optimize int === int/float === float https://github.com/php/php-src/commit/e8525c2f68d938162af055fd843239778a13565d • Weirdly enough by copying the implementation of == • Optimize is_scalar($x) into a TYPE_CHECK opcode https://github.com/php/php-src/commit/937fa6d9e2f38b5e70a2a510b87ce0be4839a404 • Optimize return type checking https://github.com/php/php-src/commit/0bac7854779595603e0431521c60744665641734 51