В этой серии мы рассмотрим самые важные вещи, которые следует учитывать при разработке плагина WordPress или темы WordPress.
Цель этого руководства — предоставить набор полезных практик, которые будут полезны как новичкам, так и опытным разработчикам, начинающим работать с WordPress.
Но ждать! Если вы разрабатывали плагины для WordPress какое-то время, посмотрите, прежде чем решить, что это руководство не для вас. Я уверен, что вы получите что-то из этого. В конце концов, мы все можем предложить что-то уникальное.
Большая часть объяснений этой серии уже существует в Кодексе , но я знаю, что она содержит так много информации, что может быть трудно понять, с чего начать.
Сегодня мы освещаем следующие темы:
- Стандарты кодирования WordPress
- Предотвращение столкновений имен функций
- Комментарии к коду
- Советы по безопасности
Целью данной серии является максимально четкая и включающая как хорошие, так и базовые примеры, чтобы дать представление о том, как определенные вещи должны работать при написании кода для WordPress.
Обратите внимание, что не все обязательно, чтобы написать плагин; однако, если вы только начинаете, то почему бы не начать с правой ноги?
Я постараюсь сделать эти серии легко читаемыми. Я включу несколько хороших и плохих примеров кода. Не все, что здесь описано, является обязательным для написания плагина, но если вы начинаете с разработки WordPress, почему бы не начать правильный путь? Как только это станет привычкой, будет трудно сделать это неправильно.
Стандарты кодирования WordPress
Собственно говоря, это один из моих самых больших недостатков при разработке плагинов. Если вы разрабатываете инструменты для WordPress, вы должны просто следовать стандартам WordPress Coding . Стандарты кодирования помогают улучшить читаемость кода и помогает избежать распространенных ошибок кодирования.
WordPress — это совместная CMS, и такая простая вещь, что каждый, кто пишет код одинаково, делает чтение, написание и поддержку кода более простым для всех. В начале может быть трудно изменить стиль кодирования, с которым вы привыкли работать, но в конечном итоге вы обнаружите, что он станет второй натурой, и ваш код станет чище и намного проще для чтения.
В Руководстве по WordPress стандарты разделены на четыре основных используемых языка.
- Стандарты CSS кодирования
- Стандарты HTML-кодирования
- Стандарты кодирования JavaScript
- Стандарты кодирования PHP
Примеры
Ниже я покажу вам несколько простых примеров стиля скобки PHP, чтобы вы могли получить представление.
Плохие примеры
01
02
03
04
05
06
07
08
09
10
11
12
|
if(condition)
action0($var);
if(condition)
{
action1();
}
elseif(condition2)
{
action2a();
action2b();
}
|
Хорошие примеры
01
02
03
04
05
06
07
08
09
10
|
if ( condition ) {
action0( $var );
}
if ( condition ) {
action1();
} elseif ( condition2 ) {
action2a();
action2b();
}
|
Второй пример намного легче читать, не так ли? Справочник по стандартам кодирования полон примеров, которые помогут вам сделать ваш код чище. Легко удивиться тому, как что-то простое, например, несколько пробелов и табуляции, может улучшить читаемость кода .
Во время написания этой статьи я купил тему для клиента, и когда я приступил к редактированию некоторого кода, я был шокирован тем, как трудно это было сделать.
Вот что я имею в виду:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<?php if (have_posts()){
$row_count=0;
while (have_posts()){ the_post();
$row_count++;
$post_id = get_the_ID();
//get all post categories
$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’);
<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 «
}
}?>
</div>
|
Немного страшно, правда? После нескольких минут работы с этим кодом я отправил автору электронное письмо со ссылкой на Книгу стандартов кодирования.
Предотвращение столкновений имен функций
Конфликты имен происходят, когда функция имеет то же имя, что и функция, которая уже была определена. Например, если в вашей теме у вас есть функция get_the_post_terms()
и вы устанавливаете плагин с функцией с таким же именем, вы получите что-то вроде:
1
|
Fatal error: Cannot redeclare get_the_post_terms() (previously declared in….
|
К сожалению, они случаются гораздо чаще, чем должны. Дело в том, что этого легко избежать.
Чтобы избежать этого у нас есть варианты:
1. Префикс ваших функций
Например, если ваш плагин называется «WordPress Cool Plugin», вы можете использовать префикс wcc_
во всех своих функциях.
Таким образом, в приведенном выше примере имя нашей функции будет wcc_get_the_post_terms()
Я также рекомендую вам префикс вашего CSS или, по крайней мере, попытаться сделать его более уникальным, чтобы избежать изменения других стилей плагинов
2. Оберните свои функции внутри класса
Возможно, ваш плагин настолько прост, что ему не нужен класс, но вы все равно можете создать его, чтобы все было организовано. Мне особенно нравится использовать шаблон синглтона, но посмотрите пример ниже для простого класса со статическим методом.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
class Wcc_Mailer {
static function send( $post_ID ) {
$friends = ‘[email protected]’;
mail( $friends,»New post!», ‘Check my new post in ‘ . get_permalink( $post_ID ) );
return $post_ID;
}
}
add_action( ‘publish_post’, array( ‘Wcc_Mailer’, ‘send’ ) );
|
Как вы можете видеть из этого примера, у меня есть только префикс имени класса, но моя функция называется просто «отправить». Имя этого метода теперь защищено от глобального пространства имен и не может быть вызвано напрямую. Чтобы позвонить, мне нужно сделать это:
1
|
Wcc_Mailer::send( $post_id );
|
Код комментирования
Комментарии кода — лучший друг разработчика. Вы можете счесть ненужным комментировать каждую отдельную функцию или переменную, которую вы создаете, но поверьте мне, когда ваш код расширяется — особенно когда он получает вклады от других — может быть трудно точно знать, что делать.
Также, как я уже говорил, WordPress — это совместная CMS. Многие разработчики изучат ваш код и с некоторой помощью пойдут по правильному пути.
Я лично использую синтаксис PHPDoc для комментирования своих функций, и с помощью Sublime + Docblockr это действительно легко сделать.
Давайте посмотрим, как ребята из WordPress комментируют wp_mail()
расположенную в wp-includes/pluggable.php
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/**
* Send mail, similar to PHP’s mail
*
* A true return value does not automatically mean that the user received the
* email successfully.
* process the request without any errors.
*
* Using the two ‘wp_mail_from’ and ‘wp_mail_from_name’ hooks allow from
* creating a from address like ‘Name <[email protected]>’ when both are set.
* just ‘wp_mail_from’ is set, then just the email address will be used with no
* name.
*
* The default content type is ‘text/plain’ which does not allow using HTML.
* However, you can set the content type of the email by using the
* ‘wp_mail_content_type’ filter.
*
* The default charset is based on the charset used on the blog.
* be set using the ‘wp_mail_charset’ filter.
*
* @since 1.2.1
*
* @uses PHPMailer
*
* @param string|array $to Array or comma-separated list of email addresses to send message.
* @param string $subject Email subject
* @param string $message Message contents
* @param string|array $headers Optional.
* @param string|array $attachments Optional.
* @return bool Whether the email contents were sent successfully.
*/
function wp_mail( $to, $subject, $message, $headers = », $attachments = array() ) {
[….]
// Send!
try {
return $phpmailer->Send();
} catch ( phpmailerException $e ) {
return false;
}
}
|
Как вы можете видеть, они описывают, что делает функция, какие параметры необходимы и что она собирается возвращать.
Довольно понятно, верно?
Комментарии не предназначены для использования только с PHP. Например, в HTML я люблю использовать <!--#id-of-div-->
в конце больших блоков кода, чтобы не потеряться так легко.
Для CSS я использую комментарии, чтобы разделить мой код на разные разделы.
Например :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/*********************
GENERAL STYLES
*********************/
body {
font-family: Arial;
color: #333;
}
/******************************************************************
H1, H2, H3, H4, H5 STYLES
******************************************************************/
h1, .h1 {
font-size: 2.5em;
line-height: 1em;
font-family: $vag-bold;
}
/*********************
NAVIGATION STYLES
*********************/
nav {
color:red
}
[…]
|
Поделитесь с нами своими комментариями!
Советы по безопасности
К безопасности нужно относиться очень серьезно! Если ваш плагин или тема становятся популярными, поверьте мне, вы не хотите быть виновником тысяч взломанных сайтов. Если вы считаете, что я преувеличиваю, взгляните на исследование Checkmarx, проведенное в 2013 году, о 50 лучших плагинах WordPress.
Теперь давайте посмотрим несколько советов по безопасности разработки WordPress:
XSS Уязвимости
Чтобы предотвратить XSS, мы должны сделать две вещи. Санитарная обработка ввода данных и дезинфекция выходных данных . У нас есть несколько методов санации в зависимости от данных и используемого контекста. По общему правилу вам не нужно доверять никаким входным данным и не доверять никаким данным, которые будут выводиться.
Для входных данных вы можете использовать, например, sanitize_text_field()
который проверяет недействительный UTF-8, конвертировать одиночные символы <в сущность, вырезать все теги, удалить разрывы строк, табуляции и лишние пробелы и октеты. В зависимости от вашего контекста, существуют различные функции, которые помогут вам очистить ваши данные.
То же самое происходит, когда вы выводите свои данные. Проверьте следующий пример о том, как вывести ссылку:
1
|
<a href=»<?php echo esc_url( $url ); ?>»><?php echo esc_html( $text );
|
esc_url
отклоняет недействительные URL, удаляет недопустимые символы и удаляет опасные символы
esc_html
кодирует <> & «‘при выводе HTML.
Опять же, в зависимости от имеющихся у вас данных, вам могут помочь разные функции. Для JavaScript вы можете использовать esc_js
.
В дополнение к санитарной обработке, не забудьте также подтвердить свою дату.
Запретить прямой доступ к вашим файлам
Большинство хостов позволяют прямой доступ к файлам. В вашем плагине это означает, что, скорее всего, возникнут некоторые ошибки PHP, и эти ошибки представляют собой ценную информацию для злоумышленников.
Очень простой код для предотвращения этого, который вы можете поместить поверх вашего скрипта:
1
2
|
// Exit if accessed directly
if ( ! defined( ‘ABSPATH’ ) ) exit;
|
Это в основном препятствует выполнению скрипта, если мы не обращаемся к нему через WordPress.
Удалить все предупреждения и уведомления
Злоумышленникам помогают не только ошибки PHP — уведомления и предупреждения также содержат много ценной информации. Каждый плагин должен быть закодирован в режиме DEBUG . Это также поможет поймать устаревшие функции в вашем плагине. Чтобы включить режим DEBUG
просто найдите эту строку в вашем wp-config.php
и измените ее на TRUE
.
1
|
define( WP_DEBUG, true );
|
Наряду с этим, вы должны попробовать отличный плагин Debug Bar . Добавив эту другую простую строку, вы также сможете анализировать все запросы к базе данных.
1
|
define( ‘SAVEQUERIES’, true );
|
Использовать одноразовые значения
Одноразовые значения являются короткими для чисел, используемых один раз, и используются для защиты от подделки межсайтовых запросов или CSRF, то есть, другими словами, это непредвиденные или дублирующие запросы, которые могут вызвать нежелательные постоянные или необратимые изменения на веб-сайте, и особенно на его база данных. Все это может быть выполнено злоумышленником или простой ошибкой доверенного пользователя.
В зависимости от того, где вам нужен одноразовый номер, вы можете создать его различными способами:
Чтобы использовать его в ссылке, используйте wp_nonce_url()
1
|
$complete_url = wp_nonce_url( $bare_url, ‘trash-post’, ‘my_nonce’ );
|
Чтобы использовать его в форме, используйте wp_nonce_field()
1
|
wp_nonce_field( ‘trash-post’, ‘my_nonce’ );
|
Чтобы использовать его в любом другом месте, используйте wp_create_nonce()
1
|
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-вызовы.
Затем в своем скрипте, чтобы просто проверить одноразовый номер, введите следующий код
1
2
3
|
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
, которые не только будут кодировать данные, но и будут предлагать wp_remote_get
wp_remote_post
случае сбоя cURL
.
Другим примером будет использование get_template_part()
вместо использования PHP-функций require()
или include()
. Хотя они в основном одинаковы, первый уже знает, где находится ваша тема, и будет искать запрошенный файл в каталоге этой темы. Он не выдаст предупреждение или неустранимую ошибку, если запрошенный файл не существует, он может ищите другие подходящие файлы, если запрашиваемый файл не найден и он знает о дочерних и родительских темах.
Ядро WordPress включает в себя множество скриптов, которые мы можем использовать в наших плагинах или темах. Поэтому всегда смотрите перед добавлением новых библиотек.
Что дальше?
Я надеюсь, что вы многое узнали из этой статьи. Как я упоминал в начале, большая часть этой информации уже существует в Кодексе, который должен стать вашей первой остановкой, когда вы начали свое приключение по разработке WordPress.
Когда я начал разрабатывать с WordPress несколько лет назад, мне было жаль, что у меня не было такого руководства со всей этой информацией, поэтому я решил написать эту серию.
В следующей статье я объясню следующие темы:
- Правильный способ добавить JavaScript и таблицы стилей в ваш плагин
- Как правильно использовать Ajax в WordPress
- Пусть ваши пользователи делают изменения с помощью хуков
Пожалуйста, не стесняйтесь оставлять свои комментарии или предложения для двух оставшихся статей в этой серии.