php 7 evolution
Post on 16-Feb-2017
522 Views
Preview:
TRANSCRIPT
@felixgomezlopez
PHP 7 Evolution
@felixgomezlopez
@felixgomezlopez
@felixgomezlopez
0. CHRONOLOGY
@felixgomezlopez
1995-2016 (21 YEARS OF PHP)
Version Release date
Personal Homepage Tools (PHP Tools) Version 1.0
PHP/FI 2
June 8th 1995
November 1997
PHP 3 June 1998
PHP 4 May 2000
PHP 5 July 2004
PHP 5.3/5.4 June 2009
PHP 7 December 2015
= PHP 6 - UNICODE
@felixgomezlopez
¿QUÉ FUE DE PHP6?
https://wiki.php.net/rfc/php6
● Intento fallido de salto de versión
● Iniciado en 2005 y finalizado en 2010
● Se integraron features en PHP 5.3 y 5.4
● Después de descartar UTF-16, intl se distribuyó como parte de PHP 5.3
y exponía las funcionalidades de la librería ICU.
● Se llegaron a publicar libros y se dieron charlas, pero nunca vió la luz
@felixgomezlopez
CRONOLOGíA PHP (21 AÑOS)
Versión Tiempo de vida
Personal Homepage Tools (PHP Tools) Version 1.0
PHP/FI 2
~ 2 años
~ 1 año
PHP 3 ~ 2 años
PHP 4 ~ 2 años
PHP 5 ~ 11 años
@felixgomezlopez
VERSIONES ACTUALES
http://www.php.net/supported-versions.php
@felixgomezlopez
PORCENTAJES DE USO
http://w3techs.com/technologies/details/pl-php/all/all
@felixgomezlopez@felixgomezlopez
PHP 7
@felixgomezlopez
¿SOBRE QUÉ SE BASA?
https://drive.google.com/file/d/0B3UKOMH_4lgBUTdjUGxIZ3l1Ukk/view?usp=sharing
● Refactoring
● Objetivo principal: Alcanzar un nuevo nivel de rendimiento y
hacerlo base para futuras releases
● Separado de la rama principal de PHP en Enero de 2014
● Sin cambios para el usuario (solo cambios internos)
@felixgomezlopez
ESTADO DE PHPNG
● Llevó 2 semanas compilar el core
● En dos semanas más podía correr bench.php
● Después de mes y medio compatible con WordPress
● Se abre el proyecto 1 mes después (principios de mayo)
● Se mergea a master como base para PHP7 en Agosto de 2014
@felixgomezlopez
ESTADO DE PHPNG EN OCTUBE 2014
@felixgomezlopez
ESTADO DE PHPNG EN OCTUBE 2014
@felixgomezlopez
@felixgomezlopez
@felixgomezlopez
http://es.slideshare.net/nikita_ppv/php-7-what-changed-internally-php-barcelona-2015
@felixgomezlopez
USERLAND
PHP 7 CHANGES
INTERNALS
@felixgomezlopez@felixgomezlopez
PHP 7: INTERNALS
@felixgomezlopez
INTERNALS
CÓDIGO PHP SCANNING
(a.k.a. LEXING)
<?php
echo "Hello World";$a = 1 + 1;echo $a;
<?php
$code = <<<'PHPCODE'<?phpecho "Hello World";$a = 1 + 1;echo $a;PHPCODE;
print_r(token_get_all($code));
TOKENS
@felixgomezlopez
Array( [0] => Array ( [0] => 376 [1] => <?php [2] => 1 )
[1] => Array ( [0] => 312 [1] => $a [2] => 2 )
[2] => Array ( [0] => 379 [1] => [2] => 2 )
[3] => =
[4] => Array ( [0] => 379 [1] => [2] => 2 )
[5] => Array ( [0] => 318 [1] => "Hello World" [2] => 2 )
[6] => ; [7] => Array ( [0] => 379 [1] => [2] => 2 )
[8] => Array ( [0] => 319 [1] => echo [2] => 3 )
[9] => Array ( [0] => 379 [1] => [2] => 3 )
[10] => Array ( [0] => 312 [1] => $a [2] => 3 )
[11] => ;)
SCANNING (a.k.a LEXING)
@felixgomezlopez
<?php
$code = <<<'CODE'<?php$a = "Hello World";echo $a;CODE;
$tokens = token_get_all($code);
array_walk($tokens, function (&$token) {
if (count($token) > 1) { $token[0] = token_name((int) $token[0]); } });
print_r($tokens);
SCANNING (a.k.a LEXING)
@felixgomezlopez
Array( [0] => Array ( [0] => T_OPEN_TAG [1] => <?php [2] => 1 )
[1] => Array ( [0] => T_VARIABLE [1] => $a [2] => 2 )
[2] => Array ( [0] => T_WHITESPACE [1] => [2] => 2 )
[3] => =
[4] => Array ( [0] => T_WHITESPACE [1] => [2] => 2 )
[5] => Array ( [0] => T_CONSTANT_ENCAPSED_STRING [1] => "Hello World" [2] => 2 )
[6] => ; [7] => Array ( [0] => T_WHITESPACE [1] => [2] => 2 )
http://php.net/manual/en/tokens.php
@felixgomezlopez
CÓDIGO PHP SCANNING
(a.k.a. LEXING)
PARSINGTokens
● Elimina espacios en blanco ● Se queda con expresiones irreducibles del
conjunto de tokens
PARSING (PHP 5)
<?php
echo "Hello World";$a = 1 + 1;echo $a;
1. mostrar string2. sumar dos números3. guardar el resultado de la operación anterior en una
variable4. mostrar la variable
@felixgomezlopez
COMPILING (PHP 5)
CÓDIGO PHP SCANNING
(a.k.a. LEXING)
TokensOPCODES
● ZEND_ECHO 'Hello World'
● ZEND_ADD ~0 1 1
● ZEND_ASSIGN !0 ~0
● ZEND_ECHO !0
<?php
echo "Hello World";$a = 1 + 1;echo $a;
PARSINGmatching and opcode generation
@felixgomezlopez
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = -2
filename: /in/KVrR3
function name: (null)
number of ops: 4
compiled vars: !0 = $a
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
3 0 E > ECHO 'Hello+World'
4 1 ASSIGN !0, 2
5 2 ECHO !0
3 > RETURN 1
Generated using Vulcan Logic Dumper, using php 7.0.0
OPCODE REPRESENTATION EXAMPLE (PHP 7)
<?php
echo "Hello World";$a = 1 + 1;echo $a;
https://github.com/php/php-src/blob/master/Zend/zend_vm_def.h
@felixgomezlopez
CÓDIGO PHP SCANNING
(a.k.a. LEXING)
OPCODESPARSING AST
Tokens
Tokens
PHP 7: ABSTRACT SYNTAX TREE (AST)
https://es.wikipedia.org/wiki/%C3%81rbol_de_sintaxis_abstracta
@felixgomezlopez
PHP 7: VENTAJAS ABSTRACT SYNTAX TREE (AST)
● Permite añadir funcionalidades más fácilmente
● Consistencia en la interpretación
● Mejora en rendimiento
● Permite que el lenguaje sea más flexible
Posibilidades “SCI-FI”
● Posibilidad de conversión inversa por análisis de AST->SOURCE CODE
● Posibilidad de generar AST externo para ser compilado por Zend
Engine 3
@felixgomezlopez
[$x*2 foreach(range(0,10) as $x)]
http://twig.sensiolabs.org/doc/internals.html
[x*2 for x in range(10)]
PHP 7: POSIBILITIES ABSTRACT SYNTAX TREE (AST)
http://docs.hylang.org/en/latest/
@felixgomezlopez
PHP 7: USERLANDNEWS
@felixgomezlopez
ENGINE EXCEPTIONS
https://wiki.php.net/rfc/throwable-interfacehttps://wiki.php.net/rfc/engine_exceptions_for_php7
@felixgomezlopez
NEW EXCEPTION TREE
Exception
LogicException
RangeException
Throwable
Error
ParseError
TypeError
@felixgomezlopez
EXCEPTIONS (NEW ERROR INTERCEPTION)
<?php
function add(int $left, int $right) { return $left + $right;}
try { echo add('left', 'right');} catch (Exception $e) { echo "Captured exception";} catch (Error $e) { // TypeError echo $e->getMessage();}
@felixgomezlopez
EXCEPTIONS
<?php
$a=6;
$a->grow();
PHP5
PHP7
PHP Fatal error: Call to a member function grow() on integer
Fatal error: Uncaught Error: Call to a member function grow() on integer
@felixgomezlopez
<?php
try {
$a = 6;
$a->grow();
} catch (Error $e) {
echo $e->getMessage();
}
EXCEPTIONS
Call to a member function grow() on integer
@felixgomezlopez
EXCEPTIONS
<?php
try {
foo();
} catch (Error $e) {
var_dump($e);
}
object(Error)#1 (7) {
["message":protected]=>
string(43) "Call to a member function grow() on
integer"
["string":"Error":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(27) "/home/vagrant/Lab/index.php"
["line":protected]=>
int(5)
["trace":"Error":private]=>
array(0) {
}
["previous":"Error":private]=>
NULL
}
@felixgomezlopez
RETURN TYPE DECLARATIONS https://wiki.php.net/rfc/return_types
@felixgomezlopez
RETURN TYPE DECLARATIONS (TIPOS DE RETORNO)
function foo(): array {
return [];
}
@felixgomezlopez
RETURN TYPE DECLARATIONS (TIPOS DE RETORNO)
<?php
// Returned type does not match the type declaration
function get_config(): array {
return 42;
}
get_config();
Fatal error: Uncaught TypeError: Return value of get_config() must be of the
type array, integer returned in /home/vagrant/Lab/index.php:6
Stack trace:
#0 /home/vagrant/Lab/index.php(9): get_config()
#1 {main}
thrown in /home/vagrant/Lab/index.php on line 6
@felixgomezlopez
SCALAR TYPE DECLARATIONS
https://wiki.php.net/rfc/scalar_type_hints_v5
@felixgomezlopez
SCALAR TYPE DECLARATIONS
<?php
declare(strict_types=1);
function add(float $a, float $b): float {
return $a + $b;
}
add(1, 2); // float(3)
int a float es la única conversión permitida
@felixgomezlopez
SCALAR TYPE DECLARATIONS
<?php
function add(int $val1, int $val2) {
return $val1 + $val2;
}
$a = add("2", "2");
var_dump($a); // int(4)
@felixgomezlopez
SCALAR TYPE DECLARATIONS
<?php
declare(strict_types = 1);
function add(int $val1, int $val2) {
return $val1 + $val2;
}
$a = add("2", "2");
var_dump($a);
@felixgomezlopez
Fatal error: Uncaught TypeError: Argument 1 passed to add()
must be of the type integer, string given, called in
/home/vagrant/Lab/index.php on line 10 and defined in
/home/vagrant/Lab/index.php:5
Stack trace:
#0 /home/vagrant/Lab/index.php(10): add('2', '2')
#1 {main}
thrown in /home/vagrant/Lab/index.php on line 5
SCALAR TYPE DECLARATIONS
@felixgomezlopez
<?php
declare(strict_types = 1);
function foo() : bool {
return 1;
}
$a = foo();
var_dump($a);
SCALAR TYPE DECLARATIONS
@felixgomezlopez
SCALAR TYPE DECLARATIONS
Fatal error: Uncaught TypeError: Return value of foo() must
be of the type boolean, integer returned in
/home/vagrant/Lab/index.php:5
Stack trace:
#0 /home/vagrant/Lab/index.php(8): foo()
#1 {main}
thrown in /home/vagrant/Lab/index.php on line 5
@felixgomezlopez
NULL COALESCE OPERATOR(OPERADOR DE FUSIÓN DE NULL)
https://wiki.php.net/rfc/isset_ternary
@felixgomezlopez
NULL COALESCE OPERATOR - ANTERIOR ALTERNATIVA
if (isset($_GET['user'])) {
$user = $_GET['user'];
} else {
$user = 'nobody';
}
$user = isset($_GET['user']) ? $_GET['user'] : 'nobody';
@felixgomezlopez
NULL COALESCE OPERATOR (FUSIÓN DE NULL)
$x = ['foo' => 'a', 'bar' => 'b'];
var_dump($x['baz'] ?? $x['bar'] ?? $x['foo'] ?? 'none');
// string(1) "b"
$user = $_GET['user'] ?? 'nobody';
$user = isset($_GET['user']) ? $_GET['user'] : 'nobody';
@felixgomezlopez
SPACESHIP (a.k.a. COMBINED COMPARISON) OPERATOR
https://wiki.php.net/rfc/combined-comparison-operator
@felixgomezlopez
SPACESHIP OPERATOR
// Integersecho 1 <=> 1; // 0echo 1 <=> 2; // -1echo 2 <=> 1; // 1
// Floatsecho 1.5 <=> 1.5; // 0echo 1.5 <=> 2.5; // -1echo 2.5 <=> 1.5; // 1
// Stringsecho "a" <=> "a"; // 0echo "a" <=> "b"; // -1echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1echo "zz" <=> "aa"; // 1
// Arraysecho [] <=> []; // 0echo [1, 2, 3] <=> [1, 2, 3]; // 0echo [1, 2, 3] <=> []; // 1echo [1, 2, 3] <=> [1, 2, 1]; // 1echo [1, 2, 3] <=> [1, 2, 4]; // -1
// Objects// Only values are compared$a = (object) ["a" => "b"];$b = (object) ["b" => "b"];echo $a <=> $b; // 0
@felixgomezlopez
ANONYMOUS CLASSEShttps://wiki.php.net/rfc/anonymous_classes
@felixgomezlopez
ANONYMOUS CLASSES
<?php
var_dump(new class($i) { public function __construct($i) { $this->i = $i; }});
<?php
class Foo {}$child = new class extends Foo {};
var_dump($child instanceof Foo); // true
@felixgomezlopez
ANONYMOUS CLASSES
<?php
trait Foo { public function someMethod() { return "bar"; }}
$anonClass = new class { use Foo;};
var_dump($anonClass->someMethod()); // string(3) "bar"
@felixgomezlopez
ANONYMOUS CLASSES
<?php
// PHP 5.xclass MyLogger { public function log($msg) { print_r($msg . "\n"); }}
$pusher->setLogger( new MyLogger() );
// New Hotness$pusher->setLogger(new class { public function log($msg) { print_r($msg . "\n"); }});
@felixgomezlopez
GROUP USE DECLARATIONShttps://wiki.php.net/rfc/group_use_declarations
@felixgomezlopez
GROUP USE DECLARATIONS
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Talk\TalkDb;
use Talk\TalkApi;
use User\UserDb;
use User\UserApi;
use Symfony\Component\Form\{Form, FormError};
use Talk\{TalkDb, TalkApi};
use User\{UserDb, UserApi};
PHP5
PHP7
@felixgomezlopez
UNIFORM VARIABLE SYNTAXhttps://wiki.php.net/rfc/uniform_variable_syntax
@felixgomezlopez
UNIFORM VARIABLE SYNTAX
echo $car->$engine['model'];
// PHP 5
echo $car->{$engine['model']};
// PHP 7
echo {$car->$engine}['model'];
@felixgomezlopez
UNIFORM VARIABLE SYNTAX (CONT.)
// old meaning // new meaning
$$foo['bar']['baz'] ${$foo['bar']['baz']} ($$foo)['bar']['baz']
$foo->$bar['baz'] $foo->{$bar['baz']} ($foo->$bar)['baz']
$foo->$bar['baz']() $foo->{$bar['baz']}() ($foo->$bar)['baz']()
Foo::$bar['baz']() Foo::{$bar['baz']}() (Foo::$bar)['baz']()
Ante la duda paréntesis!
@felixgomezlopez
$foo()['bar']()
[$obj1, $obj2][0]->prop
getStr(){0}
// support nested ::
$foo['bar']::$baz
$foo::$bar::$baz
$foo->bar()::baz()
// support nested ()
foo()()
$foo->bar()()
Foo::bar()()
$foo()()
UNIFORM VARIABLE SYNTAX (CONT.)
@felixgomezlopez
UNIFORM VARIABLE SYNTAX (CONT.)
// support operations on arbitrary (...) expressions
(...)['foo']
(...)->foo
(...)->foo()
(...)::$foo
(...)::foo()
(...)()
// two more practical examples for the last point
(function() { ... })()
($obj->closure)()
@felixgomezlopez
GENERATOR DELEGATION & RETURN VALUEShttps://wiki.php.net/rfc/generator-delegation
@felixgomezlopez
GENERATOR RETURN VALUES
<?php
function foo() { yield 1; yield 2; return 42;}
$bar = foo();foreach ($bar as $element) { echo $element, "\n";}
var_dump($bar->getReturn());
// 1// 2// int(42)
@felixgomezlopez
GENERATOR DELEGATION
<?php
function myGeneratorFunction($foo) { $bar = yield from factoredComputation1($foo); $baz = yield from factoredComputation2($bar);
return $baz;}
function factoredComputation1($foo) { yield $foo + 1; yield $foo + 2;}
function factoredComputation2($bar) { yield $bar + 3; yield $bar + 4;}
foreach (myGeneratorFunction(0) as $v) { echo $v;}
// 1234
@felixgomezlopez
UNICODE SCAPE SYNTAXhttps://wiki.php.net/rfc/unicode_escape
@felixgomezlopez
UNICODE SCAPE SYNTAX
echo "We \u{2665} PHPVigo\n";
We ♥ PHPVigo
echo "\u{1F602}"; // outputs
echo "\u{202E}Reversed text";
// outputs txet desreveR
@felixgomezlopez
REMOVE ALTERNATIVE PHP TAGS
https://wiki.php.net/rfc/remove_alternative_php_tags
@felixgomezlopez
REMOVE ALTERNATIVE PHP TAGS
● <% opening tag
● <%= opening tag with echo
● %> closing tag
● (<script\s+language\s*=\s*(php|"php"|'php')\s*>)i
opening tag
● (</script>)i closing tag
@felixgomezlopez
REMOVE ALTERNATIVE PHP TAGS
<script type="php">
// No funciona
</script>
<%
// Tampoco funciona
%>
@felixgomezlopez
REMOVE DEAD SAPIS AND EXTENSIONS
https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
@felixgomezlopez
REMOVE DEAD SAPIS AND EXTENSIONS
Se eliminan las APIS de servidor no portadas o discontinuadas
● sapi/aolserver● sapi/apache● sapi/apache_hooks● sapi/apache2filter● sapi/caudium● sapi/continuity● sapi/isapi● sapi/milter● sapi/nsapi
● sapi/phttpd● sapi/pi3web● sapi/roxen● sapi/thttpd● sapi/tux● sapi/webjames● ext/mssql● ext/mysql● ext/sybase_ct● ext/ereg
Muchas de ellas se migran a PECL
@felixgomezlopez
REMOVE DEPRECATED FUNCIONALITY
https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
@felixgomezlopez
REMOVE DEPRECATED FUNCIONALITY
Las más notables son:
● Extensión mysql (ext/mysql) -> PDO, mysqli
● Extensión ereg (ext/ereg) -> PCRE
● Asignación de new por referencia $a = & new A;
@felixgomezlopez
“REMOVAL” OF PHP4 CONSTRUCTORS
https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
@felixgomezlopez
<?phpclass Filter{
// PHP 5: filter is a constructor// PHP 7: filter is a constructor and E_DEPRECATED is raised// PHP 8: filter is a normal method and is not a constructor; no E_DEPRECATED is raised
function filter($a) {}}
$filter = new ReflectionMethod('Filter', 'filter');
// PHP 5: bool(true)// PHP 7: bool(true)// PHP 8: bool(false)var_dump($filter->isConstructor());
“REMOVAL” OF PHP4 CONSTRUCTORS
@felixgomezlopez
<?php
// function filter is not used as constructor in PHP 5+
class Filter
{
// PHP 5: E_STRICT "Redefining already defined
constructor"
// PHP 7: No error is raised
// PHP 8: No error is raised
function __construct() {}
function filter($a) {}
}
“REMOVAL” OF PHP4 CONSTRUCTORS
@felixgomezlopez
<?php
// function filter is not used as constructor in PHP 5+
class Filter {
function __construct() {}
// PHP 5.0.0 - 5.2.13, 5.3.0 - 5.3.2: E_STRICT "Redefining
already defined constructor"
// PHP 5.2.14 - 5.2.17, 5.3.3 - 5.6: No error is raised
// PHP 7: No error is raised
// PHP 8: No error is raised
function filter($a) {}
}
REMOVAL OF PHP4 CONSTRUCTORS
@felixgomezlopez
class Filter{ // PHP 5: filter is a constructor // PHP 7: filter is a constructor and E_DEPRECATED is raised // PHP 8: filter is a normal method and is not a constructor; no E_DEPRECATED is raised function filter() {}}
class FilterX extends Filter{
function __construct(){ // PHP 5: Filter::filter is called; no error // PHP 7: Filter::filter is called; no error // PHP 8: "Fatal error: Cannot call constructor" parent::__construct(); } }
new FilterX();
“REMOVAL” OF PHP4 CONSTRUCTORS
@felixgomezlopez
BUGFIX: MULTIPLE DEFAULT CLAUSES IN SWITCH RAISE ERRORhttps://wiki.php.net/rfc/switch.default.multiple
@felixgomezlopez
MULTIPLE DEFAULT CLAUSES IN SWITCH RAISE ERROR
switch ($expr) {
default:
neverExecuted();
break;
default:
executed();
}
@felixgomezlopez
BUGFIX: FOREACH BEHAVIOURhttps://wiki.php.net/rfc/php7_foreach
@felixgomezlopez
BUGFIX FOREACH BEHAVIOUR
<?php
$a = [1,2,3];
foreach($a as $v) { echo $v . " - " . current($a) . "\n";}
// PHP5// 1 - 2// 2 - 2// 3 - 2
// PHP7// 1 - 1// 2 - 1// 3 - 1
@felixgomezlopez
PHP 7: TESTS
@felixgomezlopez
https://hub.docker.com/_/php/
https://github.com/rlerdorf/php7dev
https://3v4l.org/
https://github.com/sstalle/php7cc
TESTS
@felixgomezlopez
QUESTIONS?
THANKS!
@felixgomezlopez
www.opsou.com www.pedrofigueras.com
top related