PHP 6 не за горами, но для разработчиков, которые просто не могут ждать, есть хорошие новости — многие функции, первоначально запланированные для PHP 6, были перенесены в PHP 5.3, окончательный стабильный выпуск которого должен быть в Первая половина этого года.
Эта новость также может приветствоваться теми, кто хочет использовать некоторые из новых функций, но чьи хостинг-провайдеры не будут обновляться до версии 6 в течение некоторого времени — хостинг-провайдеры традиционно откладывают обновление основных версий, пока проводится приемочное тестирование (читай: стабильность была доказана в другом месте в первую очередь). Многие хостинговые компании, вероятно, откладывают обновление своих сервисных предложений до выпуска версии 6.1. Незначительное обновление с 5.2.x до 5.3, однако, будет меньшим препятствием для большинства хостинговых компаний.
В этой статье представлены новые функции, приведены примеры того, где они могут быть полезны, а также приведен демонстрационный код, позволяющий приступить к работе с минимальными усилиями. Он не охватывает такие темы, как установка PHP 5.3 — последняя версия для разработчиков, которая в настоящее время доступна . Если вы хотите поиграться с кодом в этой статье, вам следует установить PHP 5.3, а затем загрузить архив кода . Статью по установке PHP 5.3 можно
найден на веб-сайте Мельбурнской группы пользователей PHP.
Пространства имен
До появления объектно-ориентированного PHP многие разработчики приложений использовали подробные имена функций, чтобы избежать конфликтов пространства имен. WordPress, например, реализует такие функции, как wp_update_post
wp_create_user
wp_ prefix
В объектно-ориентированном мире конфликты пространства имен менее вероятны. Рассмотрим следующий пример фрагмента кода, который основан на вымышленном приложении для ведения блогов:
<?php
class User {
public function set( $attribute, $value ) { ... }
public function save() { ... }
}
$user = new User();
$user->set('fullname', 'Ben Balbo');
$user->save();
В этом примере метод save не будет конфликтовать с любым другим методом, так как он содержится в классе User. Тем не менее, существует потенциальная проблема: класс User может быть уже определен какой-либо другой частью системы, если, например, приложение для ведения блога работает в системе управления контентом.
Решением этой проблемы является использование нового ключевого слова 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 (‘полное имя’, ‘Бен Бальбо’);
$ User-> Save ();
На первый взгляд, преимущества, предлагаемые пространством имен нашей функции, могут быть не сразу очевидны — в конце концов, мы просто изменили MyCompany_Blog_User
MyCompany::Blog::User
Однако теперь мы можем создать класс User
<?php
namespace MyCompany::CMS;
класс User {
набор публичных функций ($ attribute, $ value) {
$ this -> $ attribute = $ value;
}
публичная функция save () {
echo ‘<p> пользователь CMS’. $ this-> полное имя. ‘сохранен </ 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();
Псевдонимы пространства имен
Ранее я указывал, что одним из преимуществ пространства имен является возможность определять более одного класса с одним и тем же именем в разных пространствах имен. Очевидно, будут случаи, когда эти два класса используются одним и тем же сценарием. Мы могли бы просто импортировать пространства имен, однако у нас также есть возможность импортировать только классы. Для этого мы можем использовать псевдонимы пространства имен для идентификации каждого класса, например так:
<?php
use MyCompany::Blog::User as BlogUser;
use MyCompany::CMS::User as CMSUser;
$ bloguser = new BlogUser ();
$ bloguser-> set (‘полное имя’, ‘Джон Доу’);
$ Bloguser-> Save ();
$ cmsuser = new CMSUser ();
$ cmsuser-> set (‘полное имя’, ‘Джон Доу’);
$ Cmsuser-> Save ();
Константы класса
Константы теперь могут быть определены на уровне класса! Обратите внимание, что константы класса доступны при импорте пространств имен, но вы не можете импортировать саму константу. Вот пример того, как мы могли бы их использовать:
<?php
namespace MyCompany;
Блог класса {
const VERSION = ‘1.0.0’;
}
<? PHP
echo ‘<p> Blog bersion’. MyCompany :: Блог :: ВЕРСИЯ. ‘</ Р>’;
использовать MyCompany :: Blog;
echo ‘<p> Версия блога’. Блог :: ВЕРСИЯ. ‘</ Р>’;
используйте MyCompany :: Blog :: VERSION как Foo;
echo ‘<p> Версия блога’. Фу. ‘</ Р>’;
Это приведет к следующему выводу:
Блог Bersion 1.0.0
Блог версия 1.0.0
Версия блога Foo
Функции пространства имен
Использование статических методов класса устарело использование функций в объектно-ориентированном мире, в котором мы сейчас живем. Однако, если вам нужно добавить функцию в ваш пакет, она тоже будет подвержена пространству имен!
Вот пример:
<?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> Это глобальный foo </ p>’; }
require (‘lib / bundle.class.php’);
расслоение :: Foo (); // Это печатает ‘Это в комплекте Foo’
Foo (); // Это печатает ‘Это глобальный foo’
Глобальное пространство имен
Глобальное пространство имен является важным фактором при работе с функциями. В предыдущем примере вы заметите, что не существует прямого способа вызова глобальной функции foo
Метод разрешения вызовов функций по умолчанию — использовать текущее пространство имен. Если функция не может быть найдена, она будет искать внутреннюю функцию с таким именем. Он не будет смотреть в других пространствах имен автоматически.
Чтобы вызвать глобальную функцию 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' );
Вы, вероятно, ожидаете, что это вернет «Ребенок говорит Привет». Хотя я понимаю, почему вы можете ожидать этого, вы будете разочарованы, увидев, что он возвращает «Родитель говорит Привет».
Причина этого заключается в том, что ссылки на self::
__CLASS__
PHP 5.3 теперь включает static::
static public function say( $str ) {
static::do_print( $str );
}
С добавлением static::
__callstatic
До сих пор PHP поддерживал ряд магических методов в классах, с которыми вы уже знакомы, таких как __set
__get
__call
В PHP 5.3 представлен метод __callstatic
Другими словами, метод воздействует на нераспознанные статические вызовы непосредственно в классе.
Следующий пример иллюстрирует концепцию:
<?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 );
You can create dynamic namespaces like so:
<?php
require_once( 'lib/autoload.php' );
$class = 'MyCompany::Blog::User';
$user = new $class();
$user->set('fullname', 'Ben Balbo');
$user->save();
Эти маленькие штрихи могут сделать ваш код более читабельным и обеспечить полную гибкость в объектно-ориентированном смысле.
MySQL Native Driver
До версии 5.3 PHP любое взаимодействие с MySQL обычно происходило в сочетании с libmysql
Нативный драйвер MySQL для PHP 5.3 был разработан с нуля для PHP и движка ZEND, что дает ряд преимуществ. Очевидно, что родной драйвер специфичен для PHP и поэтому был оптимизирован для движка ZEND. Это дает клиенту меньшую площадь и меньшее время выполнения.
Во-вторых, нативный драйвер использует управление памятью движка ZEND и, в отличие от libmysql
Нативный драйвер был лицензирован по лицензии PHP, чтобы избежать проблем с лицензированием.
Дополнительные функции OpenSSL
Если вам когда-либо приходилось выполнять какие-либо действия, связанные с OpenSSL, в ваших сценариях (например, генерировать ключ Диффи-Хеллмана или шифровать контент), вы либо выполнили эту операцию в пользовательской среде, либо передали запрос системному вызову. ,
Патч для функциональности OpenSSL в PHP 5.3 предоставляет дополнительные функции, необходимые для выполнения этих действий через библиотеку OpenSSL, которая не только облегчает вашу жизнь и ваши приложения быстрее, но и позволяет вам повторно использовать проверенный код, который поставляется с OpenSSL.
Это будет отличной новостью для тех, кто в настоящее время работает с OpenID.
Улучшенная поддержка параметров командной строки
Надеюсь, вы будете знать, что PHP — это больше, чем просто язык сценариев для Интернета. Версия PHP для командной строки работает вне среды веб-сервера и полезна для автоматизации процессов системы и приложений.
Например, функция getopt в PHP существовала некоторое время, но была ограничена рядом системных типов; чаще всего он не функционировал в среде операционной системы Windows.
Начиная с PHP 5.3, функция getopt больше не зависит от системы. Ура!
XSLT Профилирование
XSLT — сложный зверь, и большинство пользователей этого шаблонного механизма знакомы с опцией профилирования xsltproc. Начиная с PHP 5.3, вы можете профилировать преобразования из ваших скриптов PHP. Этот фрагмент из примера кода , сопровождающего эту статью, дает вам представление о том, как мы могли бы его использовать:
$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
Ну, теперь это так! Да, PHP 5.3 теперь включает E_STRICT
E_ALL
Кроме того, в то время как E_STRICT
E_DEPRECATED
E_STRICT
Другие незначительные улучшения
В PHP 5.3 появилось несколько других улучшений, которые либо не гарантируют целый раздел в этой статье, либо не были протестированы на момент написания этой статьи, такие как:
- Поддержка Sqlite3 через расширение
ext/sqlite
-
DirectoryIterator
ArrayAccess
- Две новостные функции:
array_replace
array_replace_recursive
Хотя эти функции не были определены при тестировании в PHP 5.3.0, код C, который их реализует, предполагает, что они будут содержать функциональность, аналогичнуюarray_merge
Единственное исключение, однако, заключается в том, что функцияarray_replace
Любые ключи, которые присутствуют во втором массиве, но не появляются в первом, будут игнорироваться.
Резюме
PHP 5.3 содержит много функциональных возможностей, которые изначально были предназначены для включения в PHP 6, что превращает его из незначительного обновления в значительный выпуск, о котором каждый разработчик PHP должен задуматься. Мы коснулись большинства функций в этой статье и рассмотрели некоторый код, демонстрирующий, как вы можете использовать эти новые функции.
Не забудьте скачать архив кода, который сопровождает эту статью , и повеселиться, живя на грани!