Typed Properties and more: What's coming in PHP 7.4?

Typed Properties and more:
What’s coming in PHP 7.4?
Nikita Popov
Typed Properties and more: What's coming in PHP 7.4?
Release schedule (tentative)
Now
June 6th PHP 7.4 Alpha 1
July 18th PHP 7.4 Beta 1 – Feature freeze
November 21st PHP 7.4 GA Release
Release schedule (tentative)
Now
June 6th PHP 7.4 Alpha 1
July 18th PHP 7.4 Beta 1 – Feature freeze
November 21st PHP 7.4 GA Release
December 2020 PHP 8.0 Release
≈
Overview
●
FFI & Preloading
●
Typed Properties
●
Arrow Functions
●
Covariant Return Types
●
??=
●
Array Spread Operator
●
WeakReference
●
Deprecations
Overview
●
FFI & Preloading => See Dmitry Stogov’s talk!
●
Typed Properties
●
Arrow Functions
●
Covariant Return Types
●
??=
●
Array Spread Operator
●
WeakReference
●
Deprecations
Typed Properties
class User {
public int $id;
public string $name;
}
$user = new User;
$user->id = 42;
$user->name = [];
// Uncaught TypeError: Typed property User::$name
// must be string, array used
Nullability & Initialization
class User {
public int $id; // no null default
public ?string $name; // also no null default (!)
}
Nullability & Initialization
class User {
public int $id; // no null default
public ?string $name; // also no null default (!)
}
$user = new User;
var_dump($user->name);
// Uncaught Error: Typed property User::$name must
// not be accessed before initialization
Nullability & Initialization
class User {
public int $id;
public ?string $name = null;
}
$user = new User;
var_dump($user->name); // NULL
References
class User {
public int $id = 42;
public string $name = "nikic";
}
$user = new User;
$id =& $user->id;
$id = "not an id";
// Uncaught TypeError: Cannot assign string to
// reference held by property User::$id of type int
Poor Man’s Intersection Types
class Test {
public ?Traversable $traversable;
public ?Countable $countable;
public $both = null;
}
$test = new Test;
$test->traversable =& $test->both;
$test->countable =& $test->both;
$test->both = new ArrayIterator;
Poor Man’s Intersection Types
class Test {
public ?Traversable $traversable;
public ?Countable $countable;
public $both = null;
}
$test = new Test;
$test->traversable =& $test->both;
$test->countable =& $test->both;
$test->both = new ArrayIterator;
Effectively ?(Traversable&Countable)
Poor Man’s Intersection Types
class Test {
public ?Traversable $traversable;
public ?Countable $countable;
public $both = null;
}
$test = new Test;
$test->traversable =& $test->both;
$test->countable =& $test->both;
$test->both = new AppendIterator;
// Uncaught TypeError: Cannot assign AppendIterator
// to reference held by property Test::$countable
// of type ?Countable
Poor Man’s Typed Variables
int $i = 0;
$i = "foobar";
Poor Man’s Typed Variables
$i =& int(0);
$i = "foobar";
// Uncaught TypeError: Cannot assign string to
// reference held by property class@anonymous::$prop
// of type int
Poor Man’s Typed Variables
function &int(int $i) {
$obj = new class { public int $prop; };
$obj->prop = $i;
$GLOBALS['huge_memory_leak'][] = $obj;
return $obj->prop;
}
$i =& int(0);
$i = "foobar";
// Uncaught TypeError: Cannot assign string to
// reference held by property class@anonymous::$prop
// of type int
Public Typed Properties?
class User {
private $name;
public function getName(): string {
return $this->name;
}
public function setName(string $name): void {
$this->name = $name;
}
}
Public Typed Properties?
class User {
public string $name;
}
Public Typed Properties?
class User {
public string $name;
}
What if additional validation will be needed?
Future: Property Accessors?
class User {
public string $name {
get;
set($name) {
if (strlen($name) == 0)
throw new Exception(
'Name cannot be empty');
$this->name = $name;
}
};
}
Arrow Functions
array_filter(
$values,
function($v) use($allowedValues) {
return in_array($v, $allowedValues);
}
);
Arrow Functions
array_filter(
$values,
fn($v) => in_array($v, $allowedValues)
);
Arrow Functions
array_filter(
$values,
fn($v) => in_array($v, $allowedValues)
);
Implicit use($allowedValues)
By-Value Binding
$i = 0;
$fn = fn() => $i++;
$fn();
var_dump($i); // int(0)
By-Value Binding
$fns = [];
foreach ([1, 2, 3] as $i) {
$fns[] = fn() => $i;
}
foreach ($fns as $fn) {
echo $fn() . " ";
}
// Prints: 1 2 3
// Not: 3 3 3 (would happen with by-reference)
Syntax – Why fn?
array_filter(
$values,
$v => in_array($v, $allowedValues)
);
ECMAScript syntax
Syntax – Array Ambiguity
$array = [
$a => $a + $b,
$x => $x * $y,
];
Array of arrow functions?
Or just a key-value map?
Syntax – Parsing
// Looks like: Assignment expression
($x = [42] + ["foobar"]) => $x;
// Looks like: Constant lookup + bitwise and
(Type &$x) => $x;
// Looks like: Ternary operator
$a ? ($b): Type => $c : $d;
Syntax – Parsing
// Looks like: Assignment expression
($x = [42] + ["foobar"]) => $x;
// Looks like: Constant lookup + bitwise and
(Type &$x) => $x;
// Looks like: Ternary operator
$a ? ($b): Type => $c : $d;
Need special handling starting at (
But only know it’s an arrow function at =>
Future: Block Syntax
array_filter(
$values,
fn($v) => in_array($v, $allowedValues)
);
Future: Block Syntax
array_filter(
$values,
fn($v) {
// More code...
return in_array($v, $allowedValues);
}
);
Future: Block Syntax
array_filter(
$values,
fn($v) {
// More code...
return in_array($v, $allowedValues);
}
);
Basically like normal closure syntax,
but with implicit variable capture
Covariant Return Types
class A {}
class B extends A {}
class Producer {
public function produce(): A {}
}
class ChildProducer extends Producer {
public function produce(): B {}
}
Sound because $childFactory->create() still instanceof A.
Common Case: Self
class Foo {
public function fluent(): self {}
}
class Bar extends Foo {
public function fluent(): self {}
}
Ordering Issues
class A {
public function method(): B {}
}
class B extends A {
public function method(): C {}
}
class C extends B {}
Ordering Issues
class A {
public function method(): B {}
}
class B extends A {
public function method(): C {}
}
class C extends B {}
Sound, but class C not available when verifying B.
=> No way to reorder classes “correctly”.
=> Will only work with autoloading (for now).
Contravariant Parameter Types
class A {}
class B extends A {}
class Consumer {
public function comsume(B $value) {}
}
class ChildConsumer extends Consumer {
public function comsume(A $value) {}
}
Sound, but rarely useful.
Covariant Parameter Types?
interface Event { ... }
class SpecificEvent implements Event { ... }
interface EventHandler {
public function handle(Event $e);
}
class SpecificEventHandler implements EventHandler {
public function handle(SpecificEvent $e) {}
}
Unsound, will never work!
Future: Generics
interface Event { ... }
class SpecificEvent implements Event { ... }
interface EventHandler<E: Event> {
public function handle(E $e);
}
class SpecificEventHandler
implements EventHandler<SpecificEvent>
{
public function handle(SpecificEvent $e) {}
}
??=
$options["something"] ??= new DefaultObject;
// Roughly equivalent to:
$options["something"] =
$options["something"] ?? new DefaultObject;
??=
$options["something"] ??= new DefaultObject;
Only created if $options["something"] is null
Array spread operator
$array = [3, 4, 5];
return call(1, 2, ...$array); // call(1, 2, 3, 4, 5)
$array = [3, 4, 5];
return [1, 2, ...$array]; // [1, 2, 3, 4, 5]
Array spread operator
$array = new ArrayIterator([1, 2, 3]);
return call(1, 2, ...$array); // call(1, 2, 3, 4, 5)
$array = new ArrayIterator([1, 2, 3]);
return [1, 2, ...$array]; // [1, 2, 3, 4, 5]
Array spread operator
$array = ['y' => 'b', 'z' => 'c'];
return ['x' => 'a', ...$array];
// Uncaught Error: Cannot unpack array with
// string keys
Future: … in destructuring
[$head, ...$tail] = $array;
Future: … in destructuring
$array = [2 => 2, 1 => 1, 0 => 0];
[$head, ...$tail] = $array;
What happens?
WeakReference
$object = new stdClass;
$weakRef = WeakReference::create($object);
var_dump($weakRef->get()); // object(stdClass)#1
unset($object);
var_dump($weakRef->get()); // NULL
WeakReference
$this->data[get_object_id($object)]
= [WeakReference::create($object), $data];
WeakReference
$this->data[get_object_id($object)]
= [WeakReference::create($object), $data];
Will be reused once
object is destroyed
WeakReference
$this->data[get_object_id($object)]
= [WeakReference::create($object), $data];
Will be reused once
object is destroyed
Check $weakRef->get() != null
to know whether the entry is still valid
WeakReference
$this->data[get_object_id($object)]
= [WeakReference::create($object), $data];
Will be reused once
object is destroyed
Check $weakRef->get() != null
to know whether the entry is still valid
Problem: Doesn’t keep $object alive, but keeps dead cache entry
Future: WeakMap
$this->data = new WeakMap();
$this->data[$object] = $data;
Does not keep $object alive; immediately
drops cache entry when object destroyed
Deprecations
Surprisingly few for now…
…there will probably be more.
Ternary Associativity
return $a == 1 ? 'one'
: $a == 2 ? 'two'
: 'other';
// was intended as:
return $a == 1 ? 'one'
: ($a == 2 ? 'two'
: 'other');
// but PHP interprets it as:
return ($a == 1 ? 'one'
: $a == 2) ? 'two'
: 'other';
Ternary Associativity
return $a == 1 ? 'one' // Deprecated in 7.4.
: $a == 2 ? 'two' // Compile error in 8.0.
: 'other';
// was intended as:
return $a == 1 ? 'one'
: ($a == 2 ? 'two'
: 'other');
// but PHP interprets it as:
return ($a == 1 ? 'one'
: $a == 2) ? 'two'
: 'other';
Concatenation Precedence
$a = 1;
$b = 2;
echo "Sum: " . $a+$b;
// was intended as:
echo "Sum: " . ($a+$b);
// but PHP interprets it as:
echo ("Sum: " . $a)+$b;
Concatenation Precedence
$a = 1;
$b = 2;
echo "Sum: " . $a+$b; // Deprecated in PHP 7.4
// was intended as:
echo "Sum: " . ($a+$b); // New behavior in PHP 8.0
// but PHP interprets it as:
echo ("Sum: " . $a)+$b;
Short Open Tags (?)
●
<? deprecated in 7.4, removed in 8.0
●
Only <?php and <?= supported
●
(???) short_open_tag default value from On to
Off in 7.4
Disclaimer: RFC accepted, but much push-back after voting.
3v4l.org
Travis CI
php:
- 7.3
- 7.4snapshot
- nightly
install:
- composer install --ignore-platform-reqs
PHPUnit claims it is not
PHP 8 compatible (it is)PHP 8
Docker
●
https://github.com/devilbox/docker-php-fpm-7.4
●
https://github.com/devilbox/docker-php-fpm-8.0
Thank You!
Questions?
1 of 63

Recommended

Flask – PythonFlask – Python
Flask – PythonMax Claus Nunes
15.9K views30 slides
What Is PhpWhat Is Php
What Is PhpAVC
4.8K views64 slides
Php and MySQLPhp and MySQL
Php and MySQLTiji Thomas
29.5K views83 slides
Introduction to phpIntroduction to php
Introduction to phpAnjan Banda
1.5K views37 slides
Introduction to phpIntroduction to php
Introduction to phpTaha Malampatti
37.7K views32 slides

More Related Content

What's hot(20)

PHP -  Introduction to PHP FundamentalsPHP -  Introduction to PHP Fundamentals
PHP - Introduction to PHP Fundamentals
Vibrant Technologies & Computers3.3K views
Php Using ArraysPhp Using Arrays
Php Using Arrays
mussawir2016.4K views
Introduction To PHPIntroduction To PHP
Introduction To PHP
Shweta A605 views
Introduction to PHPIntroduction to PHP
Introduction to PHP
Collaboration Technologies299 views
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
Vineet Kumar Saini5.3K views
PHP POWERPOINT SLIDESPHP POWERPOINT SLIDES
PHP POWERPOINT SLIDES
Ismail Mukiibi3.9K views
Php mysql pptPhp mysql ppt
Php mysql ppt
Karmatechnologies Pvt. Ltd.70K views
Basics PHPBasics PHP
Basics PHP
Alokin Software Pvt Ltd5.1K views
Php functionsPhp functions
Php functions
JIGAR MAKHIJA286 views
phpphp
php
ajeetjhajharia65.4K views
Lesson 2   php data typesLesson 2   php data types
Lesson 2 php data types
MLG College of Learning, Inc314 views
Java scriptJava script
Java script
Sadeek Mohammed3.7K views
Lesson 6   php if...else...elseif statementsLesson 6   php if...else...elseif statements
Lesson 6 php if...else...elseif statements
MLG College of Learning, Inc256 views
Form Handling using PHPForm Handling using PHP
Form Handling using PHP
Nisa Soomro3.5K views
Control Structures In Php 2Control Structures In Php 2
Control Structures In Php 2
Digital Insights - Digital Marketing Agency2.4K views
Php sessionPhp session
Php session
argusacademy1K views
Php basicsPhp basics
Php basics
Jamshid Hashimi15.2K views
jQuery for beginnersjQuery for beginners
jQuery for beginners
Arulmurugan Rajaraman34.7K views
MYSQL - PHP Database ConnectivityMYSQL - PHP Database Connectivity
MYSQL - PHP Database Connectivity
V.V.Vanniaperumal College for Women2.6K views

Similar to Typed Properties and more: What's coming in PHP 7.4?(20)

JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
Stoyan Stefanov15.6K views
Intermediate PHPIntermediate PHP
Intermediate PHP
Bradley Holt2.5K views
php AND MYSQL _ppt.pdfphp AND MYSQL _ppt.pdf
php AND MYSQL _ppt.pdf
SVN Polytechnic Kalan Sultanpur UP12 views
Hack tutorialHack tutorial
Hack tutorial
Wakana Yoshizawa7.8K views
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
Seri Moth514 views
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3
Nate Abele7K views
Smelling your codeSmelling your code
Smelling your code
Raju Mazumder3.3K views
Mocking DemystifiedMocking Demystified
Mocking Demystified
Marcello Duarte18.1K views
Node.js for PHP developersNode.js for PHP developers
Node.js for PHP developers
Andrew Eddie2.9K views
PHP Tips & TricksPHP Tips & Tricks
PHP Tips & Tricks
Radek Benkel8.4K views
PHP Language TriviaPHP Language Trivia
PHP Language Trivia
Nikita Popov15K views
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
Kang-min Liu8.9K views

More from Nikita Popov(9)

Opaque Pointers Are ComingOpaque Pointers Are Coming
Opaque Pointers Are Coming
Nikita Popov959 views
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
Nikita Popov3.2K views
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
Nikita Popov1.6K views
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
Nikita Popov10K views
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
Nikita Popov6.6K views

Typed Properties and more: What's coming in PHP 7.4?