Пространства имен и автозагрузчики классов – два важных инструмента, предлагаемых PHP, которые WordPress-разработчики должны использовать в своих интересах. Я уже писал о том, почему это нужно делать, опубликовав краткое введение, раскрывающее основы использования данных инструментов. В этой статье будет предложено всестороннее введение в пространства имен PHP.
Пространства имен – это более качественная, более гибкая версия использования уникальных предпочтений в ваших именах классов. Кроме того, они помогают структурировать ваши каталоги и позволяют вам в полной мере воспользоваться всеми плюсами автозагрузчиков, которые следуют за последними стандартами, как, к примеру, автозагрузчик Composer.
Я предполагаю, что вы уже знакомы с основами объектно-ориентированного программирования на PHP. Если нет, то прочтите следующую статью.
Я также исхожу из предположения, что вы используете как минимум PHP 5.3. Если вы по-прежнему сидите на версии PHP 5.2, то в таком случае вы должны реально переходить на новую версию, поскольку версия PHP 5.2 медленная и небезопасная. Учтите, что если вы будете применять советы, приведенные в руководстве, на практике в темах или плагинах, то в таком случае вы обязательно столкнетесь с пользователями, которые используют PHP 5.2; обращение к пространствам имен приведет к фатальным ошибкам для пользователей, причем они даже не будут знать, по какой причине.
Пространства имен для вашего класса
Я собираюсь показать вам все особенности использования пространств имен. В этих примерах давайте предположим, что плагин называется Fun Machine.
Вот как будет выглядеть типичный класс после применения стандартов именования классов WordPress:
<?php class Fun_Machine_Shortcode { /** * Process the shortcode * * @param $atts * * @return string */ public static function the_shortcode( $atts ) { $atts = shortcode_atts( array( 'foo' => 'fighter', 'dave' => 'grohl' ), $atts, 'fun-machine' ); return self::shortcode_callback( $atts['foo'], $atts['dave'] ); } /** * Callback for shortcode * * @param string $foo * @param string $dave * * @return string */ public static function shortcode_callback( $foo, $dave ) { return $foo.$dave; } } add_shortcode( 'fun-machine', array( 'Fun_Machine_Shortcode', 'the_shortcode' ) );
Имя класса состоит из названия плагина и цели этого класса. Это имеет смысл, поскольку наименование класса только по его целям, как, к примеру, «shortcode», выльется в огромную проблему – два класса не могут иметь одно и то же имя. Что произойдет, если другой плагин добавит класс под названием shortcode? Появится фатальная ошибка, и оба разработчика плагинов будут виновны в этом.
Такая система становится слишком громоздкой, особенно если вам нравится работать с небольшими, узкоспециализированными классами. Вместо этого мы можем поместить данный класс в пространство имен «fun_machine». Вот класс в общих чертах, который содержит контент в пространстве имен:
<?php namespace fun_machine; class shortcode { //do the same stuff }
Теперь, когда у нас есть пространство имен, тот способ, который мы использовали для регистрации шорткодов (add_shortcode) в первом примере, не будет работать. Мы должны применить к нему пространство имен. Пространства имен разделяются при помощи левого слэша. Регистрация шорткода выглядела бы так:
add_shortcode( 'fun-machine', array( '\fun_machine\shortcode', 'the_shortcode' ) );
Если бы нам нужно было вызвать метод shortcode_callback в другом классе, мы бы поступили следующим образом:
\fun_machine\shortcode::callback( $foo, $dave );
Стартовый слэш требуется не всегда. Он помещает нас в глобальное пространство имен, однако это не требуется, если все происходит в том же самом пространстве имен.
Чтобы проиллюстрировать различие, давайте взглянем на три небольших класса.
Примечание: каждый из них должен быть в своем собственном файле, что я детально опишу в своей следующей статье про автозагрузчики.
<?php namespace fun_machine; class add_shortcode { /** * Process the "fun" shortcode * * @param $atts * * @return string */ public static function fun( $atts ) { $atts = shortcode_atts( array( 'foo' => 'fighter', 'dave' => 'grohl' ), $atts, 'fun' ); return shortcode_callbacks::fun( $atts['foo'], $atts['dave'] ); } } ?> <?php namespace fun_machine; class shortcode_callbacks { /** * Callback for "fun" shortcode * * @param string $foo * @param string $dave * * @return string */ public static function fun( $foo, $dave ) { return \less_fun\teeth::do_something_to_foo( $foo ); } } ?> <?php namespace less_fun; class teeth { /** * Does two fairly opposite things * * @param string $foo * * @return string */ public static function do_something_to_foo( $foo ) { return strtolower( strtoupper( $foo ) ); } }
В первом классе вызывается метод add_shortcode() из второго класса, и это работает точно так же, как и без пространства имен, поскольку они находятся в одном и том же пространстве имен. Во втором классе вызывается метод из третьего класса. Поскольку они стоят в разных пространствах имен, нам понадобится использовать полностью определенное пространство имен: \less_fun\teeth::do_something_to_foo.
Вложенные пространства имен
До сих пор мы использовали только одиночные пространства имен, однако пространства имен могут быть также вложенными. К примеру, мы можем иметь пространство имен shortcodes в главном пространстве имен fun_machine. Вот как выглядели бы в таком случае классы:
<?php namespace fun_machine\shortcode; class add_shortcode { /** * Process the "fun" shortcode * * @param $atts * * @return string */ public static function fun( $atts ) { $atts = shortcode_atts( array( 'foo' => 'fighter', 'dave' => 'grohl' ), $atts, 'fun' ); return shortcode_callbacks::fun( $atts['foo'], $atts['dave'] ); } } ?> <?php namespace fun_machine\shortcode; class shortcode_callbacks { /** * Callback for "fun" shortcode * * @param string $foo * @param string $dave * * @return string */ public static function fun( $foo, $dave ) { return \less_fun\teeth::do_something_to_foo( $foo ); } } ?>
Теперь для регистрации шорткода нам нужно ввести следующее:
add_shortcode( 'fun-machine', array( '\fun_machine\shortcode\add_shortcode', 'fun' ) );
Вложенные пространства имен помогают упростить работу класса на основе его пространств имен. Также они помогают группировать классы по целям и создавать логичную и непротиворечивую структуру файлов, что мы обсудим уже в следующей статье.
Использование псевдонимов (aliasing) для пространств имен
Если бы не было возможности задания псевдонимов для пространств имен, нам бы пришлось постоянно писать эти длинные названия пространств имен. К счастью, псевдонимы позволяют нам использовать методы класса в разных пространствах имен, используя только имя класса.
Псевдонимы задаются при помощи простого оператора use между объявлением пространства имен и началом класса. Вот класс shortcode_callbacks из прошлого примера, в котором мы настроили псевдоним класса \less_fun\teeth:
<?php namespace fun_machine; use \less_fun\teeth; class shortcode_callbacks { /** * Callback for "fun" shortcode * * @param string $foo * @param string $dave * * @return string */ public static function fun( $foo, $dave ) { return teeth::do_something_to_foo( $foo ); } } ?>
Как вы можете видеть, я добавил оператор use, и потому я смог изменить строку return \less_fun\teeth::do_something_to_foo( $foo ); на строку return teeth::do_something_to_foo( $foo );. Если данный класс используется более одного раза, то это может заметно упростить работу.
Заключение
Этого достаточно, чтобы начать использовать пространства имен в своих проектах WordPress. После применения нескольких новых концепций ваш код станет более простым и структурированным.
Теперь, когда мы разобрались с пространством имен, самое время перейти к автозагрузчикам классов. Мы это сделаем уже в следующей статье.
Источник: http://torquemag.io