Статьи

PHP5: скоро будет веб-сервер рядом с вами

Если вы имеете дело с PHP , самым популярным языком программирования на стороне сервера, вы, несомненно, будете знать, что преемник текущей версии PHP 4 ждет своего часа.

В последние пару лет PHP5 шептался на краю дискуссий PHP, часто выходя на поверхность в обсуждениях объектной модели PHP4 (поддержка, которую PHP предоставляет для объектно-ориентированного программирования).

Для некоторых PHP5 — это «святой Грааль», который предоставит основные функции, без которых они боролись, чтобы выжить. Для других PHP5 смутно тревожит, поскольку, похоже, он угрожает статус-кво предложениями о принятии дисциплины программирования, подобной Java.

Независимо от вашего взгляда на ситуацию (или если вы даже не знали об этом), час PHP5 быстро приближается. 29 июня 2003 года Стерлинг Хьюз объявил о выпуске PHP5 Beta 1 , первого релиза, призванного дать всему сообществу PHP представление о предстоящем событии.

Я наблюдал за эволюцией PHP5 со стороны и списков рассылки, стараясь не отвлекаться от реальной работы с PHP4, но с анонсом Beta 1 мое любопытство наконец-то одолело меня. В этой статье я подробно расскажу о важных возможностях PHP5, основанных на бета-версии. Мы также рассмотрим его значение для будущего PHP как технологии.

Сразу скажу (для тех, кто нервничает по поводу влияния версии 5 на их способность взламывать с помощью PHP), не паникуйте! Основная команда разработчиков PHP хорошо знает о самых сильных сторонах PHP, включая быстрое создание прототипов, простоту использования и практический подход к решению проблем. При разработке версии 5 ясно, что эти принципы оставались главным приоритетом команды, несмотря на то, что движущей силой было сделать PHP более привлекательным для профессиональных разработчиков программного обеспечения.

Сегодня мы поговорим о:

  • Почему PHP5?
  • Тест-драйв: новая объектная модель, новая база данных, обработка исключений, новый механизм XML и многое другое …
  • Создание волн: будущее с PHP

Важное примечание: PHP5 Beta 1 не должен использоваться на работающем веб-сервере; Есть еще много вопросов, которые необходимо решить. Бета-версия предназначена для разработчиков, чтобы получить представление о том, что предлагается, и помочь группе PHP с поиском ошибок.

Почему PHP5?

Все любят PHP, верно? Ну, возможно, каждый, кто его использует, но PHP4 имеет ряд областей, которые вызывают критику со стороны разработчиков, использующих такие языки, как Java. Большое количество этой критики происходит из истории PHP; PHP начал свою жизнь как элементарный процедурный язык программирования.

Процедурные Vs. Объектно-ориентированный

Процедурный язык программирования — это язык, на котором разработчик записывает список инструкций для компьютера, которым нужно следовать в «пакете». В центре внимания процедурного языка находится функция, которой отдается приоритет над данными (переменными). Процедурное программирование часто очень эффективно для одноразового, «выброшенного» решения проблем, такого как сценарий командной строки для резервного копирования базы данных или простая веб-страница с формой. Недостаток процедурного программирования становится очевидным, когда вы начинаете создавать более крупные и сложные приложения. Переменные, доступные из всех областей, могут быть легко перезаписаны по ошибке, и общая структура приложения обычно приводит к воспроизведению подпрограмм, что приводит к большим головным болям, когда происходит неизбежное изменение.

Одним из широко распространенных альтернативных подходов является объектно-ориентированная парадигма, которая предполагает, что данные (или переменные) имеют первый приоритет и должны быть тщательно защищены, тогда как функции «возвращают» данные с помощью подпрограмм, которые обрабатывают их ввод и вывод. ООП приводит к другому подходу к разработке приложений, так как в рамках этой парадигмы разработчики больше заботятся о том, что входит и что выходит, чем о конкретном потоке пакета процедур. ООП доказал успешный подход к работе с изменениями, помогая разработчикам «абстрагировать» элементы приложения, которые могут изменяться, компилируя их в четко определенные модули, которые легко обслуживать.

Шаблоны проектирования

Возможно, наибольшим успехом объектно-ориентированной парадигмы является понятие шаблонов проектирования . Попытка отдать должное шаблонам проектирования в коротком абзаце — это не то, что я собираюсь предпринять (если вы хотите получить какое-то мнение, попробуйте Advanced PHP Forum ), но в целом аргумент «дизайн мертв» также может быть применен к программирование. Шаблоны проектирования представляют собой обобщенный опыт ведущих мировых разработчиков программного обеспечения и позволяют таким разработчикам, как вы и я, учиться на чужих успехах, а не тратить время на мучительные уроки на собственных ошибках.

Некоторые говорят, что поддержка ООП в PHP4 была добавлена ​​в качестве запоздалой мысли. Конечно, по сравнению с таким языком, как Java, PHP4 реализует только самые элементарные языковые функции, чтобы сделать возможным объектно-ориентированное программирование. Возможно, показателем проблемы является то, как ссылки работают в PHP4 ( больше информации здесь ) — по сути, они работают так, что это прямая противоположность такого языка, как Java. Ссылки на PHP4, без сомнения, смутили всех, от новичков, делающих следующий шаг от HTML, до опытных разработчиков из Java, C ++ и других областей.

Опытные разработчики PHP4 зарекомендовали себя в достижении высокой степени абстракции в своих проектах, что привело к созданию мощных и гибких приложений, таких как eZ publish и Krysalis , но степень дисциплины, необходимая для достижения этого уровня сложности, огромна. Более того, в том, что касается применения шаблонов проектирования, PHP4 часто требует некрасивых, нестандартных обходных путей (например, шаблон Singleton ).

Эта комбинация факторов влияет на общий «опыт разработки» с PHP4. Для большой библиотеки классов проблемы усугубляются, что затрудняет разработку действительно надежных, связных библиотек, выдерживающих испытание временем.

Обратно в реальность

Теперь, это все очень хорошо в теории. Вскоре мы все можем говорить о рентабельности инвестиций в наши системы управления контентом (которые мы взломали однажды вечером), о росте бороды и развитии серьезного поведения. Но позвольте мне поставить все это по-другому …

Возможно, вопрос № 1, который подчеркивает недостаток в построении современных PHP-приложений: «Как мне интегрировать остальную часть моего сайта с phpBB / vBulletin / Invision Board / *** вставить PHP форум сюда ***?» Вообще говоря, ответ «взломать!»

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

В результате большинство современных PHP-проектов начинаются более или менее с нуля, с внедрения систем аутентификации, логики обработки форм, механизмов шаблонов и многого другого — чего еще не делали тысячи других разработчиков. Частично проблема заключается в том, что объектная модель PHP4 лишь частично преуспела в содействии развитию стандартных компонентов приложения. Репозитории, такие как PEAR и PHP Classes, подчеркивают как успех, так и неудачу объектной модели PHP4.

Суть в том, что разработчики PHP тратят впустую много часов, теряя свои волосы, поскольку они без необходимости заново изобретают колеса. PHP5 вполне может быть тем тоником для волос, который вы ищете …

Обработка ошибок

Хотя я провожу грязное бельё в PHP4, другой недостаток — это способ, которым обычно обрабатываются ошибки.

То, как ваш код реагирует, когда что-то идет не так (как это неизбежно будет), очень важно. Например, представьте, что ваш сервер MySQL на мгновение «отключился». Неужели посетитель вашего сайта только что потерял обширную детальную рассылку, которую собирались опубликовать на вашем форуме?

Сегодняшние разработчики PHP приняли много разных подходов к обработке ошибок. Некоторые разработали относительно сложные механизмы обработки ошибок (например, PEAR Error ). Другие просто полностью игнорируют обработку ошибок, кроме случайного die (), когда кто-то идет не так, как надо.

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

Хорошая новость в том, что у PHP5 есть ответ!

Поддержка XML

Учитывая, что рендеринг некоторого подмножества XML (например, HTML) — это то, чем на самом деле занимается PHP, его разная поддержка XML оставляет определенную возможность для улучшения.

Сегодня PHP использует три набора сторонних библиотек для реализации XML:

  • Парсер Expat SAX Джеймса Кларка
  • библиотека libxml проекта Gnome для обеспечения парсера DOM
  • Саблотронная библиотека Ginger Alliance для XSLT

Из трех, только расширение Sax — это то, на что PHP-разработчики могут положиться на 100%. Расширение XSLT довольно солидно, хотя иногда возникали ошибки, связанные с платформой, и это расширение широко не поддерживается веб-хостами. Расширение PHP DOM XML является самым слабым звеном в результате многочисленных ошибок и изменений API и остается экспериментальным на сегодняшний день.

Проблема с использованием трех отдельных сторонних библиотек заключается в необходимости обслуживания группы PHP. Expat стабилен и практически не меняется, но имеет ограниченный набор функций, в то время как libxml и Sablotron все еще развиваются. Попытка поддерживать параллельные расширения PHP, которые их используют, — головная боль. В PHP5 были заложены основы для обеспечения исключительной поддержки XML в PHP, как мы вскоре увидим.

С этим у меня на груди пришло время прокатиться с PHP5 …

Тест-драйв

Как следует из предыдущего обсуждения, новые функции, которые предоставляет PHP5, — это то, что вы могли бы назвать «продвинутым», с точки зрения того, как мы используем PHP в качестве языка. Если вы еще не привыкли к объектной модели PHP4 или у вас нет опыта использования ООП на другом языке, вам придется простить меня, если приведенные ниже примеры перестанут быть у вас над головой. Но если вы затормозили в изучении ООП в PHP, сейчас самое время начать, так как синтаксис версии 4 довольно прост.

Справка доступна в виде набора расширенных ресурсов PHP , а также статьи Кевина Янка « Объектно-ориентированный PHP: наборы результатов пейджинга» , которая служит отличным учебником по синтаксису классов PHP4. Для более углубленного изучения объектно-ориентированного программирования я рекомендую « Мыслить на Java» Брюса Экеля (доступно бесплатно в электронном виде). В случае, если вам интересно, почему я рекомендую книгу по Java для программистов PHP, «Мышление в Java» дает очень твердое резюме всех фундаментальных аспектов объектно-ориентированной парадигмы, а код, который иллюстрирует их, прост и понятен. смысл. Синтаксис Java достаточно близок к PHP4 с точки зрения ООП, для тех, кто разбирается в синтаксисе PHP, чтобы понять, что делает Java.

Тем не менее, если ООП действительно отключит вас, в PHP5 есть несколько других новых функций, которые могут вас заинтересовать, в частности области SQLite, обработки исключений и SimpleXML, о которых я расскажу чуть позже.

Когда дело доходит до установки PHP5, я собираюсь оставить его на Advanced PHP Forum, чтобы помочь вам. Здесь вы найдете людей, которые успешно установили его под Linux, Mac OSX и Windows. Мне удалось успешно установить под Suse 8.1 Linux и Windows 2000, процесс был относительно безболезненным и практически таким же, как с PHP4 (подробнее см. Руководство по установке ). Я столкнулся с несколькими проблемами с Windows XP, где Apache зависал при запуске любых PHP-скриптов, хотя эта проблема может быть связана с моей системой.

Один из советов для пользователей Windows (который называется «Быстро и грязно») — скопировать iconv.dll из php5 / dlls в каталог php5 / sapi (чтобы справиться с тем фактом, что PHP не может найти php4apache.dll) ,

Что касается конфигурации Apache, сначала убедитесь, что вы используете версию Apache 1.3.x (поскольку PHP4 и 5 не были объявлены стабильными с Apache 2.x). В httpd.conf, где для PHP4 у вас обычно было бы что-то вроде:

 LoadModule php4_module libexec/libphp4.so" # Unix  #LoadModule php4_module "c:/php4/sapi/php4apache.dll" # Windows  

Теперь у вас есть:

  LoadModule php5_module libexec/libphp5.so" # Unix  #LoadModule php5_module "c:/php4/sapi/php4apache.dll" # Windows  

Обратите внимание, что в Windows вы все еще используете php4apache.dll с PHP5 (нет, это не опечатка).

Помните, что пример кода, который я покажу вам здесь, может оказаться недействительным, когда PHP5 достигнет полной версии. Полный код доступен в виде ZIP в конце этой статьи.

SQLite

Для того, чтобы набрать обороты, первая большая новость заключается в том, что PHP5 поставляется с собственным встроенным ядром базы данных под названием SQLite, который вы можете начать использовать с момента установки PHP.

Ошеломленный?

SQLite — это легкий, общедоступный механизм баз данных, написанный на C, разработанный Д. Ричардом Хиппом из Hipp, Wyrick & Company, Inc., и свободно доступный по адресу http://www.hwaci.com/sw/sqlite/. ,

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

SQLite не предназначен для замены существующих серверов баз данных, таких как MySQL и Postgresql.

Если вы думали, что MySQL является элементарным с точки зрения того, что он предлагает (например, отсутствие триггеров, хранимых процедур и т. Д.), SQLite удастся сделать его многофункциональным. Для SQLite это скорость и возможность хранить данные как в файлах, так и в памяти. Тесты показывают, что он примерно в два раза быстрее MySQL для обычных операций, и MySQL определенно не медленный.

Некоторыми из задач, для которых я мог бы рассмотреть возможность установки SQlite, может быть информация о конфигурации приложения, хранение сеансов, хранение сериализованных объектов между запросами страниц и, возможно, хранение информации для входа пользователя в зависимости от дизайна приложения. Буду ли я использовать его в качестве основного хранилища данных, еще неизвестно — я не видел, как SQLite стоит на живом веб-сайте с большим трафиком. Джон Лим из PHP Everywhere имеет некоторые интересные мысли о SQLite .

Вот как вы можете использовать SQLite с PHP5. Обратите внимание, что это не будет обширное учебное пособие, но оно призвано дать вам приблизительное представление о том, как оно работает. Прочитайте FAQ по SQLite и документацию по SQL для получения дополнительной информации. Сейчас нет официальной документации по PHP (кроме этой презентации ), но я обнаружил, что реализация (с точки зрения функций PHP) соответствует интерфейсу SQLite C.

 <?php  // Create SQLite Database and Table   // Display some version information  echo ( 'SQLite Version: '.sqlite_libversion().'<br />');  echo ( 'SQLite Encoding: '.sqlite_libencoding().'<br />');   // The file path to the database  $sqliteDb='/www/sitepoint/php5/sitepoint.sqlite';   // Connect to the database (creates the file)  if ( !$db = sqlite_open($sqliteDb, 0666, $err) )    die($err);   // A query to create a table  $sql = "CREATE TABLE            users                (                id INTEGER PRIMARY KEY,                login STRING UNIQUE,                password STRING,                email STRING                )";   // Run the query  if ( !sqlite_query($sql, $db) )    // Die if errors happen, displaying the error message    die(sqlite_last_error($db).': '.        sqlite_error_string(sqlite_last_error($db)));   echo ( "Database $sqliteDb created successfully" );   // Close the connection  sqlite_close($db);  ?>  
Скрипт: sqlite_create.php

В приведенном выше примере создается таблица «users» в файле базы данных «/www/sitepoint/php5/sitepoint.sqlite» (файл создается автоматически, если его не существует).

Теперь, чтобы положить некоторые данные в таблицу;

  <?php  // Insert some data into the table   // Connect to the database  $sqliteDb='/www/sitepoint/php5/sitepoint.sqlite';  if ( !$db = sqlite_open($sqliteDb, 0666, $err) )    die($err);   // Some data to insert  $users = array(    array(        'login'=>'jbloggs',        'password'=>md5('secret'),        'email'=>'[email protected]'        ),    array(        'login'=>'jsmith',        'password'=>md5('secret'),        'email'=>'[email protected]'        ) );   foreach ( $users as $user ) {    // An INSERT query    $sql = "INSERT INTO                users (login, password, email)            VALUES                (                    '".$user['login']."',                    '".$user['password']."',                    '".$user['email']."'                )";     // Perform the query    if ( !sqlite_query($sql, $db) )        // Die if errors happen, displaying the error message        die(sqlite_last_error($db).': '.            sqlite_error_string(sqlite_last_error($db)));  }  echo ( 'Values inserted successfully' );   // Close connection  sqlite_close($db);  ?>  
Скрипт: sqlite_insert.php

Поскольку столбец «id» является целочисленным первичным ключом, SQLite обрабатывает автоматические приращения для меня (например, MySQL).

Наконец, я выбираю некоторые данные из таблицы;

  <?php  // Performs a select on the table   // Connect  $sqliteDb='/www/sitepoint/php5/sitepoint.sqlite';  if ( !$db = sqlite_open($sqliteDb, 0666, $err) )    die($err);   // Select the data  $sql = "SELECT            *        FROM            users";   // Get the result  if ( !$result = sqlite_query($sql, $db) )    // Die if errors happen, displaying the error message    die(sqlite_last_error($db).': '.        sqlite_error_string(sqlite_last_error($db)));   echo ( '<h2>User List</h2>' );   // Fetch the results into an array, row by row  while ($row = sqlite_fetch_array($result, SQLITE_ASSOC)) {    echo ( $row['id'].'. <b>Login:</b> '.$row['login'].           ' <b>Email:</b> '.$row['email'].'<br />' );  }   // Close connection  sqlite_close($db);  ?>  
Скрипт: sqlite_select.php

Это довольно просто - более или менее похоже на работу с MySQL в PHP.

Как уже упоминалось, SQLite также может хранить данные в памяти, что может предложить альтернативу функциям разделяемой памяти PHP, которые никогда не работали в Windows. Он также имеет альтернативный объектно-ориентированный API по сравнению с функциями PHP, которые я использовал выше. Смотрите эту презентацию для получения дополнительной информации.

Объектная модель PHP5

Во-первых, предупреждение - с этого момента все становится более интенсивным. Есть много оснований, и я предполагаю, что вы знакомы с ООП, а также имеете общее представление о том, как обстоят дела в PHP4 сегодня. Если вы хотите больше подробностей, пожалуйста, не стесняйтесь добавлять к обсуждению в конце этой статьи. Главным образом, я оставлю это самому коду, чтобы говорить за себя, поэтому вам, вероятно, придется изучить его довольно тщательно. Не стесняйтесь оставлять вопросы в обсуждении в конце этой статьи или на форумах Advanced PHP, если что-то неясно.

Если вы когда-либо работали с Java, объектная модель PHP5 будет вам очень знакома. Это не значит, что это так же, как Java; Существуют значительные различия с точки зрения удобства для разработчиков и того факта, что PHP является динамически типизированным языком.

Здесь я возьму вас в тур с примерами. В сети уже есть несколько ресурсов (см. Конец этой статьи), которые предлагают больше информации.

Частный, охраняемый и публичный

Что касается, возможно, жалобы № 1, направленной на PHP4, теперь вы можете объявить переменные-члены и методы в вашем классе как «запрещенные» для кода, который является внешним по отношению к классу. С PHP4 вы могли бы справиться с некоторой самодисциплиной, но для некоторых (возможно, тех, кому не хватает необходимой дисциплины!) Этого было недостаточно. Таким образом, с помощью PHP5 теперь вы можете защитить внутренние объекты от внешнего мира, предоставляя доступ только через определенный вами API-интерфейс (Application Program Interface).

Частный (и публичный)?

Вот и пример использования частного ключевого слова для защиты переменной класса и метода класса;

  <?php  class Color {    // Available only from within the class    private $rgb = array();     // Note "public" and "var" are basically the same thing    public $colorname = '';     // This method is only available from within the class    private function setRGB ($rgb) {        $this->rgb=$rgb;    }     // "public" is optional    public function setColor($color) {        $colorMap = array (            'white' => array ('r'=>255,'g'=>255,'b'=>255),            'gray' => array ('r'=>190,'g'=>190,'b'=>190),            'yellow' => array ('r'=>255,'g'=>255,'b'=>0),            'black' => array ('r'=>0,'g'=>0,'b'=>0)            );         // Use private method        $this->setRGB($colorMap[$color]);        $this->colorname = $color;    }     // More public methods    function r() {        return $this->rgb['r'];    }    function g() {        return $this->rgb['g'];    }    function b() {        return $this->rgb['b'];    }     function name() {        return $this->colorname;    }  }   $color = new Color();   # Private property - FATAL Error!  // $color->rgb = array ('r'=>255,'g'=>255,'b'=>0);   # Private method - FATAL Error!  // $color->setRGB(array ('r'=>255,'g'=>255,'b'=>0));  $color->setColor('yellow');   echo ( 'Yellow is made from:<br />' );  echo ( 'Red: '.$color->r().' ' );  echo ( 'Green: '.$color->g().' ' );  echo ( 'Blue: '.$color->b().' ' );  ?>  
Скрипт: private.php

Обратите внимание, что в приведенном выше примере я также использовал ключевое слово public, чтобы показать, что это возможно. По сути, «public» является необязательным, так как любой метод или переменная класса, которые не объявлены как «private» или «protected», по умолчанию имеют значение «public» (с учетом обратной совместимости).

Все, что объявлено как «личное», доступно только внутри класса, в котором оно объявлено. Это означает, что подклассам также запрещен доступ. Если вы создадите подкласс, вы можете объявить методы и переменные с одинаковыми именами, но они будут отделены от сущностей, объявленных в родительском объекте.

защищенный

Вот пример с защищенной переменной;

  <?php  class Color {    // Accessible only inside this class and subclasses of this class    protected $rgb = array();    var $colorname = '';     private function setRGB ($rgb) {        $this->rgb=$rgb;    }     function setColor($color) {        $colorMap = array (            'white' => array ('r'=>255,'g'=>255,'b'=>255),            'gray' => array ('r'=>190,'g'=>190,'b'=>190),            'yellow' => array ('r'=>255,'g'=>255,'b'=>0),            'black' => array ('r'=>0,'g'=>0,'b'=>0)            );         // Use private method        $this->setRGB($colorMap[$color]);        $this->colorname = $color;    }     function r() {        return $this->rgb['r'];    }    function g() {        return $this->rgb['g'];    }    function b() {        return $this->rgb['b'];    }     function name() {        return $this->colorname;    }  }   class RedFilter extends Color {    function setColor($color) {        parent::setColor($color);        $this->rgb['r'] = 0;    }  }   $color = new RedFilter;   # Protected property - FATAL Error!  // $color->rgb = array ('r'=>255,'g'=>255,'b'=>0);   $color->setColor('yellow');   echo ( 'Yellow filtered by Red is made from:<br />' );  echo ( 'Red: '.$color->r().' ' );  echo ( 'Green: '.$color->g().' ' );  echo ( 'Blue: '.$color->b().' ' );  ?>  
Скрипт: protected.php

Защищенная переменная (или метод) доступна для подкласса.

Конструкторы и деструкторы

PHP5 предлагает альтернативу PHP4 для метода конструктора класса. Вместо того, чтобы давать конструктору то же имя, что и сам класс, вы можете использовать метод __construct() в качестве конструктора. Преимущество этого состоит в том, что если вы переименуете класс, вам не нужно переименовывать конструктор (или любой код в подклассах переименованного вами класса). Обратите внимание, что вы все еще можете использовать старый подход к конструкторам (обратная совместимость сохраняется).

Вот пример:

  <?php  class Foo {    var $variable;    /**     * Constructors now have the common __construct()     * function.     */    function __construct() {        $this->variable = 'Something';    }  }   echo 'Constructing Foo with the new __construct()<br />';  $f = new Foo();   echo ( $f->variable );  ?>  
Скрипт: constructor.php

PHP5 также вводит метод деструктора __destruct() , который вы можете использовать, чтобы убедиться, что объект должным образом «очищен» (например, закрывает соединение с базой данных), как только вы закончите с ним. Механизм сборки мусора в PHP вызовет деструктор, когда удалит объект из памяти; Кроме того, вы можете вызвать деструктор прямо из вашего кода.

Например:
<?php class File { var $resource; function __construct($name) { $this->resource = fopen($name,'r'); } function read() { if ( !feof($this->resource) ) return fgets($this->resource); else return false; } function __destruct() { fclose($this->resource); } } $file = new File('example.html'); echo ('<pre>'); while ( $contents = $file->read() ) { echo ( htmlspecialchars($contents) ); } echo ('</pre>'); ?>
Скрипт: destructor.php

Приведенный __destruct() метод __destruct() гарантирует, что открытый файл будет закрыт, когда объект уничтожен сборщиком мусора PHP.

Обратите внимание, что сам вызов __destruct() самом деле не удаляет объект из памяти - он просто выполняет код, который вы определили с помощью __destruct() . В первоначальном обзоре движка Zend 2 [PDF] говорилось об операторе удаления для удаления объектов из памяти; мои попытки использовать его с бета-версией привели к синтаксическим ошибкам.

абстрактный

PHP5 формализовал абстрактные классы и методы на уровне движка. Абстрактный класс (или метод) - это класс, который не должен использоваться напрямую; вместо этого его следует использовать через конкретный подкласс. Смысл в наличии абстрактных классов состоит в том, чтобы позволить группе подклассов совместно использовать родительскую реализацию, одновременно предупреждая других разработчиков не использовать родительский объект напрямую. Например, у вас может быть абстрактный класс HTML_Widget , который расширяется такими классами, как HTML_Table и HTML_Form ; Вы хотите, чтобы люди использовали только подклассы, а не самого родителя.

Обычное соглашение PHP4 заключалось в том, чтобы помещать операторы die() в классы и методы, которые должны были быть абстрактными, но в PHP5 у нас теперь есть стандартный подход (что является еще одной хорошей вещью).

Вот пример:

  <?php  abstract class Senior {    protected $speech = 'Hello World!';     function speech() {        return $this->speech;    }  }   class Junior extends Senior {    protected $speech = 'Goodbye World!';     abstract function think() {        sleep(5);    }  }   # Attempt to instantiate abstract class: FATAL Error!  // $g = new Senior();  $g = new Junior();   # Attempt to instantiate abstract method: FATAL Error!  // $g->think();   echo ( $g->speech() );  ?>  
Скрипт: abstract.php

Вы получите фатальные ошибки, если попытаетесь создать экземпляр абстрактного класса Senior или метод think() класса Junior.

Интерфейсы

Интерфейсы - это новая особенность PHP5, которая была возможна для дисциплинированных разработчиков, использующих PHP4, но только в качестве свободной договоренности.

Интерфейсы по сути являются «контрактом», которому должен подчиняться любой конкретный класс, реализующий интерфейс. Преимущество наличия интерфейсов состоит в том, что они позволяют разработчикам указывать свои намерения в библиотеке классов и, таким образом, помогают другим разработчикам, которые добавляют свой собственный код, соответствовать стандартам библиотеки. Интерфейсы также полезны, когда необходимо идентифицировать объект с помощью самоанализа.

Самоанализ - это способность вашего кода проверять данные во время выполнения и определять тип, доступные методы (если это объект) и так далее. PHP уже предоставляет ряд функций самоанализа, таких как is_a и новое ключевое слово с PHP5, «instanceof», которое фактически делает то же самое, что is_a (), но должно улучшить читаемость. Интроспекция может получить гораздо больше функций к тому времени, когда PHP5 станет стабильным.

Класс интерфейса просто объявляет набор имен методов без методов, имеющих тело. Например:

  <?php  interface Iterator {    function fetch();    function howMany();  }   class Presidents implements Iterator {    private $presidents = array();    function __construct() {        $this->presidents = array (            'Jimmy Carter','Ronald Reagan','George Bush',            'Bill Clinton','George W. Bush'        );    }    function fetch() {        $president = each($this->presidents);        if ( $president ) {            return $president['value'];        } else {            reset ( $this->presidents );            return false;        }    }     # Commented out to produce error    /*    function howMany() {        return count($this->presidents);    }    */  }   #Fatal Error - Presidents does not implement the howMany() method in Iterator!  $presidents = new Presidents();   while ( $president = $presidents->fetch() ) {    echo ( $president.'<br />' );  }  ?>  
Скрипт: interface.php

В приведенном выше примере интерфейс Iterator определяет два метода, которые должны обеспечивать реализующие его классы. Это зависит от реализующего класса, чтобы обеспечить логику для методов. Поскольку я закомментировал метод howMany() в классе Presidents, когда я его howMany() PHP выдает мне фатальную ошибку, напоминающую, что мне нужно снова сделать метод howMany() доступным.

Примечание: что касается Итераторов, см. «Это не все, ребята ...» далее в этой статье.

В то время как PHP5 развивался, был некоторый аргумент по поводу множественного наследования (как в случае с C ++) и интерфейсов (способ Java). Многократное наследование (расширение нескольких родительских классов), возможно, более мощное, но оно также вносит гораздо большую сложность в язык и (возможно) часто приводит к плохому дизайну. Группа PHP выбрала подход Java, который может не понравиться всем, но, безусловно, разумен.

Лично я думаю, что интерфейсы - лучший путь; PHP нужно больше сосредоточиться на стандартизации, а не на выборе (которого он уже предлагает много). В то же время вопросы производительности, скорее всего, поднимут голову в отношении интерфейсов, поскольку PHP интерпретируется, а не компилируется.

Для получения более подробной информации об интерфейсах и множественном наследовании попробуйте это обсуждение и статью, на которую оно ссылается .

перегрузка

Перегрузка объектов в PHP4 стала возможной благодаря (экспериментальному) расширению перегрузки , которое вы можете найти более подробно здесь . В PHP5 перегрузка стала центральной особенностью языка и, несомненно, окажется важной при работе с веб-сервисами, а также при интеграции с другими платформами, такими как Java и .NET.

Перегрузка в контексте PHP отличается от перегрузки методов в (статически типизированных) языках, таких как C ++ и Java. PHP предоставляет функцию func_num_args () , которую можно комбинировать с самоанализом типа, например is_int (), если вам нужно добиться того же эффекта. Однако на практике, поскольку PHP динамически типизирован, вам редко требуется перегрузка методов в стиле Java / C ++.

В PHP перегрузка означает возможность вызова методов и свойств объекта, которые не были явно объявлены в классе. PHP позволяет использовать три «магических» метода __get() , __set() (оба из которых применяются к свойствам объекта) и __call() (который применяется к методам объекта), в которых можно разместить код для обработки «неожиданного» вызова ,

Вот пример использования __call() в PHP5 для разрешения __call() функций PHP через объект:

  <?php  class MyString {    private $string;    function __construct($string) {        $this->string = $string;    }    function __call($method,$params) {        switch ($method) {            case'strlen':                return strlen($this->string);            break;            case'substr':                return substr($this->string,$params[0],$params[1]);            break;            default:                return false;            break;        }    }  }   $myString = new MyString('Hello World!');   echo ( 'The string length is '.$myString->strlen().'<br />' );   echo ( 'Substr: '.$myString->substr(3,6).'<br />' );  ?>  
Скрипт: overload.php

Нативные функции PHP substr() и strlen() теперь можно вызывать через экземпляр класса MyString, без которого вам нужно явно объявить их как методы.

Немного украшения

Перегрузка может также использоваться для реализации шаблона Decorator (шаблон Decorator предоставляет альтернативу подклассам). Например:

  <?php  class FileList {    var $listing;    function __construct($path) {    $this->listing = array();    $path = realpath($path);    $dir = Dir($path);    while (false !== ($entry = $dir->read())) {      if ( is_file($path.'/'.$entry) ) {        $file = array();        $file['name'] = $entry;        $file['size'] = filesize($path.'/'.$entry);        $file['ctime'] = filectime($path.'/'.$entry);        $file['atime'] = fileatime($path.'/'.$entry);        $this->listing[]=$file;      }    }    }  function fetch() {    $file = each ( $this->listing );    if ( $file ) {      return $file['value'];    } else {      reset ( $this->listing );      return false;    }  }  function getFileByName($name) {    foreach ( $this->listing as $file ) {      if ( $file['name'] == $name ) {        return $file;      }    }    return false;  }  }   class FileSortDecorator {  var $fileList;  function __construct($fileList,$sortBy='name') {    $this->fileList = $fileList;    $sort = array();    foreach ( $this->fileList->listing as $file ) {      $sort[]=$file[$sortBy];    }    array_multisort($sort,$this->fileList->listing);  }  function __call($method,$params) {    return call_user_func_array(            array($this->fileList,$method),$params);  }  }   $fileList = new FileList('./');  $sortDecorator = new FileSortDecorator($fileList,'size');   echo ('<b>fetch:</b>');  while ( $file = $sortDecorator->fetch() ) {  echo ('<pre>');  print_r($file);  echo ('</pre>');  }   echo ('<b>getFileByName:</b><pre>');  print_r($sortDecorator->getFileByName('overload.php'));  echo ('</pre>');  ?>  
Скрипт: overload_decorator.php

Класс FileSortDecorator decorates класс FileList путем сортировки списка файлов по определенному ключу массива. В то же время он позволяет FileList методы FileList через него с помощью __call() .

Предупреждение: перегрузка очень мощная, но в большинстве случаев будет «взломать». Например, как вы можете выполнить самоанализ для перегруженного класса? Маркус Бейкер, автор превосходной платформы Simple Test Framework для модульного тестирования PHP, поднял некоторые очень веские опасения по поводу перегрузки PHP здесь .

Помимо интеграции с другими платформами и взлома, перегрузка предоставляет разработчикам PHP некоторые интересные возможности применить Aspect Oriented Paradigm (как Маркус упоминает в своем посте) и реализовать что-то вроде метаклассов Python .

Примечание: PHP не поддерживает перегрузку операторов (поэтому нет $myObject++ ).

Статический, окончательный и постоянный

PHP5 предоставляет еще три важных ключевых слова; статический, окончательный и постоянный.

статический

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

Вот статическая переменная-член класса:

  <?php  class MyStatic {    static $foo;    var $bar;  }   MyStatic::$foo = 'Red';   # Fatal error: Access to undeclared static property: mystatic::$bar  // MyStatic::$bar = 'Blue';   echo ( MyStatic::$foo );  ?>  
Скрипт: static_var.php

Что касается методов класса, ключевое слово static менее важно, так как методы в любом случае могут вызываться статически (в противном случае PHP5 нарушит большую обратную совместимость с PHP4):

  <?php  class MyStatic {    static function Foo() {        return 'This is foo()';    }    function Bar() {        return 'This is bar()';    }  }   echo ( MyStatic::foo().'<br />' );  echo ( MyStatic::bar().'<br />' );   $obj = new MyStatic();   # Fatal error - cannot call static method via object instance  // echo ( $obj->foo().'<br />' );  echo ( $obj->bar().'<br />' );  ?>  
Скрипт: static_method.php

По сути, все методы могут быть вызваны статически в PHP5 в любом случае, как это было возможно в PHP4. Однако ключевое слово static предотвращает вызов метода, объявленного вместе с ним, через экземпляр объекта, как показано в примере.

Синглтон

Одним из преимуществ ключевого слова static является то, насколько легко оно реализует шаблон Singleton:

  <?php  class Singleton {    /**    * The singleton instance is stored here    */    static private $instance = false;     private $text = 'Empty message';     /**    * Make the constructor private to prevent the class being    * instantiated directly    */    private function __construct() {}     /**    * Use this static method to get a singleton instance    */    static function instance() {        if(!Singleton::$instance) {            Singleton::$instance = new Singleton();        }        return Singleton::$instance;    }     function setText($text) {        $this->text = $text;    }     function getText() {        return $this->text;    }  }   class Hello {    function __construct() {        $single = Singleton::instance();        $single->setText('Hello World!');    }  }   class Goodbye {    function __construct() {        $single = Singleton::instance();        $single->setText('Goodbye World!');    }  }   $single = Singleton::instance();   echo ( $single->getText().'<br />' );   $hello = new Hello();   echo ( $single->getText().'<br />' );   $hello = new Goodbye();   echo ( $single->getText().'<br />' );  ?>  
Скрипт: static_singleton.php

Когда вы запустите этот скрипт, вы заметите, что, хотя я каждый раз вызываю один и тот же метод по одной и той же ссылке на объект ( $single->getText() ), конструирование классов Hello и Goodbye изменяет вывод. Это потому, что все они работают с одной и той же копией объекта (Singleton). Одиночные могут быть полезны, когда у вас есть класс, который нужно использовать многим объектам (возможно, соединение с базой данных), но вы не хотите иметь несколько экземпляров объекта (например, вы не хотите подключаться к базе данных 10 раз). Наличие ключевого слова static позволяет разработчикам PHP стандартизировать классы Singleton, а не прибегать к обходным решениям, необходимым в PHP4.

окончательный

Финальный ключик
J