PHP 5.3 незамеченный релиз
Категория: / DEV Блог
/ PHP (LAMP)
Что нового в PHP 5.3?
PHP 6 не за горами, но разработчики не могут терпеть несправедливости php 5.2, бэкпортировали возможности
шестерки в пятую ветку. Релиз которой состаялся в конце июня!
Насколько я знаю, портеры FreeBSD не сделали порт, поэтому обновляться либо вручную, либо ждать официально поддерживаемого порта.
PHP становится более объектно ориентированным языком - добавлена поддержка неймспейсов, но
корни языка попрежнему дают о себе знать - это и путаница в параметрах haystack-needle и "программистские пробелы"
в названиях функций.
В бетах php 5.3 разделителем имен был символ "::", потом разработчики хорошо подумали и ими был выбран
новый разделительный символ "\" бэкслеш, аля windows-path-separator. Теперь наш код будет смотреться удивительно
красиво - то ли мы экранируем символы, толи выделяем неймспейсы. мрак..
Вот пример кода. Одному мне кажется, что слеши смотрятся убого и нелепо
(да, теперь все основные фукции явно указываются с глобальным контекстом).
Почему они выбрали этот разделитель?
\1\Тема\на\stackoverflow
\2\RFC-Стори\на\PHP\wiki
PHP всегда был особенным, не совсем логичным языком.
В этом примере объявлен обычный класс User. Однако, если вы используете в своей разработке сторонние
библиотеки (ака фреймворки), то можете встретися с неприятной вещью - конфликтом имен. Именно поэтому
в эпоху динозавров к именам классов-переменныъ приходилось добавлять префиксы. Возьмите тот же zend framework -
все объявления классов начинаются с префикса Zend_, что не очень удобно и читабельно.
Итак, на помощь нам приходят неймспейсы. Кто вообще не в теме, неймспейсы - это так называемые "области видимости" или
можно сказать "контексты выполнения". Ранее все скрипты выполнялись в глобальном неймспейсе-контексте, теперь вы можете
объявить свои, чтобы исключить конфликты.
Смотрите код
Здесь вы явно указываете, что создаете экземпляр класса User именно из необходимого неймспейса.
Вероятнее всего, раньше бы этот класс назывался не иначе как MyCompany_Blog_User.
Сейчас, имеем имя MyCompany\Blog\User.
Усложним задачу - добавим еще один класс User, но в другом неймспейсе. Теперь мы можем манипулировать
разными "Юзерами", обращаясь к классу полным именем MyCompany\Blog\User и MyCompany\CMS\User.
The use Keyword
Для того чтобы не перегружать код программы, используются ключевое слово "use",
с помощью которого мы указываем интерпретатору, какой неймспейс мы хотим сейчас использовать.
C помощью use можно также просто импортировать класс из другого неймспейса.
Если по каким-то причинам вы не можете использовать одновременно несколько разных классов (из-за конфликтов к примеру),
язык позволяет создать алиасы (синонимы) для обращения к ним.
Константы объявляются следующим образом.
Этот код создаст две константы в неймспейсе test.
Единственное, на константу нельзя сделать алиас.
В php 5.3 добавлены новые константы:
__NAMESPACE__ - текущий неймспейс
__DIR__ - текущая директория (ранее определялась dirname(__FILE__))
В объектно ориентированном мире нет места функциям - их заменили статичные методы.
В PHP мы можем создавать функции в неймспейсах и обращаться к ним соответственно через их
область имен.
Пример:
Если ваш класс переопределяет метод из глобального неймспейса, вызвать
его можно следующим образом
Теперь в __autoload будет передаваться полное имя класса.
__autoload( 'MyCompany\Blog\User' );
Загрузку скрипта можно осуществить следующим образом
Результатом вызова __autoload будет подключение скрипта ./classes/mycompany/blog/user.class.php.
Подробнее о неймспейсах
Кто-то говорит про паттерн ActiveRecord?
LSB дает возможность вызывать в родительском классе переопределенные в результате наследования методы.
Вероятнее всего вы ожидаете результата "Child says Hello", однако теперь результатом выполнения будет "Parent says Hello".
Причина в том что self:: и __CLASS__ резолвятся в имя класса, в котором они используются. PHP 5.3 включает ключевое
слово static::, значение которого указывает на статичный класс, в контексте которого был вызван метод.
С использованием static\ скрипт выведет "Child says Hello".
До настоящего времени, у PHP в наличии были востребованные "волшебные методы" __set, __get и __call.
PHP 5.3 вводит в оборот новый метод __callstatic , который работает точно также как и __call,
за исключением того что он оперирует со статичным контекстом.
Теперь вы можете вызывать динамически статичные методы.
Вы можете динамически создавать объекты.
Хотя это не приветствуется, потому как затрудняет отладку, читаемость кода.
Нативный драйвер mysql. Улучшена производительность благодаря интеграции библиотеки mysql и движка zend.
Также значительно улучшена работа драйвера с памятью, так как она теперь выделяется не напрямую, а с помощью
механизмов zend.
Подробнее о mysqlnd
Да, да - теперь E_ALL по-умолчанию включает этот режим.
Также добавлена константа E_DEPRICATED, ошибки с уровнем которой будут возникать в случае использования функций,
помеченных как "устаревшие". И такие наверняка будут, потому как например "устарели"
Полный список устаревших конструкций
Статья - вольный перевод http://www.sitepoint.com/article/whats-new-php-5-3/
Раньше php не позволял создавать простые анонимные функции (функции без имени), вместо этого в языке была предусмотрена функция create_function.
Основное назначение анонимусов - в фукциях обратного вызова (callbacks).
В php 5.3 все объявления анонимных функций автоматически создаются как экземпляры внутреннего класса Closure.
Замыкания могут создаваться внутри других методов. Для использования переменных из родительского контекста, их нужно явно
указать в заголовке функции.
Страница мануала по замыканиям
Обычная версия его выполняет роль if-then-else и используется следующим образом
С появлением PHP 5.3, возможно отбросить среднюю часть оператора (та что true) и сразу перейти к ложному условию.
Первая часть в таком случае равна самому условию.
Страница мануала по тернарному оператору
Дополнительная информация по миграции с PHP 5.2 на 5.3
http://ru2.php.net/migration53
PHP 6 не за горами, но разработчики не могут терпеть несправедливости php 5.2, бэкпортировали возможности
шестерки в пятую ветку. Релиз которой состаялся в конце июня!
Насколько я знаю, портеры FreeBSD не сделали порт, поэтому обновляться либо вручную, либо ждать официально поддерживаемого порта.
PHP становится более объектно ориентированным языком - добавлена поддержка неймспейсов, но
корни языка попрежнему дают о себе знать - это и путаница в параметрах haystack-needle и "программистские пробелы"
в названиях функций.
Namespaces - неймспейсы - пространства имён
В бетах php 5.3 разделителем имен был символ "::", потом разработчики хорошо подумали и ими был выбран
новый разделительный символ "\" бэкслеш, аля windows-path-separator. Теперь наш код будет смотреться удивительно
красиво - то ли мы экранируем символы, толи выделяем неймспейсы. мрак..
Вот пример кода. Одному мне кажется, что слеши смотрятся убого и нелепо
(да, теперь все основные фукции явно указываются с глобальным контекстом).
if (empty($this->_options['register-only'])) {
if (!\file_exists($dest_dir) || !is_dir($dest_dir)) {
if (!\mkdir($dest_dir, 0755, true)) {
throw new Installer\Exception("failed to mkdir $dest_dir");
}
Log::log(3, "+ mkdir $dest_dir");
}
Почему они выбрали этот разделитель?
\1\Тема\на\stackoverflow
\2\RFC-Стори\на\PHP\wiki
PHP всегда был особенным, не совсем логичным языком.
<?php
class User {
public function set( $attribute, $value ) { ... }
public function save() { ... }
}
$user = new User();
$user->set('fullname', 'Ben Balbo');
$user->save();
В этом примере объявлен обычный класс User. Однако, если вы используете в своей разработке сторонние
библиотеки (ака фреймворки), то можете встретися с неприятной вещью - конфликтом имен. Именно поэтому
в эпоху динозавров к именам классов-переменныъ приходилось добавлять префиксы. Возьмите тот же zend framework -
все объявления классов начинаются с префикса Zend_, что не очень удобно и читабельно.
Итак, на помощь нам приходят неймспейсы. Кто вообще не в теме, неймспейсы - это так называемые "области видимости" или
можно сказать "контексты выполнения". Ранее все скрипты выполнялись в глобальном неймспейсе-контексте, теперь вы можете
объявить свои, чтобы исключить конфликты.
Смотрите код
<?php
namespace MyCompany\Blog;
class User {
public function set( $attribute, $value ) {
$this->$attribute = $value;
}
public function save() {
echo '<p>Blog user ' . $this->fullname . ' saved</p>';
}
}
<?php
$user = new MyCompany\Blog\User();
$user->set('fullname', 'Ben Balbo');
$user->save();
Здесь вы явно указываете, что создаете экземпляр класса User именно из необходимого неймспейса.
Вероятнее всего, раньше бы этот класс назывался не иначе как MyCompany_Blog_User.
Сейчас, имеем имя MyCompany\Blog\User.
<?php
namespace MyCompany\CMS;
class User {
public function set( $attribute, $value ) {
$this->$attribute = $value;
}
public function save() {
echo '<p>CMS user ' . $this->fullname . ' saved</p>';
}
}
Усложним задачу - добавим еще один класс User, но в другом неймспейсе. Теперь мы можем манипулировать
разными "Юзерами", обращаясь к классу полным именем MyCompany\Blog\User и MyCompany\CMS\User.
The use Keyword
Для того чтобы не перегружать код программы, используются ключевое слово "use",
с помощью которого мы указываем интерпретатору, какой неймспейс мы хотим сейчас использовать.
<?php
use MyCompany\Blog;
$user = new Blog\User();
$post = new Blog\Post();
$post->setUser( $user );
$post->setTitle( $title );
$post->setBody( $body );
$post->save();
C помощью use можно также просто импортировать класс из другого неймспейса.
<?php
use MyCompany\Blog\User;
$user = new User();
Namespace Aliases
Если по каким-то причинам вы не можете использовать одновременно несколько разных классов (из-за конфликтов к примеру),
язык позволяет создать алиасы (синонимы) для обращения к ним.
<?php
use MyCompany\Blog\User as BlogUser;
use MyCompany\CMS\User as CMSUser;
$bloguser = new BlogUser();
$bloguser->set('fullname', 'John Doe');
$bloguser->save();
$cmsuser = new CMSUser();
$cmsuser->set('fullname', 'John Doe');
$cmsuser->save();
Констаны классов
Константы объявляются следующим образом.
Этот код создаст две константы в неймспейсе test.
namespace test;
define('test\HELLO', 'Hello world!');
define(__NAMESPACE__ . '\GOODBYE', 'Goodbye cruel world!');
Единственное, на константу нельзя сделать алиас.
<?php
namespace MyCompany;
class Blog {
const VERSION = '1.0.0';
}
<?php
echo '<p>Blog bersion ' . MyCompany\Blog\VERSION . '</p>';
use MyCompany\Blog;
echo '<p>Blog version ' . Blog\VERSION . '</p>';
use MyCompany\Blog\VERSION as Foo;
echo '<p>Blog version ' . Foo . '</p>';
This will result in the following output:
Blog version 1.0.0
Blog version 1.0.0
Blog version Foo
В php 5.3 добавлены новые константы:
__NAMESPACE__ - текущий неймспейс
__DIR__ - текущая директория (ранее определялась dirname(__FILE__))
Функции в неймспейсах
В объектно ориентированном мире нет места функциям - их заменили статичные методы.
В PHP мы можем создавать функции в неймспейсах и обращаться к ним соответственно через их
область имен.
Пример:
<?php
namespace bundle;
function foo() { echo '<p>This is the bundled foo</p>'; }
foo(); // This prints 'This is the bundled foo'
<?php
function foo() { echo '<p>This is the global foo</p>'; }
require( 'lib/bundle.class.php');
bundle\foo(); // This prints 'This is the bundled foo'
foo(); // This prints 'This is the global foo'
Явный вызов функции из глобального контекста
Если ваш класс переопределяет метод из глобального неймспейса, вызвать
его можно следующим образом
<?php
namespace bundle;
function foo() { echo '<p>This is the bundled foo</p>'; }
foo(); // This prints 'This is the bundled foo'
\foo(); // This prints 'This is the global foo'
Автолоад классов в неймспейсах
Теперь в __autoload будет передаваться полное имя класса.
__autoload( 'MyCompany\Blog\User' );
Загрузку скрипта можно осуществить следующим образом
function __autoload( $classname ) {
$classname = strtolower( $classname );
$classname = str_replace( '\', DIRECTORY_SEPARATOR, $classname );
require_once( dirname( __FILE__ ) . '/' . $classname . '.class.php' );
}
Результатом вызова __autoload будет подключение скрипта ./classes/mycompany/blog/user.class.php.
Подробнее о неймспейсах
Late Static Binding, LSB, позднее связывание
Кто-то говорит про паттерн ActiveRecord?
LSB дает возможность вызывать в родительском классе переопределенные в результате наследования методы.
<?php
class ParentClass {
static public function say( $str ) {
self::do_print( $str );
}
static public function do_print( $str ) {
echo "<p>Parent says $str</p>";
}
}
class ChildClass extends ParentClass {
static public function do_print( $str ) {
echo "<p>Child says $str</p>";
}
}
ChildClass::say( 'Hello' );
Вероятнее всего вы ожидаете результата "Child says Hello", однако теперь результатом выполнения будет "Parent says Hello".
Причина в том что self:: и __CLASS__ резолвятся в имя класса, в котором они используются. PHP 5.3 включает ключевое
слово static::, значение которого указывает на статичный класс, в контексте которого был вызван метод.
static public function say( $str ) {
static::do_print( $str );
}
С использованием static\ скрипт выведет "Child says Hello".
__callstatic
До настоящего времени, у PHP в наличии были востребованные "волшебные методы" __set, __get и __call.
PHP 5.3 вводит в оборот новый метод __callstatic , который работает точно также как и __call,
за исключением того что он оперирует со статичным контекстом.
<?php
class Factory {
static function GetDatabaseHandle() {
echo '<p>Returns a database handle</p>';
}
static function __callstatic( $methodname, $args ) {
echo '<p>Unknown static method <strong>' . $methodname . '</strong>' .
' called with parameters:</p>';
echo '<pre>' . print_r( $args, true ) . '</pre>';
}
}
Factory::GetDatabaseHandle();
Factory::CreateUser();
Factory::CreateBlogPost( 'Author', 'Post Title', 'Post Body' );
Теперь вы можете вызывать динамически статичные методы.
$classname = 'Factory';
$methodname = 'CreateUser';
$classname::$methodname();
$methodname = 'CreateBlogPost';
$author = 'Author';
$posttitle = 'Post Title';
$postbody = 'Post Body';
$classname::$methodname( $author, $posttitle, $postbody );
Вы можете динамически создавать объекты.
<?php
require_once( 'lib/autoload.php' );
$class = 'MyCompany\Blog\User';
$user = new $class();
$user->set('fullname', 'Ben Balbo');
$user->save();
Хотя это не приветствуется, потому как затрудняет отладку, читаемость кода.
MySQL Native Driver - mysqlnd
Нативный драйвер mysql. Улучшена производительность благодаря интеграции библиотеки mysql и движка zend.
Также значительно улучшена работа драйвера с памятью, так как она теперь выделяется не напрямую, а с помощью
механизмов zend.
Подробнее о mysqlnd
E_STRICT
Да, да - теперь E_ALL по-умолчанию включает этот режим.
Также добавлена константа E_DEPRICATED, ошибки с уровнем которой будут возникать в случае использования функций,
помеченных как "устаревшие". И такие наверняка будут, потому как например "устарели"
call_user_method();
ereg(); // (use preg_match() instead)
ereg_replace(); // (use preg_replace() instead)
Полный список устаревших конструкций
Статья - вольный перевод http://www.sitepoint.com/article/whats-new-php-5-3/
Замыкания - closures
Раньше php не позволял создавать простые анонимные функции (функции без имени), вместо этого в языке была предусмотрена функция create_function.
Основное назначение анонимусов - в фукциях обратного вызова (callbacks).
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
// outputs helloWorld
В php 5.3 все объявления анонимных функций автоматически создаются как экземпляры внутреннего класса Closure.
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
Замыкания могут создаваться внутри других методов. Для использования переменных из родительского контекста, их нужно явно
указать в заголовке функции.
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "\PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
Страница мануала по замыканиям
Тернарный оператор (ternary)
Обычная версия его выполняет роль if-then-else и используется следующим образом
(expr1) ? (expr2) : (expr3) // if (expr1) =expr2 else =expr3
С появлением PHP 5.3, возможно отбросить среднюю часть оператора (та что true) и сразу перейти к ложному условию.
Первая часть в таком случае равна самому условию.
expr1 ?: expr3 // if (expr1) =expr1 else =expr3
Страница мануала по тернарному оператору
Дополнительная информация по миграции с PHP 5.2 на 5.3
http://ru2.php.net/migration53
if (empty($this->_options['register-only'])) {
if (!\file_exists($dest_dir) || !is_dir($dest_dir)) {
if (!\mkdir($dest_dir, 0755, true)) {
throw new Installer\Exception("failed to mkdir $dest_dir");
}
Log::log(3, "+ mkdir $dest_dir");
}
Можно написать так:
if (empty($this->_options['register-only'])) {
if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
if (!mkdir($dest_dir, 0755, true)) {
throw new Installer\Exception("failed to mkdir $dest_dir");
}
Log::log(3, "+ mkdir $dest_dir");
}
Т.е. перед вызовом стандартной функции не обязателен слеш, первым делом функция ищется в "глобальном" namespace, а потом уже в родительских. В этом есть преимущество: вы можете дополнить любую функцию объявив её в родильском namespace
function mkdir($path)
{
mdkdir($path);
//Записываем в логи необходимую информацию
}
Теперь когда вы будете вызывать фунцию mkdir в этом namespace логирование будет происходить автоматически, что ускоряет разработку.
В общем, поддержка замыканий вышла куцой :(
Ждём PHP6?...