Статьи

Как использовать Ajax в WordPress — пример из реального мира

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

Это быстрый и удобный способ отображения контента, и в результате Ajax теперь используется на веб-сайте различными способами, такими как отправка комментариев в блоге, лайки постов и загрузка файлов. Вы даже можете сделать свой сайт полностью Ajaxified , чтобы каждая страница вашего сайта загружалась асинхронно.

Учитывая популярность Ajax, большинство ведущих платформ CMS используют его в своей архитектуре. WordPress ничем не отличается. На самом деле WordPress использует Ajax очень надежным и простым способом, и сегодня я покажу вам, как вы можете использовать Ajax в WordPress на примере реального мира. Прежде чем мы начнем, я предположил, что у вас есть некоторые знания о методах jQuery Ajax и хуках WordPress, так как нам понадобятся оба!

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

WordPress jQuery UI

Что мы собираемся сделать?

Возможно, вы уже знаете, что использование Ajax в WordPress немного отличается от его использования вне WordPress, вам нужно учитывать две вещи:

  1. URL admin-ajax.php файла WordPress admin-ajax.php , где данные отправляются для обработки.
  2. Хук действия Ajax называется wp_ajax_ . Вам нужно подключить пользовательскую функцию, которая будет выполняться во время вызова Ajax.

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

Так что наш плагин «Read Me Later» будет делать несколько вещей:

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

Понял? Давайте сделаем немного работы сейчас.

Подготовка наших файлов плагинов и настройка каталогов

Сначала мы создадим папку с именем read-me-later в каталоге плагинов нашей основной установки WordPress. Эта папка будет содержать все наши файлы и подкаталоги, необходимые для нашего плагина. Теперь внутри папки read-me-later нам нужно будет создать еще две папки с js и css .

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

  • read-me-later.php
  • widget.php
  • read-me-later.js
  • read-me-later. css

Первые два файла будут напрямую идти в основную папку плагина. Файлы js и css будут помещены в папки js и css соответственно.

Теперь мы read-me-later.php файл read-me-later.php . Включая заголовок плагина:

 

Этот код важен, поскольку он используется для определения того, что это плагин для WordPress. После приведенного выше кода мы создадим наш основной класс плагина под названием ReadMeLater :

class ReadMeLater {}

Включая основные файлы JS и CSS

Далее нам нужно зарегистрировать и поставить в очередь наши файлы JavaScript и CSS с соответствующими хуками WordPress. Мы создадим несколько методов для выполнения этого шага. Скопируйте этот код в класс ReadMeLater :

 /* * Action hooks */ public function run() { // Enqueue plugin styles and scripts add_action( 'plugins_loaded', array( $this, 'enqueue_rml_scripts' ) ); add_action( 'plugins_loaded', array( $this, 'enqueue_rml_styles' ) ); } /** * Register plugin styles and scripts */ public function register_rml_scripts() { wp_register_script( 'rml-script', plugins_url( 'js/read-me-later.js', __FILE__ ), array('jquery'), null, true ); wp_register_style( 'rml-style', plugins_url( 'css/read-me-later.css' ) ); } /** * Enqueues plugin-specific scripts. */ public function enqueue_rml_scripts() { wp_enqueue_script( 'rml-script' ); } /** * Enqueues plugin-specific styles. */ public function enqueue_rml_styles() { wp_enqueue_style( 'rml-style' ); } 

Код довольно понятен. Здесь мы создали открытый метод с именем register_rml_scripts() . Внутри этого метода мы зарегистрировали наши файлы read-me-later.js и read-me-later.css используя надлежащие функции WordPress.

Следующие два метода enqueue_rml_scripts() и enqueue_rml_styles() используются для постановки в очередь нашего JavaScript и таблицы стилей. Мы также создали метод run , который будет содержать все наши хуки действий (и фильтров).

Если вы новичок в WordPress, вы можете проверить Сценарии и стили в WordPress от Younes Rafie или выполнить поиск по кодексу WordPress, чтобы узнать, как правильно регистрировать и ставить в очередь файлы JavaScript и CSS.

Создание ссылки «Прочтите позже» под каждым постом

Теперь нам нужно создать ссылку Read Me Later под каждым сообщением в блоге. Нажав на ссылку, пользователь может выбрать эту запись для сохранения в списке «Читать позже». После щелчка ссылка исчезнет из сообщения, а идентификатор сообщения будет сохранен в базе данных. При создании ссылки есть два соображения:

  • Только авторизованный пользователь увидит ссылку.
  • Ссылка будет содержать «связанный» идентификатор сообщения для последующего использования.

Для этого добавьте следующую функцию в класс ReadMeLater :

 /** * Adds a read me later button at the bottom of each post excerpt that allows logged in users to save those posts in their read me later list. * * @param string $content * @returns string */ public function rml_button( $content ) { // Show read me later link only when the user is logged in if( is_user_logged_in() && get_post_type() == post ) { $html .= '<a href="#" class="rml_bttn" data-id="' . get_the_id() . '">Read Me Later</a>'; $content .= $html; } return $content; } 

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

Чтобы разместить ссылку под каждым сообщением в блоге, добавьте код ниже в метод run :

 // Setup filter hook to show Read Me Later link add_filter( 'the_excerpt', array( $this, 'rml_button' ) ); add_filter( 'the_content', array( $this, 'rml_button' ) ); 

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

Определение URL Ajax

Когда вы собираетесь сделать Ajax-вызов, вам нужно отправить запрос в файл admin-ajax.php , который является частью ядра WordPress. Этот файл отвечает за обработку и обработку всех ваших запросов Ajax в контексте WordPress. НЕ используйте прямой URL-адрес пути к файлу. Вместо этого используйте admin_url('admin-ajax.php') который выведет правильный URL. Единственная проблема в этом состоит в том, что вы не можете поместить какие-либо функции PHP в JavaScript. Итак, нам нужен небольшой трюк, см. Код ниже:

 wp_localize_script( 'rml-script', 'readmelater_ajax', array( 'ajax_url' => admin_url('admin-ajax.php')) ); 

Здесь мы используем функцию wp_localize_script() . Требуется три аргумента:

  1. rml-script , обработчик регистрации rml-script read-me-later.js .
  2. Строка, которая будет действовать как объект JavaScript.
  3. Массив, который является фактическими данными, которые мы хотим передать из нашего JavaScript.

Итак, если мы напишем rml_obj.ajax_url , он выведет значение admin_url('admin-ajax.php') , другими словами, URL admin-ajax.php файла admin-ajax.php . Мы будем использовать его в части JavaScript.

Не забудьте поместить приведенный выше код в наш enqueue_rml_scripts() который мы создали ранее.

Добавление JavaScript и ваш первый вызов Ajax

Теперь пришло время создать наш вызов Ajax. Откройте файл read-me-later.js из нашей папки js . Добавьте следующий код:

 jQuery(document).ready( function(){ jQuery('#content').on('click', 'a.rml_bttn', function(e) { e.preventDefault(); var rml_post_id = jQuery(this).data( 'id' ); jQuery.ajax({ url : readmelater_ajax.ajax_url, type : 'post', data : { action : 'read_me_later', post_id : rml_post_id }, success : function( response ) { jQuery('.rml_contents').html(response); } }); jQuery(this).hide(); }); }); 

В приведенном выше коде мы создали функцию, которая будет вызываться, когда пользователь нажимает ссылку «Читать мне позже». Внутри этой функции мы берем идентификатор поста, используя метод данных, и сохраняем его в переменной ‘rml_post_id’. После этого мы сделали вызов Ajax с помощью метода jQuery ‘$ .ajax ()’. Этот метод принимает несколько свойств, как мы упоминали ранее в этой статье. Позвольте мне объяснить их один за другим.

url содержит URL admin-ajax.php файла admin-ajax.php . Помните, как мы определили rml_obj.ajax_url на предыдущем шаге? Вот как мы используем URL здесь. Наш Ajax-запрос будет отправлен туда для обработки.

type указывает, будет ли запрос отправляться с использованием HTTP-метода '$_GET[]' или '$_POST[]' . Мы используем здесь метод '$_POST[]' , так как мы устанавливаем его как post .

data содержат данные, которые мы хотим отправить с помощью вызова Ajax. Здесь наши данные являются объектами в виде пар ключ-значение. post_id содержит идентификатор записи, а action содержит read_me_later который является суффиксом хука wp_ajax_ . Мы определим хук действия Ajax и его функцию обратного вызова на следующем шаге.

Последний — это success который содержит анонимную функцию. Он сработает после завершения вызова Ajax.

Убедитесь, что ваша ссылка read me later обернута тегом div с атрибутом #content id иначе jQuery не будет работать.

Теперь нам нужно удалить ссылку « Read Me Later сразу после того, как пользователь щелкнет по ней, чтобы пользователь не мог сохранить сообщение дважды. Для этого мы добавили следующий код после jQuery.ajax() :

 jQuery(this).hide(); 

Это удалит ссылку «Читать мне позже», когда пользователь нажмет на нее.

Ajax Action Hook

Теперь о важной части.

Итак, мы создали ссылку Read Me Later и соединили ее с Ajax. Но ссылка пока ничего не делает, потому что мы не написали никакого кода на стороне сервера для обработки запроса Ajax. Когда пользователь щелкает ссылку, нам нужно сохранить этот идентификатор сообщения в базе данных, а затем отобразить сообщения в веб-интерфейсе на основе информации базы данных.

Чтобы выполнить этот вид обработки на стороне сервера, WordPress предоставляет нам две wp_ajax_my_action действий: wp_ajax_my_action и wp_ajax_nopriv_my_action . Первый будет работать только для вошедших в систему пользователей, а второй будет полезен, когда пользователи не вошли в систему. Поскольку наш примерный плагин предназначен только для зарегистрированных пользователей, мы будем использовать первый. Обратите внимание, что my_action является суффиксом хука wp_ajax_ и вы можете назвать его по wp_ajax_ желанию.

Добавьте следующий фрагмент внутри метода run() :

 // Setup Ajax action hook add_action( 'wp_ajax_read_me_later', array( $this, 'read_me_later' ) ); 

Единственное, с чем вы должны быть осторожны при использовании приведенного выше кода, это убедиться, что ваш суффикс ловушки Ajax соответствует значению свойства action вашего jQuery.ajax() (см. Предыдущий шаг). Вы можете заметить, что мы даем одно и то же имя функции обратного вызова, чтобы мы могли ее легко запомнить. Теперь мы определим нашу функцию обратного вызова:

 public function read_me_later() { $rml_post_id = $_POST['post_id']; $echo = array(); if(get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ) !== null ) { $value = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ); } if( $value ) { $echo = $value; array_push( $echo, $rml_post_id ); } else { $echo = array( $rml_post_id ); } update_user_meta( wp_get_current_user()->ID, 'rml_post_ids', $echo ); $ids = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ); } 

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

Сначала мы сохранили идентификатор записи в переменной $rml_post_id . Затем мы объявили пустой массив с именем $echo .

После этого мы проверяем наличие поля с ключом rml_post_ids в таблице usermeta в нашей базе данных. Если есть строка, мы берем мета-значение с помощью get_user_meta() WordPress get_user_meta() и сохраняем его в $value .

Опять же, мы проверяем, существует ли $value или нет. Если true, мы храним его в ранее объявленном массиве $echo . Затем мы $rml_post_id значение $rml_post_id в массив, используя array_push() . Если $value , то мы просто храним $rml_post_id в $echo .

update_user_meta() отвечает за обновление (или создание, если поле еще не создано) метаполя с данными, хранящимися в $echo .

Наконец, мы сохраняем недавно заполненное мета-поле, используя get_user_meta() в $ids в качестве массива.

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

 // Query read me later posts $args = array( 'post_type' => 'post', 'orderby' => 'DESC', 'posts_per_page' => -1, 'numberposts' => -1, 'post__in' => $ids ); $rmlposts = get_posts( $args ); if( $ids ) : global $post; foreach ( $rmlposts as $post ) : setup_postdata( $post ); $img = wp_get_attachment_image_src( get_post_thumbnail_id() ); ?> <div class="rml_posts"> <div class="rml_post_content"> <h5><a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a></h5> <p><?php the_excerpt(); ?></p> </div> <img src="<?php echo $img[0]; ?>" alt="<?php echo get_the_title(); ?>" class="rml_img"> </div> <?php endforeach; wp_reset_postdata(); endif; // Always die in functions echoing Ajax content die(); 

Здесь мы используем get_posts() WordPress, чтобы получить все сообщения в зависимости от выбора пользователя. Единственным обязательным параметром здесь является post__in который содержит массив идентификаторов post__in . Наконец, мы используем die() чтобы содержимое Ajax отображалось правильно.

Вот полный код функции read_me_later() :

 /** * Hook into wp_ajax_ to save post ids, then display those posts using get_posts() function */ public function read_me_later() { $rml_post_id = $_POST['post_id']; $echo = array(); if( get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ) !== null ) { $value = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ); } if( $value ) { $echo = $value; array_push( $echo, $rml_post_id ); } else { $echo = array( $rml_post_id ); } update_user_meta( wp_get_current_user()->ID, 'rml_post_ids', $echo ); $ids = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ); // Query read me later posts $args = array( 'post_type' => 'post', 'orderby' => 'DESC', 'posts_per_page' => -1, 'numberposts' => -1, 'post__in' => $ids ); $rmlposts = get_posts( $args ); if( $ids ) : global $post; foreach ( $rmlposts as $post ) : setup_postdata( $post ); $img = wp_get_attachment_image_src( get_post_thumbnail_id() ); ?> <div class="rml_posts"> <div class="rml_post_content"> <h5><a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a></h5> <p><?php the_excerpt(); ?></p> </div> <img src="<?php echo $img[0]; ?>" alt="<?php echo get_the_title(); ?>" class="rml_img"> </div> <?php endforeach; wp_reset_postdata(); endif; // Always die in functions echoing Ajax content die(); } 

Создание виджета для прочитанных мной постов позже

Теперь нам нужен виджет для отображения сообщений, сохраненных пользователем. Мы сделаем очень простой виджет для простоты. Я не буду вдаваться в подробности, нам просто нужно расширить класс WP_Widget WordPress, чтобы создать собственный виджет. Давайте сделаем это, widget.php файл widget.php и создадим дочерний класс с именем RML_Widget который расширяет класс WP_Widget .

 class RML_Widget extends WP_Widget {} 

Создайте магический метод __construct() внутри класса, чтобы инициализировать наш виджет:

 function __construct() { parent::__construct( 'rml_widget', // Base ID __( 'Read Me Later', 'text_domain' ), // Name array( 'classname' => 'rml_widgt', 'description' => __( 'Read Me Later widget for displaying saved posts', 'text_domain' ), ) // Args ); } 

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

Внутренняя форма виджета будет создана методом form() , например так:

 public function form( $instance ) { if ( isset( $instance['title'] ) ) { $title = $instance['title']; } else { $title = __( 'Read Me Later Posts', 'text_domain' ); } ?> <p> <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label> <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>"> </p> <?php } 

Как видите, наша форма состоит из текстового поля, которое содержит заголовок виджета. Мы назначаем наш заголовок в переменной $title . get_field_id() и get_field_name() дают нашему текстовому полю уникальный идентификатор и имя соответственно.

Метод update() отвечает за санитарную обработку и обновление значения пользовательского ввода.

 public function update( $new_instance, $old_instance ) { $instance = array(); $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : ''; return $instance; } 

Требуется два параметра:

  1. $new_instance содержит значение, введенное пользователем с помощью внутренней формы, которую мы создали методом form() .
  2. $old_instance противоположен, он содержит предыдущее значение.

Теперь мы создадим метод widget() который будет отображать сообщения «Read Me Later» во внешнем интерфейсе.

 public function widget( $args, $instance ) { $title = apply_filters( 'widget_title', $instance['title'] ); echo $args['before_widget']; if ( ! empty( $title ) ) { echo $args['before_title'] . $title . $args['after_title']; } echo '<div class="rml_contents">'; $ids = get_user_meta( wp_get_current_user()->ID, 'rml_post_ids', true ); $args = array( 'post_type' => 'post', 'orderby' => 'DESC', 'posts_per_page' => -1, 'numberposts' => -1, 'post__in' => $ids ); $rmlposts = get_posts( $args ); if( $ids ) : global $post; foreach ( $rmlposts as $post ) : setup_postdata( $post ); $img = wp_get_attachment_image_src( get_post_thumbnail_id() ); ?> <div class="rml_posts"> <div class="rml_post_content"> <h4><a href="<?php echo get_the_permalink(); ?>"><?php the_title(); ?></a></h4> <p><?php the_excerpt; ?></p> </div> <img src="<?php echo $img[0]; ?>" alt="<?php echo get_the_title(); ?>" class="rml_img"> </div> <?php endforeach; wp_reset_postdata(); else : echo '<p>You have no saved posts now.</p>'; endif; echo '</div>'; echo $args['after_widget']; } 

Здесь мы используем get_posts() для отображения сообщений. Практически так же, как метод read_me_later() .

Не забудьте включить файл widget.php , добавив следующий код в read-me-later.php файла read-me-later.php :

 require(plugin_dir_path( __FILE__ ).'widget.php'); 

Обеспечение безопасности ваших вызовов Ajax

Работая с Ajax, вы должны предпринять необходимые шаги для обеспечения безопасности своего кода. Если вы собираетесь получать какие-либо данные от пользователя, очистите их перед сохранением в базе данных. Используйте nonce чтобы проверить, поступил ли запрос из правильного местоположения и был выполнен аутентифицированным пользователем. Здесь я собираюсь показать вам, как использовать nonce WordPress в вызове Ajax.

Сначала мы создадим одноразовый номер с помощью wp_create_nonce() и передадим его из JavaScript. Для этого используйте код из enqueue_rml_scripts() :

 wp_localize_script( 'read-me-later', 'readmelater_ajax', array( 'ajax_url' => admin_url('admin-ajax.php') ) ); 

И замените его следующим кодом:

 wp_localize_script( 'read-me-later', 'readmelater_ajax', array( 'ajax_url' => admin_url('admin-ajax.php'), 'check_nonce' => wp_create_nonce('rml-nonce') ) ); 

Теперь мы можем получить доступ к значению nonce из нашего JavaScript, используя readmelater_ajax.check_nonce . Добавьте свойство безопасности в метод jQuery.ajax() в вашем файле JavaScript, как jQuery.ajax() ниже:

 security : readmelater_ajax.check_nonce 

Наш финальный JavaScript будет выглядеть так:

 jQuery(document).ready( function(){ jQuery('#content').on('click', 'a.rml_bttn', function(e) { e.preventDefault(); var rml_post_id = jQuery(this).data( 'id' ); jQuery.ajax({ url : readmelater_ajax.ajax_url, type : 'post', data : { action : 'read_me_later', security : readmelater_ajax.check_nonce, post_id : rml_post_id }, success : function( response ) { jQuery('.rml_contents').html(response); } }); jQuery(this).hide(); }); }); 

Наконец, нам нужно проверить одноразовый номер в нашем обратном вызове Ajax. Для этого мы будем использовать check_ajax_referer() . Добавьте следующий код в начало метода read_me_later() который мы создали ранее:

 check_ajax_referer( 'rml-nonce', 'security' ); 

Это принимает два аргумента. Первый — это ключ, который мы создали с помощью wp_create_nonce() . Второе — это свойство security мы передали из JavaScript.

Если одноразовый номер неверен или не установлен, вызов Ajax прекратится. Таким образом, наш скрипт заблокирует недопустимые запросы Ajax.

Вывод

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

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