What’s New in PHP 5.3
In PHP 5.3, as in the entire fifth branch of PHP, a new script engine Zend Engine 2.0 is included. Thanks to this, PHP started to run faster by about 15-20%.
- Wiki: PHP 5.3
?: — shorthand for the ternary operator
With PHP 5.3 it became possible not to write the middle part of the ternary operator. The expression expr1 ?: expr3 returns expr1 if expr1 is not empty, and expr3 otherwise.
Ternary — consisting of three parts, components.
$a = $expr1 ?: $expr3; // equivalent to: $a = $expr1 ? $expr1 : $expr3;
Example of the ternary operator:
// full form if ( $a > 100 ) $result = "Greater"; else $result = "Lower"; // short form $result = $a > 100 ? "Greater" : "Lower";
In the short form there is also a performance nuance, for example:
// full form if ( get_post_meta(25, 'meta_key', 1) ) echo esc_html( get_post_meta(25, 'meta_key', 1) ); else echo 'Meta field does not exist'; // short form echo esc_html( get_post_meta(25, 'meta_key', 1) ?: 'Meta field does not exist' );
In the full form the function get_post_meta() is invoked 2 times. In the short form, once, and if it returns something, the value is immediately passed to the second argument of the ternary operator: no extra variables are needed...
$func = function() use (){ } — anonymous (lambda) functions
Lambda functions are also called “anonymous functions” because they do not have a name.
Lambda functions are closures — a special kind of function defined inside another function and created each time it is executed. Syntactically it looks like a function entirely contained within the body of another function. As far as I understand, any function is a closure of the current context, i.e., the context will not be cleared while the function is running. But if a lambda function is inside a function, it becomes a closure, and if variables from the outer function are passed to it, they will not be cleared until the inner function finishes running...
In earlier versions, anonymous functions were created using the create_function() function.
Example of creating an anonymous function for sorting with usort():
$arr = array(3, 2, 5, 6, 1);
usort( $arr, function($a, $b) {
if ( $a == $b )
return 0;
return ( $a > $b ) ? -1 : 1;
});
Another feature of lambda functions is lexical binding (using variables from the current scope) via the use operator:
$var = 'Hello, Bear!';
$func = function() use ( $var ) { echo $var; };
$func(); //> Hello, Bear!
Variables are passed by value, but you can pass a reference to a variable by using &:
$var = 'Hello, Bear!';
$func = function() use ( & $var ) { $var = $var .' We’re visiting!'; };
$func(); // call
echo $var; //> Hello, Bear! We’re visiting!
method()->var — obtaining an object from a method/function
This is convenient:
$object->method()->method()->method(); $object->method()->method()->member = 5;
In PHP below 5.3 it was written like this:
$tmp = & $object->method(); $tmp = & $tmp->method(); $tmp->method();
<<<'DOC' — NOWDOC support
In PHP 5.3 you can use the analog of HEREDOC, which is called NOWDOC. The feature is that inside it variables remain plain text, as if you wrote them in a single-quoted string: 'text $foo':
$foo = 'Summer'; // HEREDOC was in 5.2 $str = <<<DOC Text with variable '$foo' DOC; echo $str; // Text with variable 'Summer' // NOWDOC appeared in 5.3 $str = '<<<DOC' Text with variable '. $foo .' DOC; echo $str; // Text with variable '. $foo .'
namespace — namespace support
Namespaces are needed to avoid conflicts when function/class/variable/constant names coincide. In short: identical names in different namespaces are different names.
The example below should explain almost everything that is possible in namespaces. For details, head to the official documentation here.
__DIR__ — new magic constant
__DIR__ contains the directory of the current file — the file in which it is used. Returns the full path to the current file without a trailing slash, except for the root directory.
__DIR__ can be replaced with:
dirname(__FILE__)
$class::$foo — dynamic class reference
This provides dynamic access to static methods/properties of a class:
class C {
static $foo = 'foo';
}
$class = 'C';
echo $class::$foo; //> foo
const — keyword for creating constants outside classes
A simple example where everything is clear:
define('SHORTINIT', 'true');
// now you can declare a constant like this:
const SHORTINIT = 'true';
Unlike define(), such constants must be declared in the top-level scope, because they are defined at compile time. This means you cannot declare them inside functions/loops/expressions if or try/catch blocks.
static::method() — late static binding
Static binding of a method/property ties it to the class from which it is called, not the class in which it is defined. See the example:
class A {
static function who() {
echo __CLASS__;
}
static function test1() {
self::who();
}
static function test2() {
static::who(); // late static binding
}
}
class B extends A {
static function who() {
echo __CLASS__;
}
}
echo B::test1(); //> A
echo B::test2(); //> B
echo B::who(); //> B
Read more about late static binding in the documentation: http://php.net/manual/ru/language.oop5.late-static-bindings.php.
goto hell; — goto operator
Used to jump to another part of the program. The target label is indicated by a label followed by a colon; after the goto operator, the desired label for the jump is specified.
The target label must be in the same file and the same context. That is, you cannot exit the function or method, so you cannot jump inside any function.
You also cannot jump into any loop or switch statement. But you can exit from any loop, so "goto" is convenient as a replacement for multi-level breaks.
Example of using goto:
function rabbit(){
$i = 1;
$out = '';
start: $out .= ($i > 1 ? '-' : '' ) .$i;
if( $i++ < 5 ){ goto start; }
return $out . ' the rabbit went for a walk';
}
echo rabbit(); //> 1-2-3-4-5 rabbit went for a walk
Example of using goto inside a loop:
for( $i=0, $j=50; $i<100; $i++ ) {
while( $j-- ) {
if( $j==17 ) goto end;
}
}
echo "i = $i"; // will be skipped
end: echo 'j reached 17';
__callStatic(), __invoke() — magic methods
__callStatic() — fires when a non-existent static method is called: Foo::bar():
class A {
static function __callStatic( $name, $args ){
return $name .' '. print_r( $args, 1 );
}
}
echo A::no_matter_what('bar');
/* Output:
no_matter_what Array
(
[0] => bar
)
*/
__invoke() — fires when an object is invoked as a function: $obj():
class A {
function __invoke( $var ){
var_dump( $var );
}
}
$obj = new A;
$obj('foo'); //> string(3) "foo"—