Полезные советы для разработчиков на WordPress

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

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

Однако! Если вы уже давно занимаетесь разработкой плагинов WordPress, не спешите закрывать эту страницу, решив, что это руководство не для вас. Я уверен, что и вы найдете в нем что-то полезное для себя. В конце концов, каждому из нас есть чем поделиться с другими, чем-то уникальным.

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

В этой статье мы рассмотрим следующие темы:

  • Стандарты кодирования WordPress;
  • Как избежать конфликта названий функций;
  • Код комментариев;
  • Советы по безопасности.

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

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

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

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

Стандарты кодирования WordPress

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

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

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

В Руководстве WordPress стандарты делятся по четырем основным используемым языкам:

  1. Стандарты кодирования CSS
  2. Стандарты кодирования НTML
  3. Стандарты кодирования JavaScript
  4. Стандарты кодирования PHP

Примеры

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

Ошибки:

if(condition)
    action0($var);

if(condition)
{
    action1();
}
elseif(condition2)
{
    action2a();
    action2b();
}

Примеры правильного кодирования:

if ( condition ) {
    action0( $var );
}

if ( condition ) {
    action1();
} elseif ( condition2 ) {
    action2a();
    action2b();
}

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

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

Вот то, что я имею в виду:

<?php if (have_posts()){ 
    $row_count=0; 
    while (have_posts()){ the_post(); 
    $row_count++;
     $post_id = get_the_ID();
     //получение всех категорий записей
$categories = get_the_category(get_the_ID());
?>
        <div <?php if(!of_get_option('disable_css_animation')==1){?><?php post_class('feature-two-column medium-two-columns appear_animation'); ?><?php }else{?> <?php post_class('feature-two-column medium-two-columns'); ?> <?php }?><?php if($row_count % 2 != 0){echo ' id="margin-left-post-'.$row_count.'"';}?>>
<div class="image_post feature-item">
<a  href="<?php the_permalink(); ?>" class="feature-link" title="<?php the_title_attribute(); ?>">              
<?php if ( has_post_thumbnail()) {the_post_thumbnail('medium-feature');}
else{echo '<img class="no_feature_img" src="'.get_template_directory_uri().'/img/feature_img/medium-feature.jpg'.'">';} ?>
</a>
 
<?php echo jellywp_post_type(); ?>
 
 <?php echo total_score_post_front(get_the_ID());?>                           
<?php  if(of_get_option('disable_post_category') !=1){
if ($categories) {
    echo '<span class="meta-category">';
    foreach( $categories as $tag) {
        $tag_link = get_category_link($tag->term_id);
        $titleColor = categorys_title_color($tag->term_id, "category", false);
     echo '<a class="post-category-color" style="background-color:'.$titleColor.'" href="'.$tag_link.'">'.$tag->name.'</a>';                 
    }
    echo "</span>";
    }
}?>
 
 </div>

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

Как избежать конфликтов имен функций

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

Fatal error: Cannot redeclare get_the_post_terms() (previously declared in....

К сожалению, это происходит гораздо чаще, чем следовало бы. Но таких конфликтов легко избежать.

Для этого у нас есть следующие варианты:

1. Префиксы функций

Например, если ваш плагин называется «WordPress Cool Plugin», вы можете использовать префикс wcc_ для всех его функций.

Таким образом, в приведенном выше примере название нашей функции будет выглядеть, как wcc_get_the_post_terms().

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

2. Заключите функции в класс

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

class Wcc_Mailer {

  static function send( $post_ID )  {

    $friends = 'jhondoe@example.org';

    mail( $friends,"New post!", 'Check my new post in ' . get_permalink( $post_ID ) );

    return $post_ID;

  }

}
add_action( 'publish_post', array( 'Wcc_Mailer', 'send' ) );

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

Wcc_Mailer::send( $post_id );

Код комментариев

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

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

Лично я использую для комментирования функций синтаксис PHPDoc, с применением Sublime + Docblockr это делается очень просто.

Давайте посмотрим, как ребята из WordPress комментируют функцию wp_mail(), расположенную в файле wp-includes/pluggable.php:

/**
 * Отправляет почтовые сообщения, аналогичные почте PHP
 *
 * Возвращаемое значение true не значит автоматически, что пользователь получил
 * письмо. Это только значит, что использованный метод выполнил
 * запрос без ошибок.
 *
 * Использование обращений 'wp_mail_from' и 'wp_mail_from_name' позволяет
 * задавать адрес отправителя в следующем формате 'Name <email@address.com>',
 * если заданы оба обращения. Если использовано только обращение 'wp_mail_from', 
 * в адресе отправителя будет указывать только электронная почта.
 *
 * Тип контента по умолчанию - 'text/plain', что не позволяет использование HTML.
 * Однако вы можете задать тип контента электронных сообщений, использовав
 * фильтр 'wp_mail_content_type'.
 *
 * Кодировка по умолчанию соответствует кодировке применяемой в блоге. Другая 
 * кодировка может быть установлена через фильтр 'wp_mail_charset'.
 *
 * @since 1.2.1
 *
 * @uses PHPMailer
 *
 * @param string|array $to Массив или разделенный запятыми список e-mail адресов для рассылки писем.
 * @param string $subject Тема письма
 * @param string $message Текст сообщения
 * @param string|array $headers Опционально. Дополнительный заголовок.
 * @param string|array $attachments Опционально. Прикрепленные файлы.
 * @return bool Всегда, когда содержимое письма было отправлено успешно.
 */
function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {

    [....]

    // Отправлено!
    try {
        return $phpmailer->Send();
    } catch ( phpmailerException $e ) {
        return false;
    }

}

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

Комментарии не предназначены для использования только с PHP. В HTML, я например, люблю использовать <!—#id-of-div—> в конце больших блоков кода, поэтому мне намного проще потом ориентироваться в коде.

В CSS я использую комментарии, чтобы разделить код на разные разделы.

Например:

/*********************
ОБЩИЕ СТИЛИ
*********************/
body {
    font-family: Arial;
    color: #333;
}

/******************************************************************
СТИЛИ H1, H2, H3, H4, H5
******************************************************************/
h1, .h1 {
    font-size: 2.5em;
    line-height: 1em;
    font-family: $vag-bold;
}
/*********************
СТИЛИ МЕНЮ НАВИГАЦИИ
*********************/
nav {
    color:red
}

[...]

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

Советы по безопасности

К безопасности нужно относиться очень серьезно! Если ваш плагин или тема становятся популярными, поверьте мне, вы не захотите, чтобы по вашей вине были взломаны тысячи сайтов.

Если вы думаете, что я преувеличиваю, посмотрите на исследования Сheckmarx, проведенные ими в 2013 году среди 50 лучших плагинов WordPress.

Теперь давайте рассмотрим некоторые советы по безопасности разработки для WordPress:

XSS-уязвимости

Для предотвращения XSS мы должны сделать две вещи. Проверять безопасность входящих данных и проверять безопасность исходящих данных.

Существует несколько методов для проверки безопасности в зависимости от данных и контекста, в котором они используются. Общее правило: вы не должны доверять любым вводящим данным, и не должны доверять любым данным, которые выводятся.

Для ввода данных можно использовать, например, sanitize_text_field(), которая проверяет недопустимый текст UTF-8, конвертирует в объект одиночные символы <, убирает все теги, удаляет разрывы строк, отступы и лишние пробелы, а также убирает октеты. В зависимости от контекста, существуют разные функции, которые помогут вам обезопасить данные.

То же самое происходит, когда вы выводите данные. Взгляните на следующий пример того, как выводится ссылка:

<a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $text ); ?></a>
  • esc_url отвергает неверные URL-адреса, устраняет недопустимые символы и удаляет опасные символы;
  • esc_html кодирует & «‘при выводе HTML.

Опять же, в зависимости от данных, которые вы имеете, существуют различные функции, которые могут вам помочь. Для JavaScript вы можете использовать esc_js.

Кроме проверки самих данных, не забудьте проверить и дату.

Предотвращение прямого доступа к файлам

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

Чтобы предотвратить это, вы можете разместить в верхней части вашего скрипта очень простой код:

// Выход, если предоставлен прямой доступ
if ( ! defined( 'ABSPATH' ) ) exit;

Это в целом помешает выполнить скрипт, если доступ к нему получен не через WordPress.

Удалите все предупреждения и уведомления

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

Это также помешает злоумышленникам вычислить устаревшие функции в вашем плагине. Чтобы включить режим DEBUG просто найдите эту строку в файле wp-config.php и установите значение TRUE:

define( WP_DEBUG, true );

Наряду с этим, я рекомендую использовать отличный плагин Debug Bar. Изменив эту строку, вы также будете иметь возможность анализировать все запросы к базе данных.

Используйте значения Nonce

Nonce-значения — это сокращение от numbers used once (однократно использованные числа), они используются для защиты от ложных запросов между сайтами, или CSRF.

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

В зависимости от того, где вам нужно применить значение Nonce, вы можете создавать его по-разному.

Для ссылок используйте wp_nonce_url():

$complete_url = wp_nonce_url( $bare_url, 'trash-post', 'my_nonce' );

Для форм — wp_nonce_field():

wp_nonce_field( 'trash-post', 'my_nonce' );

В других местах — wp_create_nonce():

wp_localize_script( 'my-script', 'my-var-name', array( 'nonce' => wp_create_nonce(  'trash-post', 'my_nonce'  ) );

Если вы посмотрите на приведенный выше пример, то увидите, как я использую wp_localize_script (о которой речь пойдет в следующей статье), чтобы включить nonce в блок кода JavaScript. Я делаю это, потому что позже планирую использовать JQuery для выполнения запроса AJAX, и вы тоже всегда должны включать nonce в вызовы AJAX.

После этого в скрипте, просто для проверки nonce, используйте следующий код:

if( ! wp_verify_nonce( 'trash_post' , 'my_nonce') ) {
    die( 'Busted!');
}

Используйте функции и библиотеки WordPress

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

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

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

Еще один пример — использование get_template_part() вместо функций РНР require() или include().

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

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

Перевод статьи «Tips for Best Practices in WordPress Development» был подготовлен дружной командой проекта Сайтостроение от А до Я.