Статья размещена автором Бетке Сергей Сергеевич

Лямбда-функции, замыкания и классы PHP 5.3

В WordPress повсеместно используется механизм функционалов (и callback аргументов соответственно, хотя – очень грубое и ограниченное “пояснение”). В результате мы получаем избыточный код (далее приведу пример). Возникла надежда, что с выходом PHP 5.3 лямбда функции решат проблему, но не тут-то было… Разберёмся.

Как и обещал, приведу сначала пример избыточного, навязанного функционалами и механизмом событий (action и filter) WordPress:

      add_settings_section(
         self::$_namespace . '_location_options',
         __('Location of your opensearch.xml file', self::$_domain),
         array(__CLASS__, 'option_location_options_description'),
         self::$_namespace . '_options_page'
      );

   ...

   public static function option_location_options_description() {
      ?>
         <p><?php _e('You can select location of your opensearch.xml file and his url, or leave automatic detection.', self::$_domain); ?></p>
      <?php
   }

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

С выходом PHP 5.3 появилась надежда на то, что механизм лямбда функций и замыканий избавит нас от подобной избыточности. Надежда выражалась в том, что приведённый выше пример можно будет переписать следующим образом:

      add_settings_section(
         self::$_namespace . '_location_options',
         __('Location of your opensearch.xml file', self::$_domain),
         function () { ?>
            <p><?php _e('You can select location of your opensearch.xml file and his url, or leave automatic detection.', self::$_domain); ?></p>
         <?php },
         self::$_namespace . '_options_page'
      );

Спешу Вас огорчить – код нерабочий. Лямбда функции работают, и замыкания – также работают. Но созданная через замыкание функция не становится методом класса! Да, при создании замыкания в методе объекта (не статическом методе класса), $this доступна в пределах замыкания даже без явного “импорта”, но код замыкания имеет права доступа к методам и полям объекта как внешний по отношению к классу код! то есть – только к публичным членам!

Ещё хуже, если мы создаём замыкание в статическом методе класса. Как Вы уже поняли, self:: в пределах замыкания использовать не удастся. Именно поэтому вышеприведённый код “не работает”.

Честно говоря, не понял, в связи с чем разработчики PHP не рассматривают замыкание, созданное кодом методов класса как метод класса, но при этом неявно связывают замыкание с $this. Явно напрашивается “внедрение” замыкания в класс с правом доступа к private и protected членам класса, использованием self:: и $this->.

P.S. Если Вы не используете классы PHP для создания пространства имён для Вашего плагина WordPress, тогда Вам действительно поможет сократить код и сделать его более “прозрачным” использование PHP 5.3 и его лямбда функций и замыканий. Если же Вы используете классы – Вам PHP 5.3 не поможет (а я так надеялся, скачал, поставил – и такой облом).

Будем надеяться, что PHP 5.4 наконец-то принесёт полноценные замыкания и в ООП программирование на PHP. Пока что “вывесил” это баг: http://bugs.php.net/bug.php?id=53610. Надеюсь, получу положительное решение проблемы.

Отзывы » (1)

  1. Сегодня пробежал ещё один комментарий на близкую тему.

    class Filter {
       public function filter($value = '') {
        return function() use ($value) {
         return $value;
        };
       }
    }
    
    class Test {
       private $_filter = null;
    
       public function test() {
        $filter = new Filter();
        $this->_filter = $filter->filter();
        echo 'filter data: ' . $this->_filter('my data'); //error
        $f = $this->_filter;
        echo 'filter data: ' . $f('my data'); //work
       }
    }
    
    $T= new Test();
    $T->test();
    

    Так что мы не одиноки с проблемами замыканий в PHP.

Опубликовать комментарий

XHTML: Вы можете использовать следующие HTML теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tags Связь с комментариями статьи:
RSS комментарии
Обратная ссылка