Что нового в PHP 5.3
В PHP 5.3, как и во всей пятой ветке PHP, включена новая машина-интерпретатор скриптов Zend Engine 2.0. Благодаря этому PHP стал работать быстрее примерно на 15-20%.
-
Wiki: PHP 5.3
- php.net: Новые возможности в PHP 5.3.
?:
— сокращение тернарного оператора
С PHP 5.3 стало возможным не писать среднюю часть тернарного оператора. Выражение expr1 ?: expr3
возвращает expr1 если expr1 не пустой, и expr3 в противном случае.
Тернарный — состоящий из трёх частей, компонентов.
$a = $expr1 ?: $expr3; // равносильно записи: $a = $expr1 ? $expr1 : $expr3;
Пример тернарного оператора:
// полная запись if ( $a > 100 ) $result = "Больше"; else $result = "Меньше"; // краткая запись $result = $a > 100 ? "Больше" : "Меньше";
В короткой записи есть еще момент производительности, например:
// полная запись if ( get_post_meta(25, 'meta_key', 1) ) echo esc_html( get_post_meta(25, 'meta_key', 1) ); else echo 'Мета поля нет'; // короткая запись echo esc_html( get_post_meta(25, 'meta_key', 1) ?: 'Мета поля нет' );
В полной записи функция get_post_meta() вызывается 2 раза. В короткой один раз, и если она что-то вернула, второму аргументу тернарного оператора сразу передается полученное значение: не нужны дополнительные переменные...
$func = function() use (){ }
— анонимные (лямбда) функции
Лямбда-функции еще называют «анонимными функциями», потому что для них не указывается название.
Лямбда-функции представляют собой замыкание (англ. closure) — это особый вид функции, которая определена в теле другой функции и создаётся каждый раз во время её выполнения. Синтаксически это выглядит как функция, находящаяся целиком в теле другой функции. Насколько я понял, любая функция — это замыкание текущего контекста, т.е. контекст не будет очищен пока работает функция. Но если в функции есть лямбда-функция, то она становится замыканием, и если в неё передаются переменные из «верхней» функции, то они не будут очищены, до тех пор пока работает вложенная-функция, даже если «верхняя» функция работу закончила...
В ранних версиях, анонимные функции создавались с помощью функции create_function().
Пример создания анонимной функции для сортировки usort():
$arr = array(3, 2, 5, 6, 1); usort( $arr, function($a, $b) { if ( $a == $b ) return 0; return ( $a > $b ) ? -1 : 1; });
Еще одна фишка лямбда-функций — это использование переменных из текущей области видимости, с помощью оператора use
:
$var = 'Превед, Медвед!'; $func = function() use ( $var ) { echo $var; }; $func(); //> Превед, Медвед!
Переменные передаются как значение, но можно передать и ссылку на переменную, указав &
:
$var = 'Превед, Медвед!'; $func = function() use ( & $var ) { $var = $var .' Мы в гости!'; }; $func(); // вызовем echo $var; //> Превед, Медвед! Мы в гости!
method()->var
— получение объекта из метода/функции
Это удобно:
$object->method()->method()->method(); $object->method()->method()->member = 5;
В PHP ниже 5.3 писали как-то так:
$tmp = & $object->method(); $tmp = & $tmp->method(); $tmp->method();
<<<'DOC'
— поддержка NOWDOC
В php 5.3 можно использовать аналог HEREDOC, который называется NOWDOC. Особенность его в том, что внутри него переменные остаются простым текстом, как если бы мы указали её в строке с одинарными кавычками: 'текст $foo'
:
$foo = 'Лето'; // HEREDOC был в 5.2 $str = <<<DOC Текст с переменной '$foo' DOC; echo $str; // Текст с переменной 'Лето' // NOWDOC появился в 5.3 $str = <<<'DOC' Текст с переменной '. $foo .' DOC; echo $str; // Текст с переменной '. $foo .'
namespace
— поддержка пространств имен
Пространства имен нужны, чтобы избежать конфликтов при совпадении названий функций/классов/переменных/констант. Если коротко: одинаковые называния в разных пространствах — это разные названия.
Пример ниже должен объяснить почти все, что возможно в пространствах имен. За подробностями идем в официальную документацию.
__DIR__
— новая магическая константа
__DIR__ содержит директорию текущего файла - файла в котором она используется. Возвращает полный путь до текущего файла без закрывающего слэша, за исключением корневой директории.
__DIR__ можно заменить:
dirname(__FILE__)
$class::$foo
— динамичное указание класса
Это дает динамичный доступ к статическим методам/свойствам класса:
class C { static $foo = 'foo'; } $class = 'C'; echo $class::$foo; //> foo
const
— ключевое слово для создания констант вне классов
Сразу пример, где все понятно:
define('SHORTINIT', 'true'); // теперь можно объявить константу и так: const SHORTINIT = 'true';
В отличие define(), такие константы, должны быть объявлены в самой верхней области видимости, потому что они определяются при компилировании скрипта. Это значит, что их нельзя объявлять внутри функций/циклов/выражений if или try/ catch блоков.
static::method()
— статическое связывание
Статическое объявление метода/свойства связывает его с классом из которого оно вызывается, а не с тем в котором оно зарегистрировано. Посмотрим на примере:
class A { static function who() { echo __CLASS__; } static function test1() { self::who(); } static function test2() { static::who(); // статическое связывание } } class B extends A { static function who() { echo __CLASS__; } } echo B::test1(); //> A echo B::test2(); //> B echo B::who(); //> B
Подробнее про статическое связывание читайте в документации.
goto hell;
— оператор goto
Используется для перехода в другую часть программы. Место, куда необходимо перейти указывается с помощью метки, за которой ставится двоеточие, после оператора goto указывается желаемая метка для перехода.
Целевая метка должна находиться в том же файле, в том же контексте. Т.е. нельзя выйти за границы функции или метода, а значит нельзя перейти внутрь любой функции.
Также нельзя перейти внутрь любой циклической структуры или оператора switch. Но можно выйти из любой циклической структуры, поэтому «goto» удобен как замена многоуровневых break.
Пример использования goto:
function zayac(){ $i = 1; $out = ''; start: $out .= ($i > 1 ? '-' : '' ) .$i; if( $i++ < 5 ){ goto start; } return $out . ' вышел зайчик погулять'; } echo zayac(); //> 1-2-3-4-5 вышел зайчик погулять
Пример использования goto в цикле:
for( $i=0, $j=50; $i<100; $i++ ) { while( $j-- ) { if( $j==17 ) goto end; } } echo "i = $i"; // будет пропущено end: echo 'j дошло до 17';
__callStatic(), __invoke()
— магические методы
__callStatic()
— срабатывает, когда вызывается несуществующий метод из статического контекста: Foo::bar()
:
class A { static function __callStatic( $name, $args ){ return $name .' '. print_r( $args, 1 ); } } echo A::no_matter_what('bar'); /* Выведет: no_matter_what Array ( [0] => bar ) */
__invoke()
— срабатывает, когда объект выполняется как функция: $obj()
:
class A { function __invoke( $var ){ var_dump( $var ); } } $obj = new A; $obj('foo'); //> string(3) "foo"
—