by Enrico Zimuel
Principal Software Engineer @ Elastic
University of Turin, Dec. 2, 2019
|
PHP 7 introduced param and return types
declare(strict_types=1);
class User
{
protected $name;
public function setName(string $name): void
{
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
//...
}
class User
{
public string $name;
}
$user = new User();
$user->name = 42;
// Fatal error: Typed property User::$name must be string
class User
{
public $name;
}
$user = new User();
var_dump($user->name);
// NULL
class User
{
public string $name;
}
$user = new User();
echo $user->name;
// Fatal error: Typed property User::$name must not
// be accessed before initialization
class User
{
public ?string $name = null;
}
$user = new User();
var_dump($user->name);
// NULL
Tony Hoare introduced Null references in ALGOL back in 1965 "simply because it was so easy to implement".
The idea was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler.
class User
{
public string $name = "foo";
}
$user = new User();
$name =& $user->name;
$name = 42;
// Fatal error: Cannot assign int to reference held
// by property User::$name of type string
class Example {
public int $scalarType;
protected ClassName $classType;
private ?ClassName $nullableClassType;
public static iterable $staticProp;
public string $str = "foo";
public ?string $nullableStr = null;
public float $x, $y;
}
It supports all types, except void and callable
Class Test {
public callable $cb;
public function __construct() {
// $this->cb is callable here
$this->cb = [$this, 'foo'];
}
private function foo() {}
}
$obj = new Test;
// $obj->cb is NOT callable here!!!
($obj->cb)();
declare(strict_types=0);
class Test {
public int $val;
}
$test = new Test;
$test->val = "42";
var_dump($test->val); // int(42)
$test->val = "42.7";
var_dump($test->val); // int(42)
$test->val = "test";
// Fatal error: Uncaught TypeError:
// Typed property Test::$val must be int
Property types (public and protected) are invariant
class A {
private bool $a;
private string $b;
protected int $c;
public ?int $d;
}
class B extends A {
public string $a; // ok, A::$a is private
private bool $b; // ok, A::$b is private
protected ?int $c; // ILLEGAL
public int $d; // ILLEGAL
}
"On server startup – before any application code is run – we may load a certain set of PHP files into memory – and make their contents “permanently available” to all subsequent requests that will be served by that server. All the functions and classes defined in these files will be available to requests out of the box, exactly like internal entities."
Dmitry Stogov
$composer = require '/path/to/vendor/composer/autoload_classmap.php';
$preload = '/tmp/preload.php';
$content = "<?php\n";
foreach (array_unique($composer) as $class => $file) {
$content .= sprintf("opcache_compile_file('%s');\n", $file);
}
file_put_contents($preload, $content);
opcache.preload="/tmp/preload.php"
I found this benchmark of Ben Morel:
Strategy | Req/sec |
No prealoding | 596 rq/s |
Preload hot classes | 695 rq/s |
Preload everything | 675 rq/s |
+13% when preloading everything
+16% when preloading "hot" classes
$ffi = FFI::cdef(
"int printf(const char *format, ...);",
"libc.so.6"
);
// esegue la funzione C printf()
$ffi->printf("Hello %s!\n", "world");
$ffi = FFI::cdef("
typedef unsigned int time_t;
typedef unsigned int suseconds_t;
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
int gettimeofday(struct timeval *tv, struct timezone *tz);
", "libc.so.6");
$tv = $ffi->new("struct timeval");
$tz = $ffi->new("struct timezone");
$ffi->gettimeofday(FFI::addr($tv), FFI::addr($tz));
var_dump($tv);
var_dump($tz);
/*
object(FFI\CData:struct timeval)#2 (2) {
["tv_sec"]=>
int(1568643992)
["tv_usec"]=>
int(0)
}
object(FFI\CData:struct timezone)#3 (2) {
["tz_minuteswest"]=>
int(0)
["tz_dsttime"]=>
int(0)
}
*/
Dmitry Stogov has developed an experimental binding of TensorFlow library in PHP using FFI:
dstogov/php-tensorflow
$this->request->data['comments']['user_id'] =
$this->request->data['comments']['user_id'] ?? 'value';
// with null coalescing assignment
$this->request->data['comments']['user_id'] ??= 'value';
$y = 1;
$fn1 = function ($x) use ($y) {
return $x + $y;
};
echo $fn1(3); // 4
// with arrow functions
$fn2 = fn($x) => $x + $y;
echo $fn2(3); // 4
fn(parameter_list) => expr
NOTE: fn is a reserved word in PHP 7.4
$x = ['c', 'd'];
$y = ['a', 'b', ...$x];
var_dump($y); // ['a', 'b', 'c', 'd']
It also works on Traversable objects
$arr1 = [...new ArrayIterator(['a', 'b', 'c'])];
var_dump($arr1); // ['a', 'b', 'c']
$arr2 = new ArrayIterator(['a', 'b']);
$arr3 = new ArrayIterator(['c']);
$arr4 = [...$arr2, ...$arr3 ];
var_dump($arr4); // ['a', 'b', 'c']
PHP ver. | Exec. time (in sec) |
7.1.32 | 0.455 |
7.2.22 | 0.437 |
7.3.9 | 0.373 |
7.4RC1 | 0.334 |
Follow me: @ezimuel
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.