SlideShare a Scribd company logo
1 of 77
Download to read offline
PHP Language Trivia
Nikita Popov
(nikic)
Object properties
Object properties
Name mangling
class Test {
public $pub = 1;
protected $prot = 2;
private $priv = 3;
}
$obj = new Test;
$arr = (array) $obj;
var_dump($arr);
class Test {
public $pub = 1;
protected $prot = 2;
private $priv = 3;
}
$obj = new Test;
$arr = (array) $obj;
var_dump($arr);
array(3) {
["pub"]=>
int(1)
["*prot"]=>
int(2)
["Testpriv"]=>
int(3)
}
class Test {
public $pub = 1;
protected $prot = 2;
private $priv = 3;
}
$obj = new Test;
$arr = (array) $obj;
var_dump($arr);
var_dump($arr["*prot"]);
// Notice: Undefined index: *prot
array(3) {
["pub"]=>
int(1)
["*prot"]=>
int(2)
["Testpriv"]=>
int(3)
}
class Test {
public $pub = 1;
protected $prot = 2;
private $priv = 3;
}
$obj = new Test;
$arr = (array) $obj;
var_dump($arr);
var_dump($arr["0*0prot"]);
// int(2)
array(3) {
["pub"]=>
int(1)
["0*0prot"]=>
int(2)
["0Test0priv"]=>
int(3)
}
Why name mangling?
class A {
private $prop = 'A';
public function getPropA() { return $this->prop; }
}
class B extends A {
protected $prop = 'B';
public function getPropB() { return $this->prop; }
}
class C extends B {
public $prop = 'C';
public function getPropC() { return $this->prop; }
}
$obj = new C;
var_dump($obj->getPropA()); // string(1) "A"
var_dump($obj->getPropB()); // string(1) "C"
var_dump($obj->getPropC()); // string(1) "C"
class A {
private $prop = 'A';
public function getPropA() { return $this->prop; }
}
class B extends A {
protected $prop = 'B';
public function getPropB() { return $this->prop; }
}
class C extends B {
public $prop = 'C';
public function getPropC() { return $this->prop; }
}
$obj = new C;
var_dump($obj->getPropA()); // string(1) "A"
var_dump($obj->getPropB()); // string(1) "C"
var_dump($obj->getPropC()); // string(1) "C"
Refer to same property
class A {
private $prop = 'A';
public function getPropA() { return $this->prop; }
}
class B extends A {
protected $prop = 'B';
public function getPropB() { return $this->prop; }
}
class C extends B {
public $prop = 'C';
public function getPropC() { return $this->prop; }
}
$obj = new C;
var_dump($obj->getPropA()); // string(1) "A"
var_dump($obj->getPropB()); // string(1) "C"
var_dump($obj->getPropC()); // string(1) "C"
Refer to same property
Private property is independent
class A {
private $prop = 'A';
public function getPropA() { return $this->prop; }
}
class B extends A {
protected $prop = 'B';
public function getPropB() { return $this->prop; }
}
class C extends B {
public $prop = 'C';
public function getPropC() { return $this->prop; }
}
$obj = new C;
var_dump((array) $obj);
Refer to same property
Private property is independent
class A {
private $prop = 'A';
public function getPropA() { return $this->prop; }
}
class B extends A {
protected $prop = 'B';
public function getPropB() { return $this->prop; }
}
class C extends B {
public $prop = 'C';
public function getPropC() { return $this->prop; }
}
$obj = new C;
var_dump((array) $obj);
array(2) {
["0A0prop"]=> string(1) "A"
["prop"]=> string(1) "C"
}
Refer to same property
Private property is independent
Object can have multiple properties
with same name
Name mangling ensures
unique property names
No reason to expose this internal detail …
No reason to expose this internal detail …
… but libraries rely on it now
to access private properties
Object properties
Integer property names
$array = [];
$array[123] = "foo";
$array["123"] = "bar";
var_dump($array);
array(1) {
[123]=>
string(3) "bar"
}
$array = [];
$array[123] = "foo";
$array["123"] = "bar";
var_dump($array);
array(1) {
[123]=>
string(3) "bar"
}
$object = new stdClass;
$object->{123} = "foo";
$object->{"123"} = "bar";
var_dump($object);
object(stdClass)#1 (1) {
["123"]=>
string(3) "bar"
}
$array = [];
$array[123] = "foo";
$array["123"] = "bar";
var_dump($array);
array(1) {
[123]=>
string(3) "bar"
}
$object = new stdClass;
$object->{123} = "foo";
$object->{"123"} = "bar";
var_dump($object);
object(stdClass)#1 (1) {
["123"]=>
string(3) "bar"
}
Normalize to int Normalize to string
$array = [];
$array[123] = "foo";
$array["123"] = "bar";
var_dump($array);
array(1) {
[123]=>
string(3) "bar"
}
$object = new stdClass;
$object->{123} = "foo";
$object->{"123"} = "bar";
var_dump($object);
object(stdClass)#1 (1) {
["123"]=>
string(3) "bar"
}
Normalize to int Normalize to string
What happens if we mix both?
$array = [123 => "foo"];
$object = (object) $array;
var_dump($object->{123});
// Notice: Undefined property: stdClass::$123
var_dump($object->{"123"});
// Notice: Undefined property: stdClass::$123
$array = [123 => "foo"];
$object = (object) $array;
var_dump($object->{123});
// Notice: Undefined property: stdClass::$123
var_dump($object->{"123"});
// Notice: Undefined property: stdClass::$123
var_dump($object);
object(stdClass)#1 (1) {
[123]=>
string(3) "foo"
}
$array = [123 => "foo"];
$object = (object) $array;
var_dump($object->{123});
// Notice: Undefined property: stdClass::$123
var_dump($object->{"123"});
// Notice: Undefined property: stdClass::$123
var_dump($object);
object(stdClass)#1 (1) {
[123]=>
string(3) "foo"
}
Unnormalized integer property name
$object = new stdClass;
$object->{123} = "foo";
$array = (array) $object;
var_dump($array[123]);
// Notice: Undefined offset: 123
var_dump($array["123"]);
// Notice: Undefined offset: 123
$object = new stdClass;
$object->{123} = "foo";
$array = (array) $object;
var_dump($array[123]);
// Notice: Undefined offset: 123
var_dump($array["123"]);
// Notice: Undefined offset: 123
var_dump($array);
array(1) {
["123"]=>
string(3) "foo"
}
Unnormalized integral string key
Fixed in PHP 7.2!
Now integer keys are renormalized
on array->object and object->array casts
$array = [123 => "foo"];
$object = (object) $array;
var_dump($object->{123});
string(3) "foo"
$object = new stdClass;
$object->{123} = "foo";
$array = (array) $object;
var_dump($array[123]);
string(3) "foo"
Object properties
Memory usage
$array = [
"key1" => 1,
"key2" => 2,
// ...
];
class Value {
public $key1;
public $key2;
}
$object = new Value;
$object->key1 = 1;
$object->key2 = 2;
vs.
0
100
200
300
400
500
600
700
800
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Memoryusage(bytes)
Number of properties/keys
Array Array (real) Object Object (real)
0
1
2
3
4
5
6
7
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Arraysize/objectsize
Number of properties/keys
Ratio Ratio (real)
Optimized for different usecases
Objects: Good for fixed set of keys
Arrays: Good for dynamic set of keys
Class entry
Property 0
Property 1
…
Object
Class entry
Property 0
Property 1
…
Object
Contains [property name => property offset] map
Class entry
Properties array
Property 0
Property 1
…
Object
Contains [property name => property offset] map
[property name => property value] map,
used if there are dynamic properties
Class entry
Properties array
Property 0
Property 1
…
Object
Contains [property name => property offset] map
[property name => property value] map,
used if there are dynamic properties
Arrays:
• Store keys (and hashes) explicitly
• Always have power of two size (8, 16, …)
for faster insertions
class Value {
public $x;
}
$obj = new Value;
// $obj size: 56 bytes
foreach ($obj as $k => $v) { }
// $obj size: 432 bytes
class Value {
public $x;
}
$obj = new Value;
// $obj size: 56 bytes
foreach ($obj as $k => $v) { }
// $obj size: 432 bytes
Forces creation of properties array
class Value {
public $x;
}
$obj = new Value;
// $obj size: 56 bytes
foreach ($obj as $k => $v) { }
// $obj size: 432 bytes
Forces creation of properties array
… no way to get rid of it afterwards
// PhpParser node iteration
$names = $node->getSubNodeNames();
foreach ($names as $name) {
$value = $node->$name;
}
// PhpParser node iteration
$names = $node->getSubNodeNames();
foreach ($names as $name) {
$value = $node->$name;
}
Dynamic lookup is slow, but this
avoids large memory usage increase
Object properties
Magic get & set
Direct property access baseline
getProperty() method 2.2x slower
__get() magic 6.0x slower
Direct property access baseline
getProperty() method 2.2x slower
__get() magic 6.0x slower
Userland  internal  userland is slow
class Test {
public function __get($name) {
return $this->$name;
}
}
class Test {
public function __get($name) {
return $this->$name;
}
} Does not recurse into __get()
Will access property directly
class Test {
public function __get($name) {
return $this->$name;
}
} Does not recurse into __get()
Will access property directly
Recursion guards are property name + accessor type specific
class Test {
public function __get($name) {
return $this->$name;
}
} Does not recurse into __get()
Will access property directly
Recursion guards are property name + accessor type specific
In __get("foo"):
• $this->foo will access property
• $this->bar will call __get("bar")
• $this->foo = 42 will call __set("foo", 42)
__get("foo")
__get("bar")
__set("bar", 42)
Recursion guards:
[
"foo" => GET,
"bar" => GET|SET,
]
__get("foo")
__get("bar")
[
"foo" => GET,
"bar" => GET,
]
Recursion guards:
__get("foo")
[
"foo" => GET,
"bar" => 0,
]
Recursion guards:
[
"foo" => 0,
"bar" => 0,
]
Recursion guards:
[
"foo" => 0,
"bar" => 0,
]
Recursion guards:
Never cleaned up
[
"foo" => 0,
"bar" => 0,
]
Recursion guards:
Never cleaned up
PHP 7.1: Recursion guard array not used if
magic accessors used only for one property at a time
Object properties
Unset properties
class Test {
public $prop;
}
$obj = new Test;
unset($obj->prop);
var_dump($obj->prop);
// Notice: Undefined property: Test::$prop
class Test {
public $prop;
}
$obj = new Test;
unset($obj->prop);
var_dump($obj->prop);
// Notice: Undefined property: Test::$prop
Once unset, __get() will be called on access
-> Lazy initialization
class Test {
public $prop;
public function __construct() {
unset($this->prop);
}
public function __get($name) {
echo "__get($name)n";
$this->$name = "init";
return $this->$name;
}
}
$obj = new Test;
var_dump($obj->prop);
var_dump($obj->prop);
class Test {
public $prop;
public function __construct() {
unset($this->prop);
}
public function __get($name) {
echo "__get($name)n";
$this->$name = "init";
return $this->$name;
}
}
$obj = new Test;
var_dump($obj->prop);
var_dump($obj->prop);
Calls __get()
Does not call __get()
Scoped calls
Foo::bar()
Static method call … or is it?
class A {
public function method() {
/* ... */
}
}
class B extends A {
public function method() {
parent::method();
/* ... */
}
}
class A {
public function method() {
/* ... */
}
}
class B extends A {
public function method() {
A::method();
/* ... */
}
}
class A {
public function method() {
/* ... */
}
}
class B extends A {
public function method() {
A::method();
/* ... */
}
}
Scoped instance call:
Call A::method() with current $this
class A {
public function method() { /* ... */ }
}
class B extends A {
public function method() { /* ... */ }
}
class C extends B {
public function method() {
A::method();
/* ... */
}
}
Can also call grandparent method
class A {
public function method() {
echo 'A::method with $this=' . get_class($this) . "n";
}
}
class B /* does not extend A */ {
public function method() {
A::method();
}
}
(new B)->method();
class A {
public function method() {
echo 'A::method with $this=' . get_class($this) . "n";
}
}
class B /* does not extend A */ {
public function method() {
A::method();
}
}
(new B)->method();
// PHP 5: A::method with $this=B (+ deprecation)
class A {
public function method() {
echo 'A::method with $this=' . get_class($this) . "n";
}
}
class B /* does not extend A */ {
public function method() {
A::method();
}
}
(new B)->method();
// PHP 5: A::method with $this=B (+ deprecation)
// PHP 7.0: Undefined variable: this
// PHP 7.1: Error: Using $this when not in object context
class Test {
public function __call($name, $args) {
echo "__call($name)n";
}
public static function __callStatic($name, $args) {
echo "__callStatic($name)n";
}
public function doCall() {
Test::foobar();
}
}
Test::foobar();
(new Test)->doCall();
class Test {
public function __call($name, $args) {
echo "__call($name)n";
}
public static function __callStatic($name, $args) {
echo "__callStatic($name)n";
}
public function doCall() {
Test::foobar();
}
}
Test::foobar(); // __callStatic(foobar)
(new Test)->doCall();
class Test {
public function __call($name, $args) {
echo "__call($name)n";
}
public static function __callStatic($name, $args) {
echo "__callStatic($name)n";
}
public function doCall() {
Test::foobar(); // __call(foobar)
}
}
Test::foobar(); // __callStatic(foobar)
(new Test)->doCall();
Static Closures
class Test {
public function __construct() {
$this->fn = function() {
/* $this can be used here */
};
}
}
class Test {
public function __construct() {
$this->fn = static function() {
/* $this CANNOT be used here */
};
}
}
class Test {
public function __construct() {
$this->fn = static function() {
/* $this CANNOT be used here */
};
}
} Without static:
• Closure references $this
• $this->fn references Closure
class Test {
public function __construct() {
$this->fn = static function() {
/* $this CANNOT be used here */
};
}
} Without static:
• Closure references $this
• $this->fn references Closure
 Cycle causes delayed GC

More Related Content

What's hot

Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Seri Moth
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance TriviaNikita Popov
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsMark Baker
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)David de Boer
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix itRafael Dohms
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Kris Wallsmith
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPatrick Allaert
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsGuilherme Blanco
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHPGuilherme Blanco
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6garux
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...Fwdays
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easyIngvar Stepanyan
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8PrinceGuru MS
 
Functional Pe(a)rls version 2
Functional Pe(a)rls version 2Functional Pe(a)rls version 2
Functional Pe(a)rls version 2osfameron
 
(Parameterized) Roles
(Parameterized) Roles(Parameterized) Roles
(Parameterized) Rolessartak
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 
Exhibition of Atrocity
Exhibition of AtrocityExhibition of Atrocity
Exhibition of AtrocityMichael Pirnat
 

What's hot (20)

Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02Jsphp 110312161301-phpapp02
Jsphp 110312161301-phpapp02
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)Being functional in PHP (DPC 2016)
Being functional in PHP (DPC 2016)
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object Calisthenics
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easy
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8
 
Functional Pe(a)rls version 2
Functional Pe(a)rls version 2Functional Pe(a)rls version 2
Functional Pe(a)rls version 2
 
(Parameterized) Roles
(Parameterized) Roles(Parameterized) Roles
(Parameterized) Roles
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Exhibition of Atrocity
Exhibition of AtrocityExhibition of Atrocity
Exhibition of Atrocity
 

Similar to PHP Language Trivia

Crazy things done on PHP
Crazy things done on PHPCrazy things done on PHP
Crazy things done on PHPTaras Kalapun
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developersStoyan Stefanov
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...James Titcumb
 
Revisiting SOLID Principles
Revisiting  SOLID Principles Revisiting  SOLID Principles
Revisiting SOLID Principles Anis Ahmad
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntityBasuke Suzuki
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
Switching from java to groovy
Switching from java to groovySwitching from java to groovy
Switching from java to groovyPaul Woods
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objectsHusain Dalal
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kirill Rozov
 
Document Classification In PHP
Document Classification In PHPDocument Classification In PHP
Document Classification In PHPIan Barber
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidJordi Gerona
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testingVincent Pradeilles
 

Similar to PHP Language Trivia (20)

Introduction to php oop
Introduction to php oopIntroduction to php oop
Introduction to php oop
 
Crazy things done on PHP
Crazy things done on PHPCrazy things done on PHP
Crazy things done on PHP
 
JavaScript for PHP developers
JavaScript for PHP developersJavaScript for PHP developers
JavaScript for PHP developers
 
Intermediate PHP
Intermediate PHPIntermediate PHP
Intermediate PHP
 
Oops in php
Oops in phpOops in php
Oops in php
 
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
Mirror, mirror on the wall - Building a new PHP reflection library (Nomad PHP...
 
PHP OOP
PHP OOPPHP OOP
PHP OOP
 
Revisiting SOLID Principles
Revisiting  SOLID Principles Revisiting  SOLID Principles
Revisiting SOLID Principles
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Switching from java to groovy
Switching from java to groovySwitching from java to groovy
Switching from java to groovy
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Groovy grails types, operators, objects
Groovy grails types, operators, objectsGroovy grails types, operators, objects
Groovy grails types, operators, objects
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Document Classification In PHP
Document Classification In PHPDocument Classification In PHP
Document Classification In PHP
 
Google Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & AndroidGoogle Guava - Core libraries for Java & Android
Google Guava - Core libraries for Java & Android
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
 

More from Nikita Popov

A whirlwind tour of the LLVM optimizer
A whirlwind tour of the LLVM optimizerA whirlwind tour of the LLVM optimizer
A whirlwind tour of the LLVM optimizerNikita Popov
 
Opaque Pointers Are Coming
Opaque Pointers Are ComingOpaque Pointers Are Coming
Opaque Pointers Are ComingNikita Popov
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?Nikita Popov
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Nikita Popov
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?Nikita Popov
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)Nikita Popov
 

More from Nikita Popov (6)

A whirlwind tour of the LLVM optimizer
A whirlwind tour of the LLVM optimizerA whirlwind tour of the LLVM optimizer
A whirlwind tour of the LLVM optimizer
 
Opaque Pointers Are Coming
Opaque Pointers Are ComingOpaque Pointers Are Coming
Opaque Pointers Are Coming
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8Just-In-Time Compiler in PHP 8
Just-In-Time Compiler in PHP 8
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)PHP 7 – What changed internally? (PHP Barcelona 2015)
PHP 7 – What changed internally? (PHP Barcelona 2015)
 

Recently uploaded

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 

Recently uploaded (20)

Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 

PHP Language Trivia

  • 4. class Test { public $pub = 1; protected $prot = 2; private $priv = 3; } $obj = new Test; $arr = (array) $obj; var_dump($arr);
  • 5. class Test { public $pub = 1; protected $prot = 2; private $priv = 3; } $obj = new Test; $arr = (array) $obj; var_dump($arr); array(3) { ["pub"]=> int(1) ["*prot"]=> int(2) ["Testpriv"]=> int(3) }
  • 6. class Test { public $pub = 1; protected $prot = 2; private $priv = 3; } $obj = new Test; $arr = (array) $obj; var_dump($arr); var_dump($arr["*prot"]); // Notice: Undefined index: *prot array(3) { ["pub"]=> int(1) ["*prot"]=> int(2) ["Testpriv"]=> int(3) }
  • 7. class Test { public $pub = 1; protected $prot = 2; private $priv = 3; } $obj = new Test; $arr = (array) $obj; var_dump($arr); var_dump($arr["0*0prot"]); // int(2) array(3) { ["pub"]=> int(1) ["0*0prot"]=> int(2) ["0Test0priv"]=> int(3) }
  • 9. class A { private $prop = 'A'; public function getPropA() { return $this->prop; } } class B extends A { protected $prop = 'B'; public function getPropB() { return $this->prop; } } class C extends B { public $prop = 'C'; public function getPropC() { return $this->prop; } } $obj = new C; var_dump($obj->getPropA()); // string(1) "A" var_dump($obj->getPropB()); // string(1) "C" var_dump($obj->getPropC()); // string(1) "C"
  • 10. class A { private $prop = 'A'; public function getPropA() { return $this->prop; } } class B extends A { protected $prop = 'B'; public function getPropB() { return $this->prop; } } class C extends B { public $prop = 'C'; public function getPropC() { return $this->prop; } } $obj = new C; var_dump($obj->getPropA()); // string(1) "A" var_dump($obj->getPropB()); // string(1) "C" var_dump($obj->getPropC()); // string(1) "C" Refer to same property
  • 11. class A { private $prop = 'A'; public function getPropA() { return $this->prop; } } class B extends A { protected $prop = 'B'; public function getPropB() { return $this->prop; } } class C extends B { public $prop = 'C'; public function getPropC() { return $this->prop; } } $obj = new C; var_dump($obj->getPropA()); // string(1) "A" var_dump($obj->getPropB()); // string(1) "C" var_dump($obj->getPropC()); // string(1) "C" Refer to same property Private property is independent
  • 12. class A { private $prop = 'A'; public function getPropA() { return $this->prop; } } class B extends A { protected $prop = 'B'; public function getPropB() { return $this->prop; } } class C extends B { public $prop = 'C'; public function getPropC() { return $this->prop; } } $obj = new C; var_dump((array) $obj); Refer to same property Private property is independent
  • 13. class A { private $prop = 'A'; public function getPropA() { return $this->prop; } } class B extends A { protected $prop = 'B'; public function getPropB() { return $this->prop; } } class C extends B { public $prop = 'C'; public function getPropC() { return $this->prop; } } $obj = new C; var_dump((array) $obj); array(2) { ["0A0prop"]=> string(1) "A" ["prop"]=> string(1) "C" } Refer to same property Private property is independent
  • 14. Object can have multiple properties with same name Name mangling ensures unique property names
  • 15. No reason to expose this internal detail …
  • 16. No reason to expose this internal detail … … but libraries rely on it now to access private properties
  • 18. $array = []; $array[123] = "foo"; $array["123"] = "bar"; var_dump($array); array(1) { [123]=> string(3) "bar" }
  • 19. $array = []; $array[123] = "foo"; $array["123"] = "bar"; var_dump($array); array(1) { [123]=> string(3) "bar" } $object = new stdClass; $object->{123} = "foo"; $object->{"123"} = "bar"; var_dump($object); object(stdClass)#1 (1) { ["123"]=> string(3) "bar" }
  • 20. $array = []; $array[123] = "foo"; $array["123"] = "bar"; var_dump($array); array(1) { [123]=> string(3) "bar" } $object = new stdClass; $object->{123} = "foo"; $object->{"123"} = "bar"; var_dump($object); object(stdClass)#1 (1) { ["123"]=> string(3) "bar" } Normalize to int Normalize to string
  • 21. $array = []; $array[123] = "foo"; $array["123"] = "bar"; var_dump($array); array(1) { [123]=> string(3) "bar" } $object = new stdClass; $object->{123} = "foo"; $object->{"123"} = "bar"; var_dump($object); object(stdClass)#1 (1) { ["123"]=> string(3) "bar" } Normalize to int Normalize to string What happens if we mix both?
  • 22. $array = [123 => "foo"]; $object = (object) $array; var_dump($object->{123}); // Notice: Undefined property: stdClass::$123 var_dump($object->{"123"}); // Notice: Undefined property: stdClass::$123
  • 23. $array = [123 => "foo"]; $object = (object) $array; var_dump($object->{123}); // Notice: Undefined property: stdClass::$123 var_dump($object->{"123"}); // Notice: Undefined property: stdClass::$123 var_dump($object); object(stdClass)#1 (1) { [123]=> string(3) "foo" }
  • 24. $array = [123 => "foo"]; $object = (object) $array; var_dump($object->{123}); // Notice: Undefined property: stdClass::$123 var_dump($object->{"123"}); // Notice: Undefined property: stdClass::$123 var_dump($object); object(stdClass)#1 (1) { [123]=> string(3) "foo" } Unnormalized integer property name
  • 25. $object = new stdClass; $object->{123} = "foo"; $array = (array) $object; var_dump($array[123]); // Notice: Undefined offset: 123 var_dump($array["123"]); // Notice: Undefined offset: 123
  • 26. $object = new stdClass; $object->{123} = "foo"; $array = (array) $object; var_dump($array[123]); // Notice: Undefined offset: 123 var_dump($array["123"]); // Notice: Undefined offset: 123 var_dump($array); array(1) { ["123"]=> string(3) "foo" } Unnormalized integral string key
  • 27. Fixed in PHP 7.2! Now integer keys are renormalized on array->object and object->array casts
  • 28. $array = [123 => "foo"]; $object = (object) $array; var_dump($object->{123}); string(3) "foo" $object = new stdClass; $object->{123} = "foo"; $array = (array) $object; var_dump($array[123]); string(3) "foo"
  • 30. $array = [ "key1" => 1, "key2" => 2, // ... ]; class Value { public $key1; public $key2; } $object = new Value; $object->key1 = 1; $object->key2 = 2; vs.
  • 31. 0 100 200 300 400 500 600 700 800 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Memoryusage(bytes) Number of properties/keys Array Array (real) Object Object (real)
  • 32. 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Arraysize/objectsize Number of properties/keys Ratio Ratio (real)
  • 33. Optimized for different usecases Objects: Good for fixed set of keys Arrays: Good for dynamic set of keys
  • 35. Class entry Property 0 Property 1 … Object Contains [property name => property offset] map
  • 36. Class entry Properties array Property 0 Property 1 … Object Contains [property name => property offset] map [property name => property value] map, used if there are dynamic properties
  • 37. Class entry Properties array Property 0 Property 1 … Object Contains [property name => property offset] map [property name => property value] map, used if there are dynamic properties Arrays: • Store keys (and hashes) explicitly • Always have power of two size (8, 16, …) for faster insertions
  • 38. class Value { public $x; } $obj = new Value; // $obj size: 56 bytes foreach ($obj as $k => $v) { } // $obj size: 432 bytes
  • 39. class Value { public $x; } $obj = new Value; // $obj size: 56 bytes foreach ($obj as $k => $v) { } // $obj size: 432 bytes Forces creation of properties array
  • 40. class Value { public $x; } $obj = new Value; // $obj size: 56 bytes foreach ($obj as $k => $v) { } // $obj size: 432 bytes Forces creation of properties array … no way to get rid of it afterwards
  • 41. // PhpParser node iteration $names = $node->getSubNodeNames(); foreach ($names as $name) { $value = $node->$name; }
  • 42. // PhpParser node iteration $names = $node->getSubNodeNames(); foreach ($names as $name) { $value = $node->$name; } Dynamic lookup is slow, but this avoids large memory usage increase
  • 44. Direct property access baseline getProperty() method 2.2x slower __get() magic 6.0x slower
  • 45. Direct property access baseline getProperty() method 2.2x slower __get() magic 6.0x slower Userland  internal  userland is slow
  • 46. class Test { public function __get($name) { return $this->$name; } }
  • 47. class Test { public function __get($name) { return $this->$name; } } Does not recurse into __get() Will access property directly
  • 48. class Test { public function __get($name) { return $this->$name; } } Does not recurse into __get() Will access property directly Recursion guards are property name + accessor type specific
  • 49. class Test { public function __get($name) { return $this->$name; } } Does not recurse into __get() Will access property directly Recursion guards are property name + accessor type specific In __get("foo"): • $this->foo will access property • $this->bar will call __get("bar") • $this->foo = 42 will call __set("foo", 42)
  • 51. __get("foo") __get("bar") [ "foo" => GET, "bar" => GET, ] Recursion guards:
  • 52. __get("foo") [ "foo" => GET, "bar" => 0, ] Recursion guards:
  • 53. [ "foo" => 0, "bar" => 0, ] Recursion guards:
  • 54. [ "foo" => 0, "bar" => 0, ] Recursion guards: Never cleaned up
  • 55. [ "foo" => 0, "bar" => 0, ] Recursion guards: Never cleaned up PHP 7.1: Recursion guard array not used if magic accessors used only for one property at a time
  • 57. class Test { public $prop; } $obj = new Test; unset($obj->prop); var_dump($obj->prop); // Notice: Undefined property: Test::$prop
  • 58. class Test { public $prop; } $obj = new Test; unset($obj->prop); var_dump($obj->prop); // Notice: Undefined property: Test::$prop Once unset, __get() will be called on access -> Lazy initialization
  • 59. class Test { public $prop; public function __construct() { unset($this->prop); } public function __get($name) { echo "__get($name)n"; $this->$name = "init"; return $this->$name; } } $obj = new Test; var_dump($obj->prop); var_dump($obj->prop);
  • 60. class Test { public $prop; public function __construct() { unset($this->prop); } public function __get($name) { echo "__get($name)n"; $this->$name = "init"; return $this->$name; } } $obj = new Test; var_dump($obj->prop); var_dump($obj->prop); Calls __get() Does not call __get()
  • 63. class A { public function method() { /* ... */ } } class B extends A { public function method() { parent::method(); /* ... */ } }
  • 64. class A { public function method() { /* ... */ } } class B extends A { public function method() { A::method(); /* ... */ } }
  • 65. class A { public function method() { /* ... */ } } class B extends A { public function method() { A::method(); /* ... */ } } Scoped instance call: Call A::method() with current $this
  • 66. class A { public function method() { /* ... */ } } class B extends A { public function method() { /* ... */ } } class C extends B { public function method() { A::method(); /* ... */ } } Can also call grandparent method
  • 67. class A { public function method() { echo 'A::method with $this=' . get_class($this) . "n"; } } class B /* does not extend A */ { public function method() { A::method(); } } (new B)->method();
  • 68. class A { public function method() { echo 'A::method with $this=' . get_class($this) . "n"; } } class B /* does not extend A */ { public function method() { A::method(); } } (new B)->method(); // PHP 5: A::method with $this=B (+ deprecation)
  • 69. class A { public function method() { echo 'A::method with $this=' . get_class($this) . "n"; } } class B /* does not extend A */ { public function method() { A::method(); } } (new B)->method(); // PHP 5: A::method with $this=B (+ deprecation) // PHP 7.0: Undefined variable: this // PHP 7.1: Error: Using $this when not in object context
  • 70. class Test { public function __call($name, $args) { echo "__call($name)n"; } public static function __callStatic($name, $args) { echo "__callStatic($name)n"; } public function doCall() { Test::foobar(); } } Test::foobar(); (new Test)->doCall();
  • 71. class Test { public function __call($name, $args) { echo "__call($name)n"; } public static function __callStatic($name, $args) { echo "__callStatic($name)n"; } public function doCall() { Test::foobar(); } } Test::foobar(); // __callStatic(foobar) (new Test)->doCall();
  • 72. class Test { public function __call($name, $args) { echo "__call($name)n"; } public static function __callStatic($name, $args) { echo "__callStatic($name)n"; } public function doCall() { Test::foobar(); // __call(foobar) } } Test::foobar(); // __callStatic(foobar) (new Test)->doCall();
  • 74. class Test { public function __construct() { $this->fn = function() { /* $this can be used here */ }; } }
  • 75. class Test { public function __construct() { $this->fn = static function() { /* $this CANNOT be used here */ }; } }
  • 76. class Test { public function __construct() { $this->fn = static function() { /* $this CANNOT be used here */ }; } } Without static: • Closure references $this • $this->fn references Closure
  • 77. class Test { public function __construct() { $this->fn = static function() { /* $this CANNOT be used here */ }; } } Without static: • Closure references $this • $this->fn references Closure  Cycle causes delayed GC