Статьи

Реальный пример разработки плагина WordPress

Чтобы извлечь максимальную пользу из этого урока, вы должны иметь общее представление о таких темах, как actions , filters , shortcodes , widgets и object orientated design .

Если вы заинтересованы в ознакомлении с основами, вы можете прочитать мою предыдущую статью «Введение в разработку плагинов WordPress» . Это поможет вам лучше понять концепции и идеи, которые мы будем использовать в этом руководстве.

WordPress-плагин

Пример из реального мира — список местоположений предприятий

Давайте перейдем непосредственно к реальному примеру использования плагинов для решения проблем и добавления функциональности на ваш сайт.

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

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

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

plugin_location_final

Настройка всего

Давайте настроим все, перейдем в каталог плагинов и создадим следующую структуру папок / файлов

  • wp_simple_location_plugin
    • CSS
      • wp_location_public_styles.css
      • wp_location_admin_styles.css
    • вкл
      • wp_location_widget.php
      • wp_location_shortcode.php
    • wp_simple_location_plugin.php

Файл верхнего уровня wp_simple_location_plugin.php станет нашим основным файлом. Именно здесь мы загрузим наши стили из нашего каталога CSS, а также дополнительные файлы PHP из каталога include.

Класс основного местоположения

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

Нет прямого доступа

Рекомендуется заблокировать прямой доступ к вашим PHP-файлам, проверив, определена ли переменная ABSPATH (если это так, мы прекращаем выполнение). Добавьте следующий код сразу после открывающего тега PHP:

 defined( 'ABSPATH' ) or die( 'Nope, not accessing this' ); 

Объявление плагинов

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

 <?php  

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

Класс wp_simple_location

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

 class wp_simple_location{ } 

Включить шорткод и файлы виджетов

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

Перейдите в конец класса wp_simple_location и добавьте следующее:

 //include shortcodes include(plugin_dir_path(__FILE__) . 'inc/wp_location_shortcode.php'); //include widgets include(plugin_dir_path(__FILE__) . 'inc/wp_location_widget.php'); 

Это загрузит оба наших файла, которые мы рассмотрим позже.

Свойства класса

Свойства класса — это переменные, к которым можно обращаться из функций внутри класса.

Объявление свойств облегчает доступ к часто используемым элементам.

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

 //properties private $wp_location_trading_hour_days = array(); 

Функция _construct

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

Эта функция — magic функция; Магические функции — это специальные функции, добавленные в PHP5, которые запускаются автоматически при определенных условиях. Эта функция запускается в тот момент, когда создается экземпляр нашего класса (класс создается и присваивается переменной).

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

Скопируйте следующий код. Мы рассмотрим каждый элемент по одному, чтобы вы могли видеть, что происходит.

 //magic function (triggered on initialization) public function __construct(){ add_action('init', array($this,'set_location_trading_hour_days')); //sets the default trading hour days (used by the content type) add_action('init', array($this,'register_location_content_type')); //register location content type add_action('add_meta_boxes', array($this,'add_location_meta_boxes')); //add meta boxes add_action('save_post_wp_locations', array($this,'save_location')); //save location add_action('admin_enqueue_scripts', array($this,'enqueue_admin_scripts_and_styles')); //admin scripts and styles add_action('wp_enqueue_scripts', array($this,'enqueue_public_scripts_and_styles')); //public scripts and styles add_filter('the_content', array($this,'prepend_location_meta_to_content')); //gets our meta data and dispayed it before the content register_activation_hook(__FILE__, array($this,'plugin_activate')); //activate hook register_deactivation_hook(__FILE__, array($this,'plugin_deactivate')); //deactivate hook } 

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

Настройка местоположения Торговый час Дни

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

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

 //set the default trading hour days (used in our admin backend) public function set_location_trading_hour_days(){ //set the default days to use for the trading hours $this->wp_location_trading_hour_days = apply_filters('wp_location_trading_hours_days', array('monday' => 'Monday', 'tuesday' => 'Tuesday', 'wednesday' => 'Wednesday', 'thursday' => 'Thursday', 'friday' => 'Friday', 'saturday' => 'Saturday', 'sunday' => 'Sunday', ) ); } 

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

Настройка местоположения Торговый час Дни

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

Мы определяем метки и аргументы для типа контента и передаем наши аргументы в функцию register_post_type .

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

 //register the location content type public function register_location_content_type(){ //Labels for post type $labels = array( 'name' => 'Location', 'singular_name' => 'Location', 'menu_name' => 'Locations', 'name_admin_bar' => 'Location', 'add_new' => 'Add New', 'add_new_item' => 'Add New Location', 'new_item' => 'New Location', 'edit_item' => 'Edit Location', 'view_item' => 'View Location', 'all_items' => 'All Locations', 'search_items' => 'Search Locations', 'parent_item_colon' => 'Parent Location:', 'not_found' => 'No Locations found.', 'not_found_in_trash' => 'No Locations found in Trash.', ); //arguments for post type $args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable'=> true, 'show_ui' => true, 'show_in_nav' => true, 'query_var' => true, 'hierarchical' => false, 'supports' => array('title','thumbnail','editor'), 'has_archive' => true, 'menu_position' => 20, 'show_in_admin_bar' => true, 'menu_icon' => 'dashicons-location-alt', 'rewrite' => array('slug' => 'locations', 'with_front' => 'true') ); //register post type register_post_type('wp_locations', $args); } 

Если у вас есть это, вы должны увидеть новое меню для вашего типа сообщения

plugin_location_context_menu

Добавление мета-бокса к типу контента местоположения ‘

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

Внутри нашей функции мы вызываем функцию add_meta_box() и предоставляем наши аргументы.

 //adding meta boxes for the location content type*/ public function add_location_meta_boxes(){ add_meta_box( 'wp_location_meta_box', //id 'Location Information', //name array($this,'location_meta_box_display'), //display function 'wp_locations', //post type 'normal', //location 'default' //priority ); } 

Наше третье значение add_meta_box — это функция, которая будет отображать вывод для поля. Мы вызываем функцию location_meta_box_display которая является следующей функцией, которую мы добавим в наш класс

Отображение мета-окна местоположения

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

 //display function used for our custom location meta box*/ public function location_meta_box_display($post){ //set nonce field wp_nonce_field('wp_location_nonce', 'wp_location_nonce_field'); //collect variables $wp_location_phone = get_post_meta($post->ID,'wp_location_phone',true); $wp_location_email = get_post_meta($post->ID,'wp_location_email',true); $wp_location_address = get_post_meta($post->ID,'wp_location_address',true); ?> <p>Enter additional information about your location </p> <div class="field-container"> <?php //before main form elementst hook do_action('wp_location_admin_form_start'); ?> <div class="field"> <label for="wp_location_phone">Contact Phone</label> <small>main contact number</small> <input type="tel" name="wp_location_phone" id="wp_location_phone" value="<?php echo $wp_location_phone;?>"/> </div> <div class="field"> <label for="wp_location_email">Contact Email</label> <small>Email contact</small> <input type="email" name="wp_location_email" id="wp_location_email" value="<?php echo $wp_location_email;?>"/> </div> <div class="field"> <label for="wp_location_address">Address</label> <small>Physical address of your location</small> <textarea name="wp_location_address" id="wp_location_address"><?php echo $wp_location_address;?></textarea> </div> <?php //trading hours if(!empty($this->wp_location_trading_hour_days)){ echo '<div class="field">'; echo '<label>Trading Hours </label>'; echo '<small> Trading hours for the location (eg 9am - 5pm) </small>'; //go through all of our registered trading hour days foreach($this->wp_location_trading_hour_days as $day_key => $day_value){ //collect trading hour meta data $wp_location_trading_hour_value = get_post_meta($post->ID,'wp_location_trading_hours_' . $day_key, true); //dsiplay label and input echo '<label for="wp_location_trading_hours_' . $day_key . '">' . $day_key . '</label>'; echo '<input type="text" name="wp_location_trading_hours_' . $day_key . '" id="wp_location_trading_hours_' . $day_key . '" value="' . $wp_location_trading_hour_value . '"/>'; } echo '</div>'; } ?> <?php //after main form elementst hook do_action('wp_location_admin_form_end'); ?> </div> <?php } 

Давайте разберемся, что делает эта функция

  • Сначала он создает безопасное одноразовое поле для мета-блока ( одноразовые номера используются для проверки того, что действие отправки пришло из правильного места ).
  • Он собирает нашу телефонную, электронную почту и метаданные адреса (если таковые имеются).
  • Непосредственно перед wp_location_admin_form_start формы мы добавляем wp_location_admin_form_start действия wp_location_admin_form_start . Это позволит другим плагинам или темам подключаться к этому расположению, позволяя отображать дополнительные поля или информацию.
  • Отображает поля телефона, электронной почты и адреса (и предварительно заполняет их, если у нас есть какие-либо предыдущие значения).
  • Отображает список торговых часовых дней для местоположения. Здесь администратор может определять торговые часы на ежедневной основе. Эти дни могут быть динамическими, поскольку они присоединены к фильтру wp_location_trading_hours_days .
  • Непосредственно перед завершением формы мы добавляем wp_location_admin_form_end действия wp_location_admin_form_end . Это позволит другим плагинам или темам подключаться к этому расположению, позволяя отображать дополнительные поля или информацию.

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

plugin_location_background_box

Регистрация Типа контента и Правила Перезаписи Перезаписи при Активации

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

Несмотря на то, что мы регистрируем наш тип контента через ловушку init , нам все равно нужно вызвать из него register_location_content_type (чтобы убедиться, что наш тип контента был добавлен правильно)

Мы также очищаем правила перезаписи, чтобы мы могли использовать довольно постоянные ссылки для наших местоположений (у нас могут быть ссылки, такие как example.com/location/mylocation вместо example.com/?p=144 )

 //triggered on activation of the plugin (called only once) public function plugin_activate(){ //call our custom content type function $this->register_location_content_type(); //flush permalinks flush_rewrite_rules(); } 

Промывка Переписать правила деактивации

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

 //trigered on deactivation of the plugin (called only once) public function plugin_deactivate(){ //flush permalinks flush_rewrite_rules(); } 

Отображение мета-информации о нашем местоположении в одном месте

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

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

 public function prepend_location_meta_to_content($content){ global $post, $post_type; //display meta only on our locations (and if its a single location) if($post_type == 'wp_locations' && is_singular('wp_locations')){ //collect variables $wp_location_id = $post->ID; $wp_location_phone = get_post_meta($post->ID,'wp_location_phone',true); $wp_location_email = get_post_meta($post->ID,'wp_location_email',true); $wp_location_address = get_post_meta($post->ID,'wp_location_address',true); //display $html = ''; $html .= '<section class="meta-data">'; //hook for outputting additional meta data (at the start of the form) do_action('wp_location_meta_data_output_start',$wp_location_id); $html .= '<p>'; //phone if(!empty($wp_location_phone)){ $html .= '<b>Location Phone</b> ' . $wp_location_phone . '</br>'; } //email if(!empty($wp_location_email)){ $html .= '<b>Location Email</b> ' . $wp_location_email . '</br>'; } //address if(!empty($wp_location_address)){ $html .= '<b>Location Address</b> ' . $wp_location_address . '</br>'; } $html .= '</p>'; //location if(!empty($this->wp_location_trading_hour_days)){ $html .= '<p>'; $html .= '<b>Location Trading Hours </b></br>'; foreach($this->wp_location_trading_hour_days as $day_key => $day_value){ $trading_hours = get_post_meta($post->ID, 'wp_location_trading_hours_' . $day_key , true); $html .= '<span class="day">' . $day_key . '</span><span class="hours">' . $trading_hours . '</span></br>'; } $html .= '</p>'; } //hook for outputting additional meta data (at the end of the form) do_action('wp_location_meta_data_output_end',$wp_location_id); $html .= '</section>'; $html .= $content; return $html; }else{ return $content; } } 

Давайте рассмотрим, что делает эта функция:

  • Поскольку функция добавляется в хук the_content , она будет запускаться каждый раз при загрузке страницы. $post_type мы используем глобальные переменные $post и $post_type чтобы гарантировать, что мы находимся только на одной странице местоположения.
  • Мы собираем основную информацию о местоположении, такую ​​как электронная почта, телефон и адрес.
  • Как только мы собираемся отобразить нашу метаинформацию, мы вызываем wp_location_meta_data_output_start действия wp_location_meta_data_output_start . Это действие позволит другим плагинам или темам подключиться к начальному выводу метаинформации (если кто-то добавил новое поле в местоположение, этот хук можно использовать для отображения сохраненной информации).
  • Мы выводим электронную почту, телефон и адресную информацию.
  • Мы просматриваем нашу переменную wp_location_trading_hour_days и видим, определены ли дни. Если мы это сделаем, мы пройдемся по всем из них, соберем его торговые часы и отобразим их.
  • Непосредственно перед тем, как мы закончим весь наш вывод, мы вызываем действие wp_location_meta_data_output_end . Это действие позволит кому-либо вывести дополнительную информацию до закрытия мета-местоположения.

Получение списка местоположений

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

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

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

 //main function for displaying locations (used for our shortcodes and widgets) public function get_locations_output($arguments = ""){ //default args $default_args = array( 'location_id' => '', 'number_of_locations' => -1 ); //update default args if we passed in new args if(!empty($arguments) && is_array($arguments)){ //go through each supplied argument foreach($arguments as $arg_key => $arg_val){ //if this argument exists in our default argument, update its value if(array_key_exists($arg_key, $default_args)){ $default_args[$arg_key] = $arg_val; } } } //find locations $location_args = array( 'post_type' => 'wp_locations', 'posts_per_page'=> $default_args['number_of_locations'], 'post_status' => 'publish' ); //if we passed in a single location to display if(!empty($default_args['location_id'])){ $location_args['include'] = $default_args['location_id']; } //output $html = ''; $locations = get_posts($location_args); //if we have locations if($locations){ $html .= '<article class="location_list cf">'; //foreach location foreach($locations as $location){ $html .= '<section class="location">'; //collect location data $wp_location_id = $location->ID; $wp_location_title = get_the_title($wp_location_id); $wp_location_thumbnail = get_the_post_thumbnail($wp_location_id,'thumbnail'); $wp_location_content = apply_filters('the_content', $location->post_content); if(!empty($wp_location_content)){ $wp_location_content = strip_shortcodes(wp_trim_words($wp_location_content, 40, '...')); } $wp_location_permalink = get_permalink($wp_location_id); $wp_location_phone = get_post_meta($wp_location_id,'wp_location_phone',true); $wp_location_email = get_post_meta($wp_location_id,'wp_location_email',true); //apply the filter before our main content starts //(lets third parties hook into the HTML output to output data) $html = apply_filters('wp_location_before_main_content', $html); //title $html .= '<h2 class="title">'; $html .= '<a href="' . $wp_location_permalink . '" title="view location">'; $html .= $wp_location_title; $html .= '</a>'; $html .= '</h2>'; //image & content if(!empty($wp_location_thumbnail) || !empty($wp_location_content)){ $html .= '<p class="image_content">'; if(!empty($wp_location_thumbnail)){ $html .= $wp_location_thumbnail; } if(!empty($wp_location_content)){ $html .= $wp_location_content; } $html .= '</p>'; } //phone & email output if(!empty($wp_location_phone) || !empty($wp_location_email)){ $html .= '<p class="phone_email">'; if(!empty($wp_location_phone)){ $html .= '<b>Phone: </b>' . $wp_location_phone . '</br>'; } if(!empty($wp_location_email)){ $html .= '<b>Email: </b>' . $wp_location_email; } $html .= '</p>'; } //apply the filter after the main content, before it ends //(lets third parties hook into the HTML output to output data) $html = apply_filters('wp_location_after_main_content', $html); //readmore $html .= '<a class="link" href="' . $wp_location_permalink . '" title="view location">View Location</a>'; $html .= '</section>'; } $html .= '</article>'; $html .= '<div class="cf"></div>'; } return $html; } 
  • Во-первых, функция имеет необязательный аргумент под названием arguments . Это используется потому, что и шорткод, и виджет будут передавать параметры на дисплей (чтобы точно настроить, что будет возвращено).
  • Функция определяет набор аргументов по умолчанию в массиве $default_args . Это в основном установит число местоположений равным -1 (все местоположения), а также установит нулевой идентификатор местоположения (то есть мы хотим отобразить список местоположений, а не только одно по умолчанию).
  • Мы проверяем, не является ли переданная переменная $arguments не пустой и также является массивом (то есть мы передали массив аргументов). Мы просматриваем все элементы в массиве $arguments и проверяем, соответствует ли какой-либо из ключей массива чему-либо в нашем массиве $default_args . Если что-то совпадает, мы обновляем массив $default_args .
  • Мы используем массив $default_args чтобы построить поиск для get_posts() который найдет все наши местоположения (если мы указали одно местоположение, мы просто найдем его)
  • Теперь мы начинаем создавать наш вывод HTML. Мы определяем нашу переменную $html и начинаем строить наш вывод.
  • Мы собираем всю нашу информацию о местоположении (название, содержание, изображение, ссылки и т. Д.) И готовим ее к выводу.
  • Прежде чем мы продолжим собирать наши выходные данные, мы все wp_location_before_main_content в нашей переменной $html . Это позволит третьим лицам добавлять дополнительный контент перед названием местоположения. Это полезно, как если бы мы определили какие-либо дополнительные поля в нашем администраторе, мы можем использовать их для вывода.
  • Заголовок, изображение, контент, телефон и электронная почта добавляются к нашему выводу (условно проверяя, существуют ли они).
  • Прежде чем мы wp_location_after_main_content кнопку «читать дальше», мы вызываем наш второй фильтр — фильтр wp_location_after_main_content . Это позволит третьим лицам добавлять контент прямо перед кнопкой.
  • Мы добавляем нашу кнопку read more в вывод и затем возвращаем нашу переменную $html .

Сохранение дополнительной мета-информации для местоположений

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

Мы используем функцию save_location для этой цели.

 //triggered when adding or editing a location public function save_location($post_id){ //check for nonce if(!isset($_POST['wp_location_nonce_field'])){ return $post_id; } //verify nonce if(!wp_verify_nonce($_POST['wp_location_nonce_field'], 'wp_location_nonce')){ return $post_id; } //check for autosave if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){ return $post_id; } //get our phone, email and address fields $wp_location_phone = isset($_POST['wp_location_phone']) ? sanitize_text_field($_POST['wp_location_phone']) : ''; $wp_location_email = isset($_POST['wp_location_email']) ? sanitize_text_field($_POST['wp_location_email']) : ''; $wp_location_address = isset($_POST['wp_location_address']) ? sanitize_text_field($_POST['wp_location_address']) : ''; //update phone, memil and address fields update_post_meta($post_id, 'wp_location_phone', $wp_location_phone); update_post_meta($post_id, 'wp_location_email', $wp_location_email); update_post_meta($post_id, 'wp_location_address', $wp_location_address); //search for our trading hour data and update foreach($_POST as $key => $value){ //if we found our trading hour data, update it if(preg_match('/^wp_location_trading_hours_/', $key)){ update_post_meta($post_id, $key, $value); } } //location save hook //used so you can hook here and save additional post fields added via 'wp_location_meta_data_output_end' or 'wp_location_meta_data_output_end' do_action('wp_location_admin_save',$post_id, $_POST); } 

Давайте проанализируем, что мы делаем:

  • Сначала мы проверяем наш одноразовый номер и проверяем, существует ли он (передается из мета-блока). Мы также проверяем, что мы не сохраняем автоматически. Как только мы уверены, что все в порядке, мы идем дальше.
  • Мы собираем информацию о телефоне, электронной почте и адресе и очищаем их с помощью функции sanitize_text_field() . Они присваиваются переменным, а затем используются в нашей функции update_post_meta() для сохранения их в определенном месте.
  • Потому что наши торговые часы динамичны, и мы должны собирать и сохранять их немного по-другому. Поскольку мы не знаем, сколько их будет, мы не можем извлечь их из массива $_POST по имени. Итак, мы проходим все переменные $_POST и проверяем, начинается ли какая-либо из них с wp_location_trading_hours_ . Если они это сделают, мы обновляем их значение и сохраняем их как метаинформацию.
  • Наконец, перед тем, как мы закончим, мы вызываем действие wp_location_admin_save . Это действие примет текущий идентификатор местоположения как $post_id и позволит сторонней функции собирать дополнительную информацию из глобального $_POST и сохранять ее в этом местоположении.

Загрузка нашего администратора и общедоступных сценариев и стилей

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

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

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

 //enqueus scripts and stles on the back end public function enqueue_admin_scripts_and_styles(){ wp_enqueue_style('wp_location_admin_styles', plugin_dir_url(__FILE__) . '/css/wp_location_admin_styles.css'); } //enqueues scripts and styled on the front end public function enqueue_public_scripts_and_styles(){ wp_enqueue_style('wp_location_public_styles', plugin_dir_url(__FILE__). '/css/wp_location_public_styles.css'); } 

Расположение Шорткод

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

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

plugin_location_shortcode_output

Мы будем работать внутри файла wp_location_shortcode.php

Запретить прямой доступ

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

 defined( 'ABSPATH' ) or die( 'Nope, not accessing this' ); 

Класс wp_location_shortcode

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

 //defines the functionality for the location shortcode class wp_location_shortcode{ } 

Функция _construct

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

 //on initialize public function __construct(){ add_action('init', array($this,'register_location_shortcodes')); //shortcodes } 

Зарегистрируйте шорткод местоположения

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

Мы вызываем функцию add_shortcode для создания нового wp_locations именем wp_locations . Затем мы будем использовать функцию location_shortcode_output для вывода шорткода.

 //location shortcode public function register_location_shortcodes(){ add_shortcode('wp_locations', array($this,'location_shortcode_output')); } 

Построение вывода для шорткода

Эта функция вызывается из функции add_shortcode и используется для создания вывода для шорткода.

 //shortcode display public function location_shortcode_output($atts, $content = '', $tag){ //get the global wp_simple_locations class global $wp_simple_locations; //build default arguments $arguments = shortcode_atts(array( 'location_id' => '', 'number_of_locations' => -1) ,$atts,$tag); //uses the main output function of the location class $html = $wp_simple_locations->get_locations_output($arguments); return $html; } 

Давайте посмотрим, что делает эта функция:

  • Функция принимает аргументы шорткода $atts , содержимое между шорткодом $content и именем шорткода $tag . Мы используем эти элементы, чтобы помочь построить вывод
  • Мы $wp_simple_locations на глобальную переменную $wp_simple_locations чтобы у нас был доступ к основному классу местоположения (и всем его функциям).
  • Мы создаем массив аргументов по умолчанию для шорткода с помощью функции shortcode_atts() .
  • Мы используем функцию get_locations_output из объекта $wp_simple_locations для создания вывода $wp_simple_locations . Мы передаем наши аргументы, чтобы шорткод мог предоставлять динамический контент. Например, идентификатор местоположения может быть передан, поэтому возвращается только одно местоположение.
  • Мы возвращаем шорткод, и он отображается на любой странице или посте, к которому вы его добавили.

Создание нового объекта wp_location_shortcode

В конце вашего класса вы создадите новый объект wp_location_shortcode . Все функции внутри класса будут активированы, и вы сможете использовать свой новый шорткод.

 $wp_location_shortcode = new wp_location_shortcode; 

Виджет местоположения

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

Мы добавили поддержку виджетов, потому что почти все темы поддерживают виджеты, и они дают пользователю-администратору быстрый и простой способ продемонстрировать свое местоположение (или, возможно, одно местоположение).

Мы открываем файл wp_location_widget.php и начинаем.

Запретить прямой доступ

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

 defined( 'ABSPATH' ) or die( 'Nope, not accessing this' ); 

Класс wp_location_widget

Давайте создадим нашу базовую структуру для класса wp_location_widget .

Класс похож на другие наши классы, которые мы создали; однако на этот раз мы расширяем уже определенный класс WP_widget .

 //main widget used for displaying locations class wp_location_widget extends WP_widget{ } 

Функция _construct

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

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

 //initialise widget values public function __construct(){ //set base values for the widget (override parent) parent::__construct( 'wp_location_widget', 'WP Location Widget', array('description' => 'A widget that displays your locations') ); add_action('widgets_init',array($this,'register_wp_location_widgets')); } 

Создание интерфейса администратора для виджета

Интерфейс администратора — это то, с чем пользователь администратора будет взаимодействовать при настройке виджета.

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

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

  //handles the back-end admin of the widget //$instance - saved values for the form public function form($instance){ //collect variables $location_id = (isset($instance['location_id']) ? $instance['location_id'] : 'default'); $number_of_locations = (isset($instance['number_of_locations']) ? $instance['number_of_locations'] : 5); ?> <p>Select your options below</p> <p> <label for="<?php echo $this->get_field_name('location_id'); ?>">Location to display</label> <select class="widefat" name="<?php echo $this->get_field_name('location_id'); ?>" id="<?php echo $this->get_field_id('location_id'); ?>" value="<?php echo $location_id; ?>"> <option value="default">All Locations</option> <?php $args = array( 'posts_per_page' => -1, 'post_type' => 'wp_locations' ); $locations = get_posts($args); if($locations){ foreach($locations as $location){ if($location->ID == $location_id){ echo '<option selected value="' . $location->ID . '">' . get_the_title($location->ID) . '</option>'; }else{ echo '<option value="' . $location->ID . '">' . get_the_title($location->ID) . '</option>'; } } } ?> </select> </p> <p> <small>If you want to display multiple locations select how many below</small><br/> <label for="<?php echo $this->get_field_id('number_of_locations'); ?>">Number of Locations</label> <select class="widefat" name="<?php echo $this->get_field_name('number_of_locations'); ?>" id="<?php echo $this->get_field_id('number_of_locations'); ?>" value="<?php echo $number_of_locations; ?>"> <option value="default" <?php if($number_of_locations == 'default'){ echo 'selected';}?>>All Locations</option> <option value="1" <?php if($number_of_locations == '1'){ echo 'selected';}?>>1</option> <option value="2" <?php if($number_of_locations == '2'){ echo 'selected';}?>>2</option> <option value="3" <?php if($number_of_locations == '3'){ echo 'selected';}?>>3</option> <option value="4" <?php if($number_of_locations == '4'){ echo 'selected';}?>>4</option> <option value="5" <?php if($number_of_locations == '5'){ echo 'selected';}?>>5</option> <option value="10" <?php if($number_of_locations == '10'){ echo 'selected';}?>>10</option> </select> </p> <?php } 

Давайте рассмотрим, что здесь происходит:

  • Сначала мы определяем значения для нашего идентификатора местоположения и количества местоположений. Мы проверяем, $instanceсодержит ли переменная какое-либо из этих значений (если они уже существуют). Если значения существуют, мы извлекаем их, если их нет, мы просто предоставляем значения по умолчанию (устанавливая количество местоположений на 5 и идентификатор местоположения по умолчанию).
  • Мы создаем метку и поле формы, которые будут использоваться для отображения местоположений для администратора. Мы выбираем все местоположения и показываем их. Мы проверяем каждое местоположение, чтобы увидеть, соответствует ли оно значению, сохраненному в идентификаторе местоположения (если оно было установлено).get_posts()
  • Мы создаем список выбора для количества мест для отображения. Снова мы проверяем каждую опцию, чтобы увидеть, соответствует ли она значению, переданному в переменную количества местоположений.

Обновление виджета и параметров сохранения

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

Функция снова наследуются от родительского класса , поэтому мы просто указать , как мы собираемся , чтобы сохранить наши ценностиupdate()WP_widget

 //handles updating the widget //$new_instance - new values, $old_instance - old saved values public function update($new_instance, $old_instance){ $instance = array(); $instance['location_id'] = $new_instance['location_id']; $instance['number_of_locations'] = $new_instance['number_of_locations']; return $instance; } 

Нам даны две переменные, $new_instanceи $old_instance.

Новый экземпляр содержит наши текущие значения в форме, а старый экземпляр содержит наши предыдущие значения.

Мы создаем новый массив для хранения извлеченных значений, а затем возвращаем их.

Отображение виджета на внешнем интерфейсе

Эта функция является другой функцией, унаследованной от родительского класса, и отвечает за вывод виджета для внешнего интерфейса. Он использует функцию отображения из класса для создания выходных данных.widget()WP_widgetwp_simple_locations

 //handles public display of the widget //$args - arguments set by the widget area, $instance - saved values public function widget( $args, $instance ) { //get wp_simple_location class (as it builds out output) global $wp_simple_locations; //pass any arguments if we have any from the widget $arguments = array(); //if we specify a location //if we specify a single location if($instance['location_id'] != 'default'){ $arguments['location_id'] = $instance['location_id']; } //if we specify a number of locations if($instance['number_of_locations'] != 'default'){ $arguments['number_of_locations'] = $instance['number_of_locations']; } //get the output $html = ''; $html .= $args['before_widget']; $html .= $args['before_title']; $html .= 'Locations'; $html .= $args['after_title']; //uses the main output function of the location class $html .= $wp_simple_locations->get_locations_output($arguments); $html .= $args['after_widget']; echo $html; } 

Давайте пройдемся по тому, что мы сделали:

  • Мы собираем наш глобальный $wp_simple_locationsобъект так, как хотим использовать его функцию отображения.
  • Мы создаем пустой массив аргументов и затем проверяем, указал ли наш виджет какие-либо аргументы (например, количество отображаемых местоположений или одно конкретное местоположение).
  • Мы запускаем процесс сборки для вывода и определяем нашу $htmlпеременную. Мы вызываем функцию, определенную в объекте, и передаем наши аргументы (она вернет весь необходимый нам HTML).get_locations_output()$wp_simple_locations
  • Мы повторяем результат нашей $htmlпеременной, и виджет отображается.

Регистрация виджета для использования

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

 //registers our widget for use public function register_wp_location_widgets(){ register_widget('wp_location_widget'); } 

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