PHP _SELF в атрибуте формы action. Плагины WordPress PHP (хуки, фильтры, действия) Нежелательные моменты, связанные с переменной PHP _SELF

24.6K

Ни для кого не является секретом, что наиболее распространенным способом взаимодействия html-страницы с сайтом является форма. Форма (то есть, html-элемент образуемый тегом form) используется и бесплатными почтовыми службами, электронными магазинами и многими другими типами сайтов.

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


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

Под текстовыми полями в этой статье понимаются элементы, создаваемые тегам input со значением параметра type равным text и тегом textarea . Организовать обработку формы состоящей из нескольких таких полей проще всего. На листинге ниже приведен листинг с html-разметкой для такой формы.






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

Переключатели

Переключателями (checkbox ) в этой статье называются элементы, создаваемые тегам input со значением параметра type равным checkbox . Форма для использования переменного количества «переключателей » строится абсолютно так же. Обратите внимание, что выбор конкретного значения переключателя (то есть значение свойства value) не важен. Пример приведен в листинге ниже:






Однако обработка такой формы отличается от обработки, описанной для текстовых полей. В данном случае необходимо определить, включил или нет посетитель сайта тот или иной переключатель. Если включил — то соответствующий элемент массива существует, если нет — то отсутствует. В следующем листинге приведен пример PHP сценария, который распечатывает включенные переключатели:

Радио-кнопки

Перед тем как описывать обработку радио-кнопок необходимо вспомнить, как они работают. Суть радио-кнопок (элементы созданные тегами input со значением параметра type равным radio ) заключается в том что, выбирая одну кнопку, пользователь автоматически снимает выделение с другой кнопки из этого же набора. Кнопки объединяются в набор очень просто: у всех кнопок в наборе одно и тоже имя.

А вот значения (то есть параметры value ) у кнопок в наборе — разные. И на сайт будет отправлено значение выбранной кнопки с именем набора. Так же как и в случае с текстовыми полями и переключателями имена наборов радио-кнопок должны оформляться как имена элементов массива в PHP. Пример такой формы приведен в следующем листинге:

// первый набор кнопок
// второй набор кнопок
// третий набор кнопок

Обработка радио-кнопок объединяет идеи, использование при обработке, как текстовых полей, так и переключателей. Если автор html-страницы не установил значение по умолчанию, а пользователь не выбрал определенную кнопку в наборе радио-кнопок, то данный элемент будет отсутствовать в массиве (как для переключателей).

Мы создали фундамент для будущего плагина, который распознает система WordPress. Сегодня мы займемся непосредственно изменением базового функционала системы.

Поможет нам в этом система «хуков» (hooks), «событий» (actions) и фильтров (filters). Эти три понятия и есть основа каждого плагина для WordPress.

Hooks

В WordPress есть два типа хуков:

  • Action hook: помечает место в коде, которое выполняет определенное действие, например, необходимо внести какие-либо данные и сохранить в базе.
  • Filter hook: помечает фильтр, который будет изменять какое-либо значение (переменную), так что в дальнейшем код будет использовать модифицированное значение.
Actions

Работа с событиями (actions)

Общая логика управления событиями в WordPress проста:

  • Пометить место, где действие должно выполниться с помощью хука (action hook) с необходимыми параметрами.
  • Создать функцию, которая будет выполнять нужные действия, используя параметры переданные хуком.
  • Зарегистрировать событие, которое будет выполняться при срабатывании хука, с определенным приоритетом.
  • Когда WordPress загружает страницу и находит hook, система выполнит все функции, которые зарегистрированы на этот хук.
  • Для выполнения первого пункта система предоставляет функцию ‘do_action’:

    Do_action($tag, $arg_1, $arg_2, ... , $arg_n);

    Она принимает следующие аргументы: $tag – название “хука”, $arg_1, $arg_2, … , $arg_n – параметры, с которыми будет вызвана функция. Аргументов может быть любое количество, либо 0.

    Система сама по себе имеет много уже определенных хуков:

    Do_action("init");

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

    Do_action("save_post", $post_id, $post);

    В этом примере хук срабатывает при сохранении записи с двумя аргументами post_id — идентификатор записи и post — сама запись.

    Создание хуков доступно любому разработчику для создания собственного плагина (или темы). Благодаря этому мы имеем мощный инструмент для управления поведением системы.

    Do_action("my_truly_custom_hook");

    Когда мы создали хук и написали функцию, нам необходимо зарегистрировать функцию с помощью «add_action»

    Add_action($tag, $function_to_add, $priority, $accepted_args_number);

    Функция ‘add_action’ принимает два обязательных параметра: $tag: название соответствующего хука и $function_to_add: имя функции, которую необходимо вызвать. Другие два параметра дополнительные: $priority: целочисленная переменная, которая определяет порядок выполнения функции (по-умолчанию — 10), $accepted_args_number: количество аргументов, которое принимает функция (по-умолчанию — 1).

    Рассмотрим пример, чтобы понять весь процесс. Допустим, мы хотим добавить небольшое уведомление внизу нашего сайта. Мы можем использовать хук ‘wp_footer’ для этого, потому что он является обязательной частью кода, который использует каждая тема.

    Function msp_helloworld_footer_notice(){ echo "Hello, I"m your custom notice"; } add_action("wp_footer", "msp_helloworld_footer_notice");

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

    Оповещение плагина WordPress

    Работа с фильтрами (filters)

    Фильтры работают по той же схеме, что и события. Но фильтры не просто выполняют определенный кусок кода, они изменяют значения, переданные им хуком. Это означает, что каждый фильтр имеет связанное с ним значение (переменную), с которым он работает.

    Функция-фильтр будет принимать это значение и преобразовывать его для дальнейшего использования. Хуки для фильтров немного отличаются от хуков для событий (action hooks).

    Apply_filters($tag, $value_to_filter, $arg_1, $arg_2, ... , $arg_n);

    Функция ‘apply_filter’ создает хук для фильтра с именем $tag и обязательным параметром $value_to_filter (он может быть пустым, но должен быть объявлен). Остальные аргументы необязательны работают так же как и для событий.

    Filter_function($value_to_filter, $arg_1, $arg_2, ... , $arg_n){ //фильтр return $value_to_filter; //значение необходимо вернуть }

    Это «скелет» фильтра, который демонстрирует, что фильтр должен:

  • принимать хотя бы 1 аргумент;
  • возвращать модифицированное значение.
  • add_filter($tag, $function_to_add, $priority, $accepted_args);

    Функция ‘add_filter’ регистрирует функцию с названием, содержащимся в $function_to_add для хука $tag. Остальные аргументы - $priority и $accepted_args — работают так же как и у хуков для событий.

    Рассмотрим пример: обычная для плагина задача — добавить что-нибудь в конец поста. Если подробнее рассмотреть функцию ‘the_content’, которая используется для вывода содержимого записи, мы найдем такой хук:

    $content = apply_filters("the_content", $content);

    Используя его мы можем легко добавить что-либо в конец поста.

    Function msp_helloworld_post_footer($content) { $content .= "

    Hello, I"m your custom post footer

    "; return $content; } add_filter("the_content", "msp_helloworld_post_footer", 100);

    Обратите внимание, что мы используем большое число для приоритета, что убедиться, что до выполнения ‘msp_helloworld_post_footer’ все стандартные фильтры отработают. После включения кода в наш плагин мы увидим результат:


    Как найти хук

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

    «Кодекс» WordPress предоставляет списки хуков для фильтров и событий Action Reference и Filter Reference .

    Дополнительные действия с хуками

    Так же как и добавить, хук можно удалить, используя похожий синтаксис.

    Удалить события можно так:

    Remove_action($tag, $function_to_remove, $priority, $accepted_args); remove_all_actions($tag, $priority);

    Как вы догадались, ‘remove_action’ удаляет определенное событие, зарегистрированное для данного хука (необходимо правильно указать приоритет и количество аргументов, так как было указано при регистрации), и ‘remove_all_actions’ помогает удалить все события, зарегистрированные для хука (если приоритет опущен, функция удалит все события).

    Фильтры можно удалять так же:

    Remove_filter($tag, $function_to_remove, $priority, $accepted_args); remove_all_filters($tag, $priority);

    API для плагинов в WordPress также предоставляет функции для проверки зарегистрирована ли функция для данного хука:

    Has_action($tag, $function_to_check); has_filter($tag, $function_to_check);

    Обе функции проверяют зарегистрирована ли данная функция для хука и возвращают true в случае успеха, иначе flase. Внутри функции у нас есть возможность проверить, что хук вызвал её:

    If("hook_to_check_name" === current_filter()){}

    Несмотря на название ‘current_filter’ работает не только с фильтрами но и с событиями.

    Нетривиальный пример

    Оживим «скелет» нашего плагина, который мы подготовили в прошлом уроке.

    Заполним файл ‘core.php’ (главная часть нашего плагина, в которой сосредоточена основная часть функций) кодом, который решает задачу, которая реально может возникнуть в ходе работы. Для её решения мы будем использовать actions и filters.

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

    Создадим собственную таксономию для обработки имя автора и его короткой биографии. Мы сможем использовать имя автора как другие термины таксономии (теги, например) в посте. Код:

    /** регистрация фильтров и событий **/ function msp_helloworld_init(){ add_action("init", "msp_helloworld_taxonomies"); add_filter("the_content", "msp_helloworld_author_block_filter"); add_filter("post_class", "msp_helloworld_post_class"); } add_action("plugins_loaded", "msp_helloworld_init"); /** taxonomy **/ function msp_helloworld_taxonomies(){ $args = array("labels" => array("name" => "Guest authors", "singular_name" => "Guest author"), "show_in_nav_menus" => false); register_taxonomy("gauthor", array("post"), $args); } /** разметка блока автора **/ function msp_helloworld_author_block(){ global $post; $author_terms = wp_get_object_terms($post->ID, "gauthor"); if(empty($author_terms)) return; $name = stripslashes($author_terms->name); $url = esc_url(get_term_link($author_terms)); $desc = wp_filter_post_kses($author_terms->description); $out = ""; $out .= "This is a guest post by {$name}"; $out .= "{$desc}"; return $out; } /** добавить разметку в конец поста **/ function msp_helloworld_author_block_filter($content){ if(is_single()) $content .= msp_helloworld_author_block(); return $content; } /** добавить CSS class к посту **/ function msp_helloworld_post_class($post_class){ global $post; $author_terms = wp_get_object_terms($post->ID, "gauthor"); if(!empty($author_terms)){ $post_class = "gauthor"; } return $post_class; }

    Как видите, мы создали функцию для регистрации собственной таксономии и привязали её к хуку ‘init’. После мы создали шаблон, отвечающий за отображение блока автора, используя функцию WordPress ‘wp_get_object_terms’. После мы вставили блок с информацией об авторе в конец поста с помощью фильтра ‘the_content’. И, наконец, мы добавили собственный CSS класс. Результат работы:


    Фильтры и события — это то, что позволяет темам и плагинам изменять поведение ядра, не изменяя исходные файлы самого ядра WordPress. В этой статье мы расскажем вам о том, как работают фильтры и события в WordPress и как ими пользоваться в ваших темах и плагинах.

    События

    События или действия (actions) в WordPress очень похожи на события в JavaScript. Событие выполняется вызовом функции do_action() , а добавить функцию к любому событию можно с помощью функции add_action() .

    При выполнении события или действия, выполняются все функции, добавленные к событию в определенном порядке. Это легче всего понять с помощью простого примера. Определяем три функции, которые будут выводить 1, 2 и 3 соответственно:

    Function one() { echo 1; } function two() { echo 2; } function three() { echo 3; }

    Добавляем функции к событию foo с помощью функции add_action() :

    Add_action("foo", "one"); add_action("foo", "two"); add_action("foo", "three");

    И выполняем наше событие с помощью функции do_action() :

    Do_action("foo"); // выведет 123

    Первый аргумент к функциям — это строка foo — название события. Название может быть любым, но во избежание конфликтов с другими плагинами и темами в собственных событиях лучше использовать префикс, например myplugin_foo , где myplugin это название вашего плагина.

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

    Итак, наш пример вызовет функции one() , two() и three() по порядку, что выведет на экран 123. Конечно мы могли самостоятельно вызвать эти функции в этом же порядке на месте do_action() , что дало бы тот же самый результат. Так зачем использовать события?

    Зачем использовать события

    Любой другой плагин или тема смогут легко добавить или удалить функции из вашего события без необходимости изменять код вашего плагина. Такой подход делает ваш плагин более гибким. Например:

    /* В другом плагине */ function four() { echo 4; } remove_action("foo", "three"); add_action("foo", "four");

    Таким образом, когда дело дойдет до вызова события foo в вашем плагине, на экран выведется уже не 123, а 124, поскольку другой плагин удалил функцию three() из вашего события с помощью функции remove_action() , и добавил на ее место новую функцию four() .

    Пример с выводом чисел не самый полезный. На практике достаточно легко придумать события в вашей теме или в плагине, которые могли бы быть полезными для других плагинов, например:

    Стоит так же отметить, что в самом ядре WordPress есть более 1500 фильтров и событий, которые можно использовать в темах и плагинах.

    Фильтры

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

    Function plus_one($value) { $value = $value + 1; return $value; }

    Эта функция принимает один аргумент, добавляет к нему единицу и возвращает результат. Добавим нашу функцию к новому фильтру с помощью add_filter() :

    Add_filter("foo", "plus_one");

    Теперь все функции добавленные к фильтру foo (в нашем случае это всего одна функция) можно легко вызвать или «применить» с помощью функции apply_filters() :

    Echo apply_filters("foo", 5); // 6

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

    В данном случае на экран выведется значение 6, поскольку значение 5 было пропущено через функцию plus_one() , которая изменила оригинальную переменную. Если убрать функцию у фильтра с помощью remove_filter() , то наш код выведет первоначальное значение 5:

    Remove_filter("foo", "plus_one"); echo apply_filters("foo", 5); // 5

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

    Пример хорошего фильтра

    Рассмотрим более интересный пример: создадим массив, который будет содержать ссылки на наши профили в социальных сетях и выводить эти ссылки в шапке нашей темы WordPress. В :

    Function get_my_social_profiles() { $profiles = array("twitter" => "http://twitter.com/wpmagru", "facebook" => "http://facebook.com/wpmagru",); return $profiles; }

    Возвращаемый массив можно использовать в цикле в нашем файле header.php:

    $profiles = get_my_social_profiles(); foreach ($profiles as $service => $url) { printf("%s", esc_url($url), $service); }

    /* В functions.php */ function get_my_social_profiles() { $profiles = array("twitter" => "http://twitter.com/wpmagru", "facebook" => "http://facebook.com/wpmagru",); return apply_filters("my_social_profiles", $profiles); }

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

    Function change_my_social_profiles($profiles) { unset($profiles["twitter"]); $profiles["google-plus"] = "https://plus.google.com/+wpmagru"; return $profiles; } add_filter("my_social_profiles", "change_my_social_profiles");

    Фильтры и события в ядре WordPress

    Как мы уже упомянули, в WordPress есть более 2000 фильтров и событий, которыми можно воспользоваться в плагинах или темах для того, чтобы изменить поведение ядра. Рассмотрим несколько интересных примеров.

    Отключить комментирование

    Отключить комментирование на всем сайте, на зависимо от настроек в параметрах можно с помощью следующего кода:

    Function my_comments_open() { return false; } add_filter("comments_open", "my_comments_open");

    Фильтр comments_open используется в ядре WordPress каждый раз для того, чтобы проверить открыты ли комментарии к той или иной статье. Наша функция всегда возвращает значение false для этого фильтра, поэтому комментарии будут закрыты везде.

    Кстати, ядро WordPress определяет несколько вспомогательных функций для работы с подобными фильтрами:

    • __return_true() — возвращает true
    • __return_false() — возвращает false
    • __return_zero() — возвращает 0
    • __return_empty_string() — возвращает пустую строку
    • __return_empty_array() — возвращает пустой массив
    • __return_null() — возвращает null

    То есть наш фильтр на comments_open можно переписать в одну строку:

    Add_filter("comments_open", "__return_false");

    Изменить длину автоматических цитат

    За длину автоматических цитат отвечает фильтр excerpt_length:

    Function my_excerpt_length($length) { $length = 10; return $length; } add_filter("excerpt_length", "my_excerpt_length");

    С помощью фильтра excerpt_more можно изменить текст, который который ставится в конце автоматический цитаты, по умолчанию это [...] :

    Function my_excerpt_more($more) { $more = "→"; return $more } add_filter("excerpt_more", "my_excerpt_more");

    Добавить баннер к содержимому каждой статьи

    Фильтр the_content выполняется перед выводом содержимого каждой статьи. Через фильтр проходит само содержимое статьи, поэтому в него легко добавить баннер «на лету» с помощью плагина:

    Function my_banner($content) { $banner = ""; $content = $banner . $content; return $content; } add_filter("the_content", "my_banner");

    Добавить favicon.ico в раздел

    В разделе в каждой теме выполняется событие wp_head . Во время этого события можно вывести ссылку на файл favicon.ico, вставить произвольный код JavaScript или CSS и многое другое:

    Function my_favicon() { echo ""; } add_action("wp_head", "my_favicon");

    Учтите, что если вам необходимо подключить внешние.js или.css файлы, делать это стоит с помощью функций wp_enqueue_script() и wp_enqueue_style() во время события wp_enqueue_scripts , а не напрямую в wp_head .

    В каждой версии WordPress добавляются все больше и больше новых и полезных фильтров и событий. Список большинства фильтров и событий в ядре можно посмотреть на сайте Адама Брауна , или просканировав файлы ядра на «do_action» и «apply_filters».

    Приоритеты

    Функции добавленные к фильтрам и событиям выполняются в том же порядке, в котором они были добавлены, но порядок легко изменить с помощью приоритетов. Приоритет указывается третьим аргументом к функциям add_action() и add_filter() .

    Без указания этого аргумента функции к фильтрам и событиям добавляются по умолчанию с приоритетом 10 . Функции выполняются от меньшего приоритета к большему, т.е. чем меньше приоритет, тем раньше выполняется функция.

    Вернемся к примеру с цифрами:

    Add_action("foo", "one"); add_action("foo", "two"); add_action("foo", "three"); do_action("foo"); // выведет 123

    Если изменить приоритет выполнения функции three() на 9, то она выполнится раньше остальных:

    Add_action("foo", "one"); add_action("foo", "two"); add_action("foo", "three", 9); do_action("foo"); // выведет 312

    Подобным образом, указав приоритет 11 для функции one() , она выполнится позднее всех остальных, несмотря на то, что она была добавлена первой с помощью add_action() :

    Add_action("foo", "one", 11); add_action("foo", "two"); add_action("foo", "three", 9); do_action("foo"); // выведет 321

    Дополнительные параметры

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

    Do_action("foo", $arg1, $arg2, $arg3); $value = apply_filters("foo", $value, $arg1, $arg2, $arg3);

    Ключевым моментом является то, что при добавлении функции к фильтру или событию нам необходимо указать количество принимаемых аргументов, за это отвечает четвертый параметр функций add_action() и add_filter() .

    Например, если в функции к событию foo мы хотим принять все три аргумента, необходимо указать 3 в качестве четвертого параметра к add_action() :

    Function my_func($arg1, $arg2, $arg3) { ... } add_action("foo", "my_func", 10, 3);

    Подобным образом, если в функции добавленной к фильтру мы хотим принять только $arg1 в качестве дополнительного аргумента, то просим add_filter() передать всего два аргумента — первый аргумент $value , и второй дополнительный аргумент $arg1:

    Function my_func($value, $arg1) { ... } add_filter("foo", "my_func", 10, 2);

    Пример

    Хорошим примером передачи дополнительных аргументов является фильтр allow_password_reset , с помощью которого можно запретить сброс пароля для пользователей:

    Add_filter("allow_password_reset", "__return_false");

    Это запретит сброс пароля для всех пользователей на сайте, но если нам необходимо запретить сброс пароля только супер-администраторам в сети (в целях безопасности), мы можем воспользоваться дополнительным аргументом:

    Function my_filter($allow, $user_id) { if (is_super_admin($user_id)) $allow = false; return $allow; } add_filter("allow_password_reset", "my_filter", 10, 2);

    Учтите, что функции привязанные к фильтрам могут изменять только первый аргумент, передаваемый в фильтр. То есть функция приведенная выше может изменить только аргумент $allow , но не $user_id .

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

    ООП, классы, объекты и анонимные функции

    Разработчики тем и плагинов WordPress часто предпочитают объектно-ориентированный стиль программирования, где большая часть кода выполняется внутри объекта, а не в глобальном пространстве. Если функциям add_action() и add_filter() необходимо передать не функцию для вызова, а метод объекта, его необходимо передать в специальном формате массивом:

    Class My_Class { function __construct() { add_filter("the_content", array($this, "filter_content")); } function filter_content($content) { // ... return $content; } } new My_Class();

    Похожим образом можно передать статический метод класса:

    Add_filter("the_content", array("My_Class", "filter_content")); add_filter("the_content", "My_Class::filter_content"); // PHP >= 5.2.3

    Фильтры и события поддерживают и анонимные функции, например:

    Add_filter("the_content", create_function("$content", "return $content;")); add_filter("the_content", function($content) { return $content; }); // PHP >= 5.3

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

    Заключение

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

    Разработчикам тем и плагинов для WordPress так же не следует забывать о фильтрах и событиях внутри их собственных продуктов для того, чтобы делать их более модульными, гибкими и легко изменяемыми с помощью стороннего кода.

    Если у вас возникнут вопросы о фильтрах и событиях в WordPress, оставьте комментарий и мы обязательно вам ответим.

    4 years ago

    Do-while loops can also be used inside other loops, for example:



    This version is easier to read and understand. And arguments for code golf are invalid as well as this version is 3 lines shorter.

    In conclusion, although you can certainly write code that abuses the `break` keyword, you shouldn"t in practice. Keep the code easy to read and understand for whoever inherits your code. And remember, code is for humans not computers.

    10 years ago

    I"m guilty of writing constructs without curly braces sometimes... writing the do--while seemed a bit odd without the curly braces ({ and }), but just so everyone is aware of how this is written with a do--while...

    a normal while:


    a do--while:


    Also, a practical example of when to use a do--while when a simple while just won"t do (lol)... copying multiple 2nd level nodes from one document to another using the DOM XML extension

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

    Концепция: что такое хуки и почему они используются?

    За любым качественно написанным программным обеспечением кроется мощная концепция, которая отвечает на вопросы «что такое?» и «почему?». Хуки – не исключение. Говоря простыми словами, хук – это заполнитель для действия. Когда происходит определенное событие, такое как публикация записи, хук активируется, позволяя реализовать соответствующую реакцию. В терминах разработчиков хуки представляют собой пример системы, управляемой событиями.

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

    Как применить хуки?

    Как разработчик, вы должны понимать не только то, что делают хуки или почему они введены, но и знать, как их создавать. Иными словами, чтобы полностью понять систему хуков, нужно разобраться в том, как они применяются.

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

    Работа с документацией

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

    • add_action($hook, $function [, $priority [, $numArgs ] ]) – задает обработчик функции $function, который вызывается в том случае, если определенный хук $hook активирован в результате возникновения события. $priority определяет, будет ли данный обработчик функции вызван до или после других обработчиков функций (по умолчанию переменная равна 10). Чем меньше этот показатель, тем раньше будет вызвана функция. $numArgs – количество аргументов, принимаемых обработчиком функции (по умолчанию 1).
    • do_action($hook [, $arg1 [, $arg2 [, $arg3 [, … ] ] ] ]) – активирует определенный хук $hook путем вызова всех обрабатываемых функций с необязательными аргументами $arg1, $arg2, $arg3 и т.д.

    Теперь, когда у нас в одной руке находится документация, мы можем сделать некоторые выводы по поводу этих двух функций. add_action просто связывает функцию, приоритет и количество аргументов со строкой. Это напоминает идеальную задачу для PHP массивов, которые также работают как хэш-карты, хранящие пары ключ-значение. do_action более тривиальная функция – она обращается к этому массиву, разыскивает функциональные обработчики и вызывает их впоследствии. Держа в памяти нашу схему, самое время перейти к применению хуков.

    Применяем полученные знания на практике

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

    Перед тем как начать, давайте создадим план действий:

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

    Код будет выглядеть следующим образом:

    $actions = array(); function add_action($hook, $function) { global $actions; // create an array of function handlers if it doesn"t already exist if(!isset($actions[ $hook ])) $actions[ $hook ] = array(); // append the current function to the list of function handlers $actions[ $hook ] = $function; } function do_action($hook) { global $actions; if(isset($actions[ $hook ])) { // call each function handler associated with this hook foreach($actions[ $hook ] as $function) call_user_func($function); } }

    Отлично; мы создали универсальную систему хуков с помощью примерно 20 строк кода. Теперь, когда у нас есть идея того, как работают хуки, давайте погрузимся в код ядра WordPress, чтобы подтвердить наши гипотезы.

    Быстро перемещаться по коду можно с помощью разных инструментов – таких как, к примеру, Yoast’s PHP Cross Reference of the WordPress Source.

    Поиск по «add_action» выдает следующий код:

    Function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) { return add_filter($tag, $function_to_add, $priority, $accepted_args); } function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) { global $wp_filter, $merged_filters; $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority); $wp_filter[$tag][$priority][$idx] = array("function" => $function_to_add, "accepted_args" => $accepted_args); unset($merged_filters[ $tag ]); return true; }

    add_action вызывает add_filter, который, в свою очередь, добавляет заданную функцию в массив, связанный с хуком $tag. Несмотря на то, чтобы здесь мы также используем параметры $priority и $accepted_args, данная функция полностью отвечает нашим предположениям. do_action будет чуть длиннее и сложнее:

    Function do_action($tag, $arg = "") { do { foreach ((array) current($wp_filter[$tag]) as $the_) if (!is_null($the_["function"])) call_user_func_array($the_["function"], array_slice($args, 0, (int) $the_["accepted_args"])); } while (next($wp_filter[$tag]) !== false); }

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

    Примеры

    Обладая пониманием работы хуков, давайте взглянем на два следующих примера. Первый пример – работа с RSS; вместо того чтобы рассылать уведомления через синдикацию, почему бы не использовать для этого электронную почту?

    Система почтовых уведомлений

    Чтобы реализовать данную систему, нам нужно получить дату публикации записи. Однако какой хук мы должны использовать для этого? Описание API действий предлагает список хуков наряду со связанными с ними событиями, что поможет нам получить ответ на поставленный выше вопрос. Описание хука publish_post подходит под наши требования, потому давайте добавим обработчик функций к нему:

    Add_action("publish_post", "notify_via_email");

    Все, что нам осталось сделать, – это отправить уведомление по электронной почте в обработчике функции notify_via_email. Обратите внимание, что хук publish_post передает ID записи как аргумент в нашу функцию. Это позволит нам получить информацию о записи с помощью функции get_post:

    Function notify_via_email($post_id) { $post = get_post($post_id); $to = "[email protected] /* */ "; $subject = "Post Published on " . get_bloginfo("name"); $message = $post->post_title . " was published on " . get_bloginfo("name") . " as of " . $post->post_date . ". You may view it at " . get_permalink($post_id) . "."; wp_mail($to, $subject, $message); }

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

    Плагин Google Analytics

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

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

    Но как добавить код в футер сайта? Все так же – с помощью хуков. Если вы работали с WordPress темами раньше, вы, вероятно, вызывали функции wp_head и wp_footer в хэдере и футере вашего сайта соответственно. Обе эти функции просто активируют хуки, чтобы плагины могли легко добавлять свой код в эти жизненно важные области страницы. Следовательно, мы просто добавим действие к хуку wp_footer:

    Add_action("wp_footer", "add_google_analytics_code");

    Наша функция add_google_analytics_code, как и предполагает ее название, печатает код Google Analytics:

    var _gaq=[["_setAccount","UA-XXXXX-X"],["_trackPageview"]]; (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t); g.async=g.src="http://www.google-analytics.com/ga.js"; s.parentNode.insertBefore(g,s)}(document,"script"))

    Обязательно измените UA-XXXXX-X на ваш личный ID, зависящий от сайта. В итоге все заработает. Просто добавьте указанный код в файл и загрузите его в вашу папку с плагинами. Убедитесь в том, что плагин содержит заголовок — к примеру, такой:



    Просмотров