PHP и формы. События и фильтры в WordPress Как избежать неприятностей, связанных с PHP _SELF

Мы создали фундамент для будущего плагина, который распознает система 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 класс. Результат работы:


    В этой статье подробно говорится об использовании переменной PHP _SELF.

    Что за переменная PHP _SELF?

    Переменная PHP _SELF возвращает имя и путь к текущему файлу (относительно корня документа). Вы можете использовать эту переменную в атрибуте формы action. Существуют также некоторые нюансы, которые вы должны знать. Мы, конечно, никак не можем обойти стороной эти нюансы.

    Давайте рассмотрим несколько примеров.

    Echo $_SERVER["PHP_SELF"];

    1) Предположим, что ваш php файл расположен по следующему адресу:

    Http://www.yourserver.com/form-action.php

    В этом случае переменная PHP _SELF будет содержать:

    "/form-action.php"

    2) Предположим, ваш php файл расположен по такому адресу:

    Http://www.yourserver.com/dir1/form-action.php

    PHP _SELF будет:

    "/dir1/form-action.php"

    PHP _SELF в атрибуте формы action. Для чего она там понадобилась?

    Обычно переменную PHP _SELF используют в атрибуте action тега form . В атрибуте action указывается адрес, по которому будет отослано содержание формы после подтверждения (клик пользователем по кнопке с type="submit"). Как правило это таже самая страница, с которой ушла форма.

    Однако, если вы переименуете файл, на который ссылается форма, вам понадобится переименовать название файла в атрибуте action , иначе форма работать не будет.

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

    Допустим, у вас есть файл с формой form-action.php, и вы хотите, чтобы после подтверждения форма отправлялась на тот же самый файл. Обычно пишут так:

    Но вы можете использовать переменную PHP _SELF вместо form-action.php. В этом случае код будет выглядеть: