PHP код у WordPress – стандарти
Щоб код WordPress скрізь був оформлений в одному стилі і зручно читався в ядрі, плагінах і темах, рекомендується дотримуватися стандартів написання коду, прийнятих розробниками WordPress. Ці стандарти дуже схожі на стандарт PEAR , однак є кардинальні відмінності. Рекомендую ознайомитись з ними і при створенні плагінів або тим, по можливості, їх дотримуватись.
PHP Documentation Standards (англ.) – стандарти документування PHP коду – це коментарі до функцій та хуків.
JavaScript Documentation Standards – стандарти документування JS коду.
Додаток до написаного тут (оновлення для версії PHP 5.6): Coding Standards Updates for PHP 5.6
Одинарні та подвійні лапки
Якщо рядок немає змінних, використовуйте одинарні лапки, в інших випадках подвійні. Не потрібно екранувати лапки у рядку і якщо вони є, то рекомендується їх чергувати:
echo '<a href="/static/link" title="Yeah yeah!">Link name</a>'; echo "<a href='$link' title='$linktitle'>$linkname</a>";
Другий рядок у цьому прикладі не очищає змінні, що виводяться, а це необхідно робити з метою безпеки. Тому для такого запису змінні повинні бути очищені заздалегідь. Загалом такий запис можна вважати неприйнятним! розділ підручника з безпечного висновку .
Відступи
Відступ повинен завжди показувати логічну структуру коду. Використовуйте табуляцію (клавіша Tab), а не прогалини – це дає більше гнучкості. Пробіли варто використовувати, коли потрібно вирівняти щось усередині рядка.
Правило: табуляція має бути використана на початку рядка для відступу, тоді як пробіли можуть бути використані в середині рядка для вирівнювання.
if ( умова ) { $foo = 'somevalue'; $foo2 = 'somevalue2'; $foo_bar = 'somevalue3'; $foo5 = 'somevalue4'; }
А так код виглядає, якщо показати невидимі символи табуляції та пробілу:
if ( умова ) { ———$foo.....= 'somevalue'; ———$foo2....= 'somevalue2'; ———$foo_bar.= 'somevalue3'; ———$foo5....= 'somevalue4'; }
Для асоціативних масивів значення повинні починатися з нового рядка. Рекомендується ставити «останню» ком при перерахуванні елементів масиву – так зручніше додавати нові елементи…
$my_array = array( ———'foo'...=> 'somevalue', ———'foo2'..=> 'somevalue2', ———'foo3'..=> 'somevalue3', ———'foo34'.=> 'somevalue3', );
Стиль фігурних дужок
Фігурні дужки повинні використовуватися для всіх блоків у стилі, як показано нижче:
if ( умова ) { action1(); action2(); } elseif ( умова2 && умова3 ) { action3(); action4(); } else { defaultaction(); }
Якщо йде довгий блок, його можна розбити на два або більше коротких блоків або функцій. Якщо такий довгий блок необхідний, додайте короткий коментар, щоб можна було зрозуміти, що саме закриває фігурна дужка. Такий підхід логічно застосовувати для блоку з 35 і більше рядків.
Слід коментувати будь-який код, який інтуїтивно не зрозумілий.
Використовуйте фігурні дужки завжди, навіть якщо вони не потрібні.
if ( умова ) { action0(); } if ( умова ) { action1(); } elseif ( умова2 ) { action2a(); action2b(); } foreach ($ items as $ item) { process_item($ item); }
Зверніть увагу, що вимога використовувати фігурні дужки завжди означає, що поодинокі конструкції в стилі одного рядка заборонені.
Можна використовувати альтернативний синтаксис для структур, що управляють : if / endif
, while / endwhile
– особливо це актуально для шаблонів, де PHP код вбудовується в HTML:
<?php if ( have_posts() ) : ?> <div class="hfeed"> <?php while ( have_posts() ) : the_post(); ?> <article id="post-<?php the_ID() ?>" class="<?php post_class() ?>"> <!-- ... --> </article> <?php endwhile; ?> </div> <?php endif; ?>
Використовуйте elseif
, а неelse if
elseif
і else if
однаково працюватимуть тільки при використанні фігурних дужок. Якщо використовуються синтаксис із двокрапкою для визначення умов потрібно використовувати elseif
, інакше ми отримаємо фатальну помилку PHP.
// Некоректний спосіб: if ($a > $b): echo "$a більше, ніж $b"; else if ( $a == $b ) : echo "Рядок вище викликає фатальну помилку."; endif; // Коректний спосіб: if ($a > $b): echo "$a більше, ніж $b"; elseif ( $a == $b ) : echo "$a і $b"; else: echo "$a не більше і не дорівнює $b"; endif;
Багаторядковий виклик функції
При розбитті параметрів функції на кілька рядків, кожен параметр повинен знаходитись на окремому рядку. Так, коментарі до параметрів зможуть мати власний рядок.
Кожен параметр повинен займати не більше одного рядка. Багаторядкові параметри потрібно переносити в змінну, а виклик функції передавати вже цю змінну.
$bar = array( 'use_this' => true, 'meta_key' => 'field_name', ); $baz = sprintf( // translators: %s: Friend's name esc_html__( 'Hello, %s!', 'yourtextdomain' ), $friend_name ); $a = foo( $bar, $baz, // translators: %s: cat sprintf( __( 'The best pet is a %s.' ), 'cat' ) );
Регулярні вирази
Використовуйте рядки в одинарних лапках для регулярних виразів, оскільки, на відміну від подвійних лапок, вони мають лише два символи, які потрібно екранувати: '
і .
Відкриття та закриття тегів PHP
При додаванні багаторядкових PHP кодів HTML блок PHP теги відкриття і закриття повинні бути розташовані на окремому рядку.
Правильно (багаторядковий):
<?php function foo() { ?> <div> <?php echo bar($baz, $bat); ?> </div> <?php }
Правильно (однорядковий):
<input name="<?php echo esc_attr( $name ); ?>" />
Неправильно:
<?php if ( $a === $b ) { ?> <some html> <?php}
Не використовуйте короткі PHP теги
Ніколи не використовуйте короткі PHP теги для публічних проектів (наприклад, плагінів), тому що на деяких серверах їхня обробка може бути відключена і ваш код не працюватиме.
Правильно:
<?php ... ?> <?php echo $var; ?>
Неправильно:
<? ... ?> <?= $var ?>
Видаляйте прогалини на кінці рядків
Видаляйте замикаючі прогалини в кінці кожного рядка.
Опускайте тег PHP, що закриває, в кінці файлу. Якщо закриваючий PHP тег все ж таки використовується, переконайтеся, що після нього немає пробілів або переносів рядків.
Так писати не слід:
<?php $foo = 'рядок';пробіл ?> Кінець файлу
Потрібно так:
<?php $foo = 'рядок'; Кінець файлу
Використання пробілу
Завжди ставте пробіли після ком, і по обидва боки логічних операторів ( ! && || ), операторів порівняння ( == ), конкатенації ( . ) і операторів присвоювання ( .= ).
x == 23 foo && bar ! foo array( 1, 2, 3 ) $baz. '-5' $term .= 'X'
Ставте пробіли на обох сторонах круглих дужок для блоків , що відкривають і закривають if, elseif, foreach, switch
.
if ( $foo ) { ... foreach ( $foo as $bar ) { ...
При визначенні функції використовуйте пробіли так:
function my_function( $param1 = 'foo', $param2 = 'bar' ) { ...
При виклику функції, так:
my_function($param1, func_param($param2));
При виконанні логічних порівнянь так:
if ( ! $foo ) { ...
При наведенні типу, так:
foreach ((array) $foo as $bar) { ... $foo = (boolean) $bar;
При зверненні до елементів масиву, додавайте пробіл навколо індексу, тільки якщо це змінна:
$x = $foo['bar']; // правильно $x = $foo['bar']; // неправильно $ x = $ foo [0]; // правильно $ x = $ foo [0]; // неправильно $ x = $ Foo [$ Bar]; // правильно $x = $foo[$bar]; // неправильно
У блоці switch
перед двокрапкою оператора case не повинно бути пропуску.
switch ($ foo) { case 'bar': // correct case 'ba' // incorrect }
Аналогічно, перед двокрапкою в оголошеннях типу, що повертається, не повинна бути пробілу.
function sum( $a, $b ): float { return $a + $b; }
Дужки всередині дужок повинні мати прогалини:
if ( $foo && ( $bar || $baz ) ) { ... my_function( ($ x - 1) * 5, $ y);
Форматування SQL конструкцій
При форматуванні SQL запиту, якщо складний запит, його можна розбити на кілька рядків і додати де потрібно відступи. Хоча більшість конструкцій пишуться в один рядок. Завжди пишіть великі такі частини SQL конструкцій, як: UPDATE
, WHERE
, FROM
, JOIN
.
Очищення, екранування запиту має бути зроблено якнайпізніше. Для захисту запиту рекомендується використовувати esc_sql() .
$var="dangerous'"; // необроблені дані, які можуть бути екрановані або екрановані $id = some_foo_number(); // дані очікуються як число, але ми не впевнені $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $var, $id ) );
%s
використовується для рядків і %d
цілих чисел. Зверніть увагу, що вони не 'в кавычках'
! $wpdb->prepare() сам екранує рядки і додає лапки, якщо треба. Перевага prepare() в тому, що не потрібно пам’ятати про ручне використання esc_sql() , а також, що рядок запиту з плейсхолдерами наочніший, ніж якщо б там використовувалися змінні обернені в esc_sql() .
Дивіться опис методу $wpdb->prepare() .
Запити бази даних
Намагайтеся не писати прямих запитів до бази даних. Якщо є підходяща функція, а їх у WP багато, яка може отримати необхідні дані – використовуйте її.
Використання функцій замість запитів допомагає зберегти майбутню сумісність коду. Крім того багато функцій працюють з кешем, а це може значно прискорити роботу коду.
Імена класів, функцій, файлів, констант, змінних
Імена функцій, змінних, хуків
Використовуйте малі літери a-z
в змінних, хуках і назвах функцій і ніколи CamelCase . Розділяйте окремі слова нижнім підкресленням _
. Не скорочуйте імена змінних без потреби; нехай код буде однозначним і самодокументованим.
function some_name( $some_variable ) { [...] }
Імена класів
Потрібно використовувати слова з Заглавных_Букв
розділені підкресленням. Будь-які скорочення (акроніми, абревіатури) повинні бути ПРОПИСНИМИ.
class Walker_Category extends Walker {[...]} class WP_HTTP {[...]}
Константи повинні бути словами в ВЕРХНЕМ_РЕГИСТРЕ
, розділені нижнім підкресленням:
define( 'DOING_AJAX', true );
Назви файлів
Повинні бути зрозумілі і повинні також містити лише малі літери, а слова повинні розділятися дефісом -
.
my-plugin-name.php
Назви файлів класів
Повинні бути засновані на імені класу з приставкою class-
, підкреслення імені класу замінені дефісом, наприклад WP_Error стає:
class-wp-error.php
Цей стандарт іменування файлів справедливий для всіх існуючих та нових файлів із класами. Однак існують файли виключення: class.wp-dependencies.php , class.wp-scripts.php , class.wp-styles.php . Ці файли мають префікс class.
, точка після слова class замість дефісу.
У ядрі, в папці wp-includes
є файли, що підключаються, в яких знаходяться функції, які зазвичай використовуються в темах (у шаблоні). Файли з такими функціями-тегами шаблону закінчуються на -template
.
- wp-includes/general-template.php
- wp-includes/comment-template.php
- wp-includes/embed-template.php
- wp-includes/author-template.php
- wp-includes/category-template.php
- wp-includes/link-template.php
- wp-includes/media-template.php
- wp-includes/nav-menu-template.php
- wp-includes/post-template.php
- wp-includes/post-thumbnail-template.php
Зрозумілі значення змінних у параметрах функцій
Булева, переважні строкові значення. Тобто. замість true/false при виклику функцій краще використовувати якусь пояснювальну значення параметра рядок.
Поганий код:
function eat( $what, $slowly = true ) { ... } eat ( 'mushrooms'); eat ( 'mushrooms', true); // Що означає true? eat('dogfood', false); // що означає false, протилежність true?
Так як PHP не підтримує іменовані аргументи, значення прапорів безглузді і щоразу, коли ми стикаємося з викликом функції, як у прикладах вище, нам потрібно дивитися документацію функції. Код може бути більш читаним за допомогою описових рядкових значень замість булевих.
Гарний код:
function eat( $what, $speed = 'slowly' ) { ... } eat ( 'mushrooms'); eat( 'mushrooms', 'slowly'); eat('dogfood', 'quickly');
Коли потрібно більше параметрів, використовуйте масив $args . Він навіть кращий!
Дуже хороший код:
function eat( $what, $args ) { ... } eat( 'noodles', array( 'speed' => 'moderate' ) );
Інтерполяція для імен динамічних хуків
Для зручності читання та виявлення, хуки зі змінними в назві повинні бути інтерполіровані (укладені у фігурні дужки {
та }
), і не повинні конкатенуватися:
Дужки потрібні, щоб PHP міг коректно аналізувати типи змінних даних в інтерполірованому рядку.
// правильно do_action( "{$new_status}_{$post->post_type}", $post->ID, $post ); // неправильно do_action( $new_status .'_'. $post->post_type, $post->ID, $post );
Там, де це можливо, динамічні значення в іменах тегів мають бути максимально короткими і точними. $user_id
набагато зрозуміліше ніж, скажімо, $this->id
.
Тернарний оператор
Тернарні оператори хороші, але в них рекомендується завжди перевіряти правдиве твердження, а не хибне. Інакше він просто вводить в оману через подвійне заперечення. Виняток – це використання ! empty()
, тому що по-іншому іноді просто складно записати.
Як потрібно перевіряти:
// (якщо умова виконується = true)? (то робимо це): (інакше це); $music_type = ('jazz' == $music)? 'cool': 'blah'; // (Якщо значення не порожнє - ! empty)? (то робимо це): (інакше це);
Як не слід писати:
// (якщо умова не виконується! = true)? (то робимо це): (інакше це); $music_type = ('jazz'! = $music)? 'blah': 'cool';
Тернарний оператор (короткий синтаксис)
Часто під час встановлення значення змінної код записується так:
$a = $b? $b: $c;
Короткий синтаксис спрощує сприйняття коду:
$a = $b?: $c;
Рекомендується використовувати короткий синтаксис, де це можливо.
Не плутайте цей оператор з оператором null-coalescing — ??
, який з’явився в PHP 7. Тут якщо $b не визначена, php виведе notice.
Умови магістра Йоди
При виконанні логічних порівнянь завжди ставте константи або літерали – зліва, а змінну – праворуч.
if ( true == $the_force ) { $ victorious = you_will ($ be); }
Якщо пропустити другий знак =
у наведеному прикладі (признатися, це відбувається навіть із найдосвідченішими з нас), то ми отримаємо помилку PHP і відразу її побачимо, тому що код не працюватиме. А от якби конструкція була зворотною – $the_force = true
то умова завжди буде виконуватися і ніякої помилки ми не побачимо, і можемо пропустити такий серйозний баг, який до того ж іноді складно відловити!
До такого «перевернутого» написання потрібно просто звикнути.
Це стосується і ==
, !=
, ===
і !==
. «Умови Йоди» для <
, >
або значно важче читати і тут їх краще не використовувати <=
.>=
Розумний код
Якщо говорити коротко, то читання коду має бути на першому плані, вона важливіша за стислості або якихось не очевидних, але зручних скорочень.
isset($var) || $var = some_function(); // або ! isset( $var ) && $var = some_function();
Так – це крутий запис, видно що зробив її досвідчений програміст. Але будь-якому іншому розробнику, а часто навіть і автору, для того, щоб розібратися в такому записі, потрібно трохи вникати і витратити зайві секунди або хвилини. Це не очевидний і не зрозумілий запис і його потрібно уникати, і краще його записати довше, але зрозуміліше:
if ( ! isset ( $ var ) ) { $var = some_function(); }
Оператор придушення помилок @
З PHP документації :
PHP підтримує один оператор керування помилками:
@
. У випадку, якщо він передує будь-якому виразу в PHP-коді, будь-які повідомлення про помилки, що генеруються цим виразом, будуть проігноровані.
У той час як цей оператор існує в ядрі, він часто використовується тому що ліньки нормально обробити змінну. Його використання настійно не рекомендується , тому що навіть PHP документація заявляє:
Увага: На сьогоднішній день оператор “@” пригнічує виведення повідомлень навіть про критичні помилки, що переривають роботу скрипта. Окрім іншого, це означає, що якщо ви використовували “@” для придушення помилок, що виникають під час роботи будь-якої функції, якщо вона недоступна або написана неправильно, подальша робота скрипта буде зупинена без будь-яких повідомлень.
Не використовуйте функцію extract()
За мотивами тикета #22400 . extract() це жахлива функція, яка сильно ускладнює налагодження коду, також сильно ускладнює читання та розуміння коду. Тому будь-коли використовуйте extract() , крім випадків коли її обійтися, тобто. ніколи!
Чому extract() така жахлива, добре пояснює Джозеф Скотт (англ.): I Don’t Like PHP’s extract() Function .
Анонімні функції
Анонімні функції корисні, коли потрібно записати коротко цілісну логічну конструкцію за допомогою PHP функції. Наприклад, виклик preg_replace_callback() можна записати так:
$caption = preg_replace_callback( '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', function ( $matches ) { return preg_replace( '/[rnt]+/', ' ', $matches[0] ); }, $caption );
Такий код покращує читання, оскільки розробнику не потрібно «стрибати» до коду функції, щоб подивитися, що там відбувається.
Там, де розробник вважає це за доцільне, анонімні функції можуть використовуватися як альтернатива створенню нових callback функцій.
Однак, анонімні функції не повинні використовуватися в хуках в ядрі WordPress як колббек функцій, тому що в цьому випадку їх неможливо видалити через remove_action() або remove_filter() . За межами ядра розробники можуть передавати анонімні функції в хуки при цьому потрібно враховувати, що може знадобиться видалити хук, в цьому випадку анонімну функцію краще не використовувати.
Простір імен (Namespaces)
Простір імен це простий спосіб інкапсуляції (відділення, ізоляції) функціональності. Однак, як було виявлено, додати простір імен в ядро WordPress це не просте завдання, яке вимагає добре продуманої архітектури.
В даний час введення просторів імен у ядро WordPress не очікується. Тому простір імен не повинен використовуватися в ядрі WordPress.
Короткий Синтаксис Масиву[]
Замість оголошення масивів з використанням синтаксису array(1, 2, 3) тепер рекомендується скорочувати до [1, 2, 3] . Це відповідає тому, як масиви оголошуються у стандартах кодування WordPress JavaScript.
Визначення змінної всередині умови
З метою нормальної читаності коду, настійно рекомендується визначати змінні на відокремленому рядку, а не всередині if умови:
Правильно:
$sticky_posts = get_option('sticky_posts'); if ( $sticky_posts ) { // ... }
Неправильно:
if ( $sticky_posts = get_option( 'sticky_posts' ) ) { // ... }
–
Посилання: