У цій серії статей ми плануємо розглянути основні моменти, які слід враховувати при розробці плагіна або теми WordPress.

Метою цього посібника є представити вам набір передових практик, які будуть корисними як для початківців, так і для досвідчених фахівців-розробників, які починають працювати з WordPress.

Однак! Якщо ви вже давно займаєтеся розробкою плагінів WordPress, не поспішайте закривати цю сторінку, вирішивши, що це керівництво не для вас. Я впевнений, що і ви знайдете в ньому щось корисне для себе. Зрештою, кожному з нас є чим поділитися з іншими, чимось унікальним.

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

У цій статті ми розглянемо такі теми:

  • Стандарти кодування WordPress;
  • Як уникнути конфлікту назв функцій;
  • Код коментарів;
  • Поради щодо безпеки.

Ми постараємося в цій серії бути як можна більш конкретними, тому в статті будуть включені як приклади ефективного застосування методів, так і приклади типових помилок. Це дасть вам чітке уявлення того, як в WordPress працюють певні речі.

Зверніть увагу, що не все описане в цій серії обов’язково застосовувати при розробці плагінів. Однак якщо ви вже приступаєте до навчання, чому б навчитися робити це правильно?

Я постараюся, щоб статті цієї серії були легкими для розуміння. Я буду включати в статті деякі приклади правильно складеного коду і приклади помилок. Не все описане тут є обов’язковим при створенні плагіна, але якщо ви починаєте роботу з WordPress, чому б не зробити це правильно?

Після того, як це увійде у вас в звичку, ви автоматично будете дотримуватися стандартів, і вам простіше буде вберегтися від помилок.

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

Чесно кажучи, це один з моїх самих серйозних недоліків. Якщо ви розробляєте інструменти для WordPress, ви повинні просто слідувати Стандартам кодування WordPress. Це допомагає підвищити читаність коду і уникнути поширених помилок.

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

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

У Керівництві WordPress стандарти діляться по чотирьом основним використовуваним мов:

  • Стандарти кодування CSS
  • Стандарти кодування НTML
  • Стандарти кодування JavaScript
  • Стандарти кодування PHP
  • Приклади

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

    Помилки:

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

    Приклади правильного кодування:

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

    Другий приклад коду набагато більше читаємо, чи не так? У Посібнику стандартам кодування багато прикладів, які допоможуть вам зробити код чистіше. Ви будете вражені тим, як же просто за допомогою декількох пропусків і відступів значно підвищити читаність коду.

    У той час як я займався написанням цієї статті, я якраз купив тему для одного свого клієнта і, коли захотів трохи змінити її код, я був вражений, як же важко це зробити.

    Ось те, що я маю на увазі:


    ‘;
    foreach( $categories as $tag) {
    $tag_link = get_category_link($tag->term_id);
    $titleColor = categorys_title_color($tag->term_id, «category», false);
    echo «.$tag->name.»;
    }
    echo ««;
    }
    }?>

    Навіть трохи страшно, чи не правда? Після декількох хвилин роботи з цим кодом я послав автору теми електронний лист з посиланням на сторінку керівництва за стандартами кодування.

    Як уникнути конфліктів імен функцій

    Конфлікти імен відбуваються, коли функція має те ж ім’я, що і функція, яка вже була визначена раніше. Наприклад, якщо у вас в темі є функція 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 = ‘[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’ ) );

    Як бачите, в цьому прикладі я просто використовував префікс імені класу, але моя функція називається «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 ‘,
    * якщо задані обидва звернення. Якщо використано тільки звернення ‘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, я наприклад, люблю використовувати в кінці великих блоків коду, тому мені набагато простіше потім орієнтуватися в коді.

    В CSS я використовую коментарі, щоб розділити код на різні розділи.

    Наприклад:

    /*********************
    ЗАГАЛЬНІ СТИЛІ
    *********************/
    body {
    font-family: Arial;
    color: #333;
    }
    /******************************************************************
    СТИЛІ H1, H2, H3, H4, H5
    ******************************************************************/
    h1, .h1 {
    font-size: 2.5 em;
    line-height: 1em;
    font-family: $vag-bold;
    }
    /*********************
    СТИЛІ МЕНЮ НАВІГАЦІЇ
    *********************/
    nav {
    color:red
    }
    […]

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

    Поради з безпеки

    До безпеки потрібно ставитися дуже серйозно! Якщо ваш плагін або тема стають популярними, повірте мені, ви не захочете, щоб з вашої вини були зламані тисячі сайтів.

    Якщо ви думаєте, що я перебільшую, подивіться на дослідження Сһескмагх, проведені ними в 2013 році серед 50 кращих плагінів WordPress.

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

    XSS-вразливості

    Для запобігання XSS ми повинні зробити дві речі. Перевіряти безпеку вхідних даних і перевіряти безпеку вихідних даних.

    Існує кілька методів для перевірки безпеки в залежності від даних і контексту, в якому вони використовуються. Загальне правило: ви не повинні довіряти будь-яким вводить даними, і не повинні довіряти будь-яких даних, що виводяться.

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

    Те ж саме відбувається, коли ви виводите дані. Погляньте на наступний приклад того, як виводиться посилання:

    • 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» був підготовлений дружною командою проекту Сайтостроение від А до Я.