Home > php, перевод, программирование > Что нового в PHP 5.3?

Что нового в PHP 5.3?

Так как вышел PHP 5.3, то многие не знают, что же их ждёт в будущем. А приплыло многое. Вот по этому и перевёл статью с sitepoint.com.

Кому не нравится перевод или нашли ошибку, то добро пожаловать на вики, где каждый может внести поправку в перевод.

Что нового в PHP 5.3?

By Ben Balbo

PHP шестой версии уже не за горами, но для нетерпеливых разработчиков, есть хорошая новость — много возможностей, которые планировались в PHP 6, были портированы в PHP 5.3, финальный релиз которого планируется в первой половине этого года (прим. переводчика: не так то оно случилось, только вот недавно вышел ;) ).

Эта новость, возможно, также будет хорошо воспринята теми, кто хотел бы воспользоваться новыми возможностями, но хостинг-провайдеры некоторое время не будут обновлять PHP до версии 6 — хостинг-провайдеры обычно оттягивают серьезные обновления версий программ пока выполняется их тестирование ( читать как: пока стабильность сначала не будет проверена где-нибудь в другом месте). Множество хостеров, возможно, отсрочат обновление своих услуг до версии 6.1. А маленькие обновления с 5.2.x до 5.3, возможно, будут маленьким препятствием для большинства хостинг компаний.

Эта статья показывает новые возможности , приводит примеры их возможного использования и предусматривает демонстрационный код чтобы вы поняли и работали с минимум суеты. Здесь не описывается как установить PHP 5.3 — последний возможный релиз [2] для разработчиков . Если вам хочется попробовать код с этой статьи, вы должны установить PHP 5.3, когда скачаете архив исходных кодов [3]. Статью о установке PHP 5.3 [4] вы можете найти на сайте Melbourne PHP Users Group.

Пространства имён

Перед тем, как PHP стал объектно-ориентированным, многие разработчики приложений используют многословные имена функций для того, чтобы избежать повторений имён. Например, в WordPress используются имена функций wp_update_post и wp_create_user. Префикс wp_ означает, что функция относится к WordPress и снижает шанс столкновений имён с существующими функциями.

В объектно-ориентированном мире столкновение имён попадается редко. Рассмотрим следующий пример кода, который базируется в фиктивном движке для блогинга:

<?php
class User {
  public function set( $attribute, $value ) {
    ...
  }
  public function save() {
    ...
  }
}

$user = new User();
$user->set('fullname', 'Ben Balbo');
$user->save();

В примере, метод save() не совпадает ни с одним другим методом , так как находится в классе User. Всё же есть потенциальная проблема: класс User может быть уже определён в какой-то другой части системы, если, например, приложение запускается вместе с системой управления контентом ( content management system — CMS ).

Решением этой проблемы — использовать новый оператор namespaces. Исходя с вышеописанного кода, обратимся к следующему примеру:

<?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();

На первый взгляд, преимущество предложенного пространства для наших функций могуть быть не очевидны — прежде всего мы просто изменили MyCompany_Blog_User на MyCompany::Blog::User. Тем не мение, мы можем сейчас создать класс User для CMS [5], используя другое пространство имён:

<?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>';
       }

}

Теперь мы можем использовать классы MyCompany::Blog::User и MyCompany::CMS::User.

Ключевое слово use

Адресация классов, используя полные имена, по прежнему длинная, и если вы используете много классов с пространства имён MyCompany::Blog, вы не хотели бы набирать этот путь к классу каждый раз. Тогда ключевое слово use вам в руки. Ваше приложение, скорое всего, будет использовать различные классы в любой момент времени. Предположим, пользователь создаёт новую запись:

<?php
use MyCompany::Blog;
$user = new Blog::User();
$post = new Blog::Post();
$post->setUser( $user );
$post->setTitle( $title );
$post->setBody( $body );
$post->save();

Слово use не ограничивается определением пространства имён в текущем действии. Вы также можете использовать его для импортирования одного класса в ваш файл, как ниже:

<?php
use MyCompany::Blog::User;
$user = new User();

Алиасы пространства имён

Ранее, я говорил, что одним из преимуществ namespacing, является возможность определения более чем на одного класса с таким же именем в разных пространствах имен. Несомненно, будут случаи, когда эти два класса используют один и тот же скрипт. Мы могли бы импортировать пространства имён, однако, у нас есть возможность импортировать просто эти классы. Чтобы сделать это, мы можем использовать псевдонимы для пространства имён, например, так:

<?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();

Констанкты классов

Константы теперь возможно определить на уровне классов! Имейте ввиду, что константы классов доступны, когда вы импортируете пространства имён, но вы не можете импортировать константу в себя. Вот пример того, как вы могли бы использовать их:

<?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>';

Вывод:

Blog bersion 1.0.0
Blog version 1.0.0
Blog version Foo

Функции в пространстве имён

Использование статических методов класса протестует против использования функций в объектно-ориентированном мире, в котором мы живём. Тем не менее, коль вам нужно добавить функцию в ваш пакет, это тоже по силам пространству имён ( namespacing )!

Вот пример

<?php
namespace bundle;
function foo() { echo '<p>This is the bundled foo</p>'; }
foo(); // Это выведет 'This is the bundled foo'

<?php
function foo() { echo '<p>This is the global foo</p>'; }
require( 'lib/bundle.class.php');
bundle::foo(); // Это выведет 'This is the bundled foo'
foo(); // Вывод: 'This is the global foo'

Глобальное пространство имён

Глобальное пространство имён — это важное возмещение, когда вы в ладах с функциями. В предыдущем примере, Вы заметите, что нет прямого пути вызова глобальной функции foo с основного кода (function from within the bundle code).

Метод для решения вызовов функций — это использовать текущее пространство имён (The default method of resolving calls to functions is to use the current namespace). Если функцию нельзя найти, то она будет искать найдена, то будут рассматриваться внутренние функции по имени. Автоматически будут искаться функции в других пространствах имён.

Для вызова глобальной функции 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 будет получать полную ссылку на класс в пространстве имён. Значит, вы могли бы получать такой вызов:

__autoload( 'MyCompany::Blog::User' );

Теперь вы можете с помощью оператора замены, преобразить двоеточие в другие символы. Наиболее ожидаемой заменой может быть символ разделения директорий:

function __autoload( $classname ) {
       $classname = strtolower( $classname );
       $classname = str_replace( '::', DIRECTORY_SEPARATOR, $classname );
       require_once( dirname( __FILE__ ) . '/' . $classname . '.class.php' );
}

Результатом будет подключение файла./classes/mycompany/blog/user.class.php.

Позднее статическое связывание

Позднее статическое связывание предоставляет возможность родительскому классу использовать статический метод, который был переопределён дочерним классом. Вы могли бы подумать, что это было поведение по-умолчанию, но подумайте над нижеупомянутом примере:

<?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' );

Переменные статические вызовы

Когда статический член или метод не статический? Тогда это динамическая ссылка конечно!

Ещё раз, это возможность, которая приносит объектную функциональность в ваши классы. К дополнению к переменным и вызовов переменных методов, у вас есть переменные статические вызовы. Возмём класс Factory с предыдущего раздела. Вы можете получить такой же результат с помощью этого кода:

$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

До версии 5.3, любые соединения с MySQL обычно происходили в связке с libmysql – клиентской библиотекой MySQL.

Родной драйвер для PHP 5.3 был разработан с нуля для PHP и Zend Engine, который будет иметь несколько преимуществ. Наиболее очевидным есть то, что драйвер специфичен для PHP и по-этому оптимизирован под Zend Engine. Он предоставляет клиент с маленьким footprint и быстрым временем выполнения.

Во-вторых, родной драйвер даёт возможность использовать планировщик памяти Zend Engine и будет подчинятся настройкам параметров ограничения памяти PHP.

Родной драйвер будет лицензирован под лицензией PHP дабы избежать проблем с лицензированием.

Дополнительные функции OpenSSH

Если вам когда нибудь приходилось выполнять какие-то OpenSSL инструкции в ваших сценариях (например генерацию ключи Diffie Hellman или шифровать содержимое), вы либо должны выполнить эту операцию от имени пользователя или передать запрос в системный вызов.

Патч для функциональности OpenSSL в PHP 5.3 предоставляет дополнительные функции, которые нужны для выполнения этих операций через библиотеку OpenSSL, которые не только делает вашу жизнь проще и ваши приложения быстрее, но и позволяет многократно использовать проверенный код.

Это будет хорошая новость для тех, кто, что в настоящее время работает с OpenID.

Улучшения поддержки параметров командной строки

Надеюсь, Вы уже поняли тот факт, что PHP не просто язык сценариев для Web. Версия PHP для запуска с командной строки, выполняется за средой веб-сервера и полезен для автоматизации процессов системы и приложений.

Например, функция PHP getopt() has been around for a while (!!!), но была ограничена на некоторых системах: в большинстве случаев, она не работала в Windows.

Начиная с PHP 5.3 функция getopt() не зависит от системы. Ура!

XSLT профайлинг

XSLT – это сложный зверь, и большинство пользователей этого шаблонного механизма знакомы с опциями профайлинга xsltproc. Начиная с 5.3 вы можете заниматься профайлингом ваших сценарием без этого инструмента. Этот фрагмент из примера[4], который сопровождает эту статью, дает представление о том, каким образом мы могли бы использовать это:

$doc = new DOMDocument();
$xsl = new XSLTProcessor();

$doc->load('./lib/collection.xsl');
$xsl->importStyleSheet($doc);

$doc->load('./lib/collection.xml');
$xsl->setProfiling("/tmp/xslt-profiling.txt");
echo $xsl->transformToXML($doc);

echo '<h2>Profile report</h2>';
echo '<pre>' . file_get_contents( '/tmp/xslt-profiling.txt' ) . '</pre>';

Результат профайлинга мог бы выглядеть где-то так:

number    match    name   mode     Calls   Tot  100us  Avg
0         collection                    1       4       4
1         cd                            2       1       0

          Total                         3       5

Новые уровни ошибок

PHP, конечно, имеет несколько каламбуров. Например, почему E_ALL не содержит все уровни ошибок?

Ну сейчас уже делает! Да, E_STRICT теперь часть E_ALL.

Кроме того, пока E_STRICT используется для информирования функциональности, которая может быть не рекомендуемой в ближайшем будущем, как, например, определения абстрактного статического метода, то в PHP 5.3 эти 2 ошибки делятся на E_DEPRECATED на E_STRICT соответственно, что больше подходит по смыслу.

Другие мелкие улучшения

Вот горсточка улучшений, которые появились в PHP 5.3, которые малы даже для параграфа, или были не стабильны во время написания этой статьи:

  • Sqlite3 поддерживается расширением ext/sqlite
  • В DirectoryIterator SPL реализован ArrayAccess
  • 2 новых функции: array_replace и array_replace_recursive. Пока эти функции не определены под PHP 5.3, но в коде на C, который их реализует, с виду их функциональность похожа на array_merge(). Одно исключение составляет функция array_replace(), которая будет обновлять значения в первом массиве, когда значения ключей в обоих массивах одинаковые. Значения ключей, которые есть в втором массиве, но нет в первом, будут игнорироваться.

Резюме

PHP 5.3 содержит много функциональности, которые намечались только в PHP 6, дабы стать маленьким обновлением для большого релиза, который каждый PHP разработчик должен знать. Мы затронули большинство возможностей в этой статье, привели несколько примеров кода, который показывает как вы можете использовать эти возможности.

Не забудьте скачать код, супуствующий этой заметке [12], и быть в курсе событий

[1] http://snaps.php.net/
[2] http://www.sitepoint.com/examples/php5/PHPdemos.zip
[3] http://phpmelb.org/index.php?option=com_content&view=article&id=69&Itemid=1
[4] http://www.sitepoint.com/examples/php5/PHPdemos.zip
[5] http://www.sitepoint.com/examples/php5/PHPdemos.zip

  1. October 6th, 2009 at 17:31 | #1

    Ой, пасиба тебе, добрый человек, за эту статью :) Очень пригодится даже :)

  2. Адрей
    June 4th, 2010 at 22:14 | #2

    самая интересная и детальная статья по пхп 5.3 из всех что видел, огромное спасибо автору.

  1. June 12th, 2011 at 21:22 | #1