Написание плагина WordPress с нуля: пошаговое руководство

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

Содержание

Описание необходимого функционала плагина

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

Плагин для одного сайта

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

Пошаговое руководство по разработке плагина для WordPress

Последовательность моих шагов:

1. Начало

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_action( 'init', 'wpshout_do_thing' );
function wpshout_do_thing() {
		if( ! isset( $_GET['wpsdt'] ) ) :
			return;
		endif;

		var_dump("Here");
		die;
}

Примечания к шагу 1

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

Обратите внимание на строку if( ! isset( $_GET[‘wpsdt’] ) ). В ней вызывается суперглобальная переменная PHP $_GET для запуска плагина. Она задействуется тогда, когда в URL-адресе есть строка запроса wpsdt. Этот прием позволяет запускать плагин путем изменения параметров URL-адресов.

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

Код var_dump(); die позволяет убедиться, что плагин выводит данные и прекращает другие процессы PHP.

Результат работы кода, приведенного выше:

2. Запрос последних записей всех типов

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_action( 'init', 'wpshout_do_thing' );
function wpshout_do_thing() {
		if( ! isset( $_GET['wpsdt'] ) ) :
			return;
		endif;

		$args = array(
			'posts_per_page' => 5,
			'post_type' => 'any',
			'post_status' => 'publish',
			'orderby' => 'date',
			'order' => 'DESC',
		);

		$query = new WP_Query( $args );

		var_dump( $query );
		die;
}

Примечания к шагу 2

На этом шаге мы создаем пользовательский запрос WP_Query и выполняем var_dump(), чтобы убедиться, что запрос работает. Он запрашивает последние пять опубликованных записей любого типа.

В результате мы получаем объект WP_Query posts, который представляет собой массив из пяти записей.

3. Как запросить все записи, опубликованные в этом месяце

Первоначально я не знал, как это реализовать. Но затем мне удалось найти пример, в котором показывается, как передать элемент date_query массива WP_Query:

'date_query' => array(
	'after' => array(
		'year'  => 2012,
		'month' => 3,
		'day'   => 1,
	),
),

Но как в PHP указать, что нам нужен текущий месяц? Поиск привел меня к следующему примеру:

'date_query' => array(
	'after' => array(
		'year'  => date( 'Y' ),
		'month' => date( 'M' ),
		'day'   => 1,
	),
),

4. Объединение запроса даты с основным запросом

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_action( 'init', 'wpshout_do_thing' );
function wpshout_do_thing() {
		if( ! isset( $_GET['wpsdt'] ) ) :
			return;
		endif;

		$args = array(
			'posts_per_page' => -1,
			'post_type' => 'any',
			'post_status' => 'publish',
			'date_query' => array(
				'after' => array(
					'year' => date( 'Y' ),
					'month' => date( 'M' ),
				),
				'day' => 1,
			),
			'orderby' => 'date',
			'order' => 'DESC',
		);

		$query = new WP_Query( $args );

		var_dump( $query );
		die;
}

Примечания к шагу 4

На этом шаге мы добавляем параметр date_query в существующий WP_Query. А также изменяем значение posts_per_page на -1, чтобы получить все интересующие записи.

Результат выполнения приведенного выше кода:

Но этот код работает неправильно. Запрос возвращает не те записи, которые нам нужны.

5. Отладка

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_action( 'init', 'wpshout_do_thing' );
function wpshout_do_thing() {
		if( ! isset( $_GET['wpsdt'] ) ) :
			return;
		endif;

		// $args = array(
		// 	'posts_per_page' => -1,
		// 	'post_type' => 'any',
		// 	'post_status' => 'publish',
		// 	'date_query' => array(
		// 		'after' => array(
		// 			'year' => date( 'Y' ),
		// 			'month' => date( 'M' ),
		// 		),
		// 		'day' => 1,
		// 	),
		// 	'orderby' => 'date',
		// 	'order' => 'DESC',
		// );

		// $query = new WP_Query( $args );

		$after = array(
			'year' => date( 'Y' ),
			'month' => date( 'M' ),
		);

		var_dump($after );
		die;
}

Примечания к шагу 5

На этом этапе мы выполняем следующие действия:

  1. Комментируем код, который ведет себя странно.
  2. Изучаем этот код.

Вся проблема в элементе after, который является частью массива date_query. Чтобы понять, что пошло не так, выведем информацию об этом элементе с помощью функции var_dump().

Оказывается, месяц является строкой, «Oct». А date_query может принимать только числовое значение.

6. Повторяем попытку

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_action( 'init', 'wpshout_do_thing' );
function wpshout_do_thing() {
		if( ! isset( $_GET['wpsdt'] ) ) :
			return;
		endif;

		$args = array(
			'posts_per_page' => -1,
			'post_type' => 'any',
			'post_status' => 'publish',
			'date_query' => array(
				'after' => array(
					'year' => date( 'Y' ),
					'month' => date( 'm' ),
				),
				'day' => 1,
			),
			'orderby' => 'date',
			'order' => 'DESC',
		);

		$query = new WP_Query( $args );

		// $after = array(
		// 	'year' => date( 'Y' ),
		// 	'month' => date( 'M' ),
		// );

		var_dump( $query );
		die;
}

Примечания к шагу 6

Замени значение ‘M’ на ‘m’ в date_query. Потому что ‘m’ дает нам числовое обозначение месяца, когда он передается в date().

Запуск этого кода дает следующее:

Но это тоже не сработало. Запрос WP_Query возвратил пустой массив posts.

7. Это не сработало — отладка

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_action( 'init', 'wpshout_do_thing' );
function wpshout_do_thing() {
		if( ! isset( $_GET['wpsdt'] ) ) :
			return;
		endif;

		$args = array(
			'posts_per_page' => -1,
			'post_type' => 'any',
			'post_status' => 'publish',
			'date_query' => array(
				'after' => array(
					'year' => date( 'Y' ),
					'month' => date( 'm' ),
					'day' => 1,
				),
			),
			'orderby' => 'date',
			'order' => 'DESC',
		);

		$query = new WP_Query( $args );

		// $after = array(
		// 	'year' => date( 'Y' ),
		// 	'month' => date( 'M' ),
		// );

		var_dump( $query );
		die;
}

Примечания к шагу 7

Ошибка заключалась в том, что я использовал day как отдельный элемент массива date_query. А нужно поместить day внутрь элемента after из date_query. Исправление и повторный запуск кода дает следующее:

В результате мы получили десять записей текущего месяца!

8. Пользовательский интерфейс и шорткод

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_shortcode( 'wpshout_show_this_months_posts_by_author', 'wpshout_show_this_months_posts_by_author' );
function wpshout_show_this_months_posts_by_author() {
		if( ! current_user_can( 'administrator' ) ) :
			return;
		endif;

		$args = array(
			'posts_per_page' => -1,
			'post_type' => 'any',
			'post_status' => 'publish',
			'date_query' => array(
				'after' => array(
					'year' => date( 'Y' ),
					'month' => date( 'm' ),
					'day' => 1,
				),
			),
			'orderby' => 'date',
			'order' => 'DESC',
		);

		$query = new WP_Query( $args );

		ob_start();

		while( $query->have_posts() ) :
			$query->the_post(); ?>

			<h2><?php the_title(); ?></h2>
			By <?php the_author(); ?> on <?php the_date(); ?>

		<?php endwhile;

		wp_reset_postdata();

		return ob_get_clean();
}

Примечания к шагу 8

Мы будем использовать шорткоды. Для этого меняем add_action() на add_shortcode() и называем функцию шорткода wpshout_show_this_months_posts_by_author(). С помощью буферизации вывода мы сможем контролировать то, какую разметку будет возвращать шорткод. Внутри цикла while() используются теги шаблонов the_author() и the_date().

Запустив плагин с помощью шорткода wpshout_show_this_months_posts_by_author, мы получаем следующее:

Но почему в одном из выведенных постов отсутствует дата?

9. THE_DATE() работает довольно странно?

<?php 
/**
 * Plugin Name: WPShout Show Authorship this Month
 * Description: Show who's written what this month on WPShout
 * Version: 1.0
 * Author: WPShout
 * Author URI: https://wpshout.com
*/

add_shortcode( 'wpshout_show_this_months_posts_by_author', 'wpshout_show_this_months_posts_by_author' );
function wpshout_show_this_months_posts_by_author() {
		if( ! current_user_can( 'administrator' ) ) :
			return;
		endif;

		$args = array(
			'posts_per_page' => -1,
			'post_type' => 'any',
			'post_status' => 'publish',
			'date_query' => array(
				'after' => array(
					'year' => date( 'Y' ),
					'month' => date( 'm' ),
					'day' => 1,
				),
			),
			'orderby' => 'date',
			'order' => 'DESC',
		);

		$query = new WP_Query( $args );

		ob_start();

		while( $query->have_posts() ) :
			$query->the_post(); ?>

			<h2><?php the_title(); ?></h2>
			By <?php the_author(); ?> on <?php echo get_the_date( 'l, F d, Y' ); ?>

		<?php endwhile;

		wp_reset_postdata();

		return ob_get_clean();
}

Примечания к шагу 9

Оказалось, что функция the_date() выводит только один пост за одну дату. Если существуют две записи с одинаковой датой публикации, она перестает работать.

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

И это именно то, что нужно.

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

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

Данная публикация представляет собой перевод статьи «Writing a WordPress Plugin From Scratch: A Step-by-Step Tutorial» , подготовленной дружной командой проекта Интернет-технологии.ру

Меню