Стандарт написания кода на PHP

За основу для данного стандарта взята статья http://www.reg.ru/coding_standards.

Оформление кода

Лесенка в 4 пробела.

Обязательна «лесенка» с отступом в 4 пробела (half-tab). При этом запрещается в редакторе изменять размер отображаемой табуляции, например выставлять отображение табуляции в 4 пробела. Код, созданный Вами при таких настройках, будет некорректно отображаться в других редакторах с другими настройками.

Величина отступа у двух соседних строчек, не должна превышать 4 пробела:

// Правильно
function get_id(
    $name   //!< Имя
) {

// Неправильно
function get_id(
                $name   //!< Имя
) {

Пробелы после запятых.

После запятых и точек с запятой (если, конечно, они не расположены в конце строки) ставятся пробелы. Перед запятой и точкой с запятой пробелы не ставятся:

$a = array (1, 2, 3);
for ($i = 0; $i < $count; $i++) {  };

Пробелы вокруг знаков операций.

Любые операторы / знаки операций (например =, ==, ⇒, <, >, &&, || и т.п.) обязательно отделяются пробелами с обоих сторон

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

$a = $b * $c + $d * $e;
$a = $b * $c  +  $d * $e;

Пробелы вокруг сложных индексных выражений.

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

$a[1];
$a[ 1 + 2 + 2 + 4 * function( $a{ $b->{c} } ) ];

Пробелы после знака комментария.

После символа начала комментария («») перед текстом самого комментария ставится пробел: <code> Комментарии начинаются С ЗАГЛАВНОЙ БУКВЫ! Вторая строка комментария </code> Исключение составляют fancy comments, где допускается сливать начальнуй символ решётки с последующими символами: <code> / MY COMMENT INIT * </code>

Пробелы после ключевых слов

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

$array = array ();
foreach ($array as $k => $item) {
    if ($item) { $array[$k] = $item * 2; }
}

<<Опять пробелы???>>

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

Не стоит полагаться на подсветку синтаксиса как на «костыль», скрывающий недостатки форматирования.

Выравнивайте комментарии точно так же, как и код.

Левый край комментариев выравнивается точно так же, как и основной код, т.е. используется принцип «лесенки».

//// тили-тили
//// трали-вали
if ($cond) {
    /*
    Это дело мне по силе,
    Откажусь теперь едва ли.
    */

}
else {
    # Это мы не проходили,
    # Это нам не задавали!
}

Ставить символы «» вначале строки, если левая граница кода находится правее, не допускается. тили-тили

// трали-вали
if ($cond) {
// ТАК ДЕЛАТЬ НЕЛЬЗЯ!!!
}

Максимальная длина строк. Разбиение длинных строк.

Строки не оставлять слишком длинными; ограничение — 80 символов в строке. При необходимости строка разбивается на несколько. Примеры допустимого разбивания конструкций:

if (
    very_long_condition_1
    && very_long_condition_2
) {
    statement;
}

if (
        ..
    &&
        ...
    ||
        ...
) {
    ...
}

Для контроля длины строк рекомендуется включить режим «статического переноса строк» после 80 символов. Большинство редакторов имеют эту возможность.

Открывающая фигурная скобка на той же строке, что и ключевое слово.

Старайтесь придерживаться компактного (K&R) стиля оформления циклов и блоков ветвления: открывающая фигурная скобка находится на той же строке, что и ключевое слово for, if, else, while и т.п. Закрывающая фигурная скобка блока, состоящего из нескольких строк, должна находиться на одной вертикали с ключевым словом начинающим конструкцию. Примеры:

if ($condition) {
    statement1;
}
else {
    statement2;
}

for ($i = 0; $i < $count; $i++) {
    statement;
}

Пробел перед открывающей фигурной скобкой.

Перед открывающей фигурной скобкой в блочных конструкциях всегда ставится пробел:

foreach ($array as $item) {
    statement;
}

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

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

foreach ($array as $item) { $item *= 2; }

Разбивайте код на абзацы, при необходимости снабжённые комментариями

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

Выравнивайте сходные элементы кода по вертикали.

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

$wm_conts_map = array (
    first_name  => 'iname',
    last_name   => 'fname',
    email       => 'email',
);

mkdir($tmpdir)          or die ("can't mkdir $tmpdir");
chmod($tmpdir, 0777)    or die ("can't change mode for $tmpdir");

Переменные и константы

Обязательно комментируйте константы.

Над константами обязательно необходимо ставить комментарий в формате doxygen

//! Режим отладки
define ("DEBUG_MODE", "1");

Не отделяйте имена переменных и функций от следующей за ними открывающей скобки.

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

# ХОРОШО
if (open_region($i)) { next CANDIDATE; }

$candidates[$i] = $incumbent[ $candidates[$i]['region'] ];
# ПЛОХО!
if (open_region ($i)){ next CANDIDATE; }

$candidates[$i] = $incumbent [ $candidates[$i]['region'] ];

Индексы ассоциативных массивов — только строки.

Индексы ассоциативных массивов должны представлять собой только текстовые значения (тип кавычек — не важен)

# ХОРОШО
$array['type_id'] = 1;
$array["type_id"] = 2;

# ПЛОХО!
$array[type_id] = 3;

Осмысленные названия идентификаторов.

Выбирайте осмысленные названия для идентификаторов (переменных, констант, функций). Исключение составляют итераторы циклов, где допускаются короткие идентификаторы: $i, $n и т.п. При этом не допускается калька с русского языка («$polzovatel», «$sajt» и т.п.). Если вы не можете вспомнить, что это имя значит — у вас проблемы.

Строчные буквы для названий переменных и функций.

Названия всех переменных и функций должны состоять только из строчных букв, цифр и знаков подчёркивания: «get_domain_name» и т.п.

Хотя короткие идентификаторы типа «$gotit» возможно и неплохи, используйте знак подчеркивания для разделения слов. В общем случае «$var_names_like_this» прочесть легче чем «$VarNamesLikeThis».

Заглавные буквы для констант.

Константы именуются только с использованием заглавных букв:

define ("DEBUG", 0);

Именуйте массивы во множественном числе, а скаляры в единственном.

Массивы рекомендуется называть во множественном числе, например $users, $objects, а скаляры — в единственном: $user, $object.

Функции

Одна функция выполняет одну задачу.

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

Имена функций должны содержать глагол.

Наименования функций должны включать глагол, например «get_domain_name», или «chash_my_program».

Имена, заданные без учёта этого принципа, вроде «flat_components», могут быть истолкованны совершенно по разному, например как «get_flat_components», «set_flat_components», «update_flat_components», «remove_flat_components» или «add_flat_components»

Используйте устоявшиеся пары антонимов в именах функций

В книге Стива Макконелла «Совершенный код» приводятся устоявшиеся пары антонимов, рекомендуемые для использования в именах функций/методов, а именно:

  • add / remove,
  • begin / end,
  • create / destroy,
  • first / last,
  • increment / decrement,
  • insert / delete,
  • lock / unlock,
  • min / max,
  • next / prev,
  • old / new,
  • open / close,
  • show / hide,
  • source / target,
  • start / stop,
  • up / down.

Использование «несогласованных» пар глаголов вроде add / delete или insert / destroy вводит в заблуждение и усложняет анализ кода.

Имена private-функций начинаются с подчёркивания.

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

Отступы и комментарии для функций. Документирование входных параметров функций

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

/**
     Получить имя домена по его id (краткое однострочное описание)

    Прочее описание

*/
function get_domain_name(
    $id //!< id домена
) {
    ...
}

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

Не более 3-х параметров у функций.

Функция может принимать не более 2-х, максимум 3-х аргументов. При большем количестве аргументов либо проводится рефакторинг с целью уменьшения количества входных параметров, либо используются именованные параметры. Именованные параметры обязательно документируются

Документирование выходных параметров функций.

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

Библиотеки.

Комментарий вначале библиотеки.

Вначале библиотеки обязателен комментарий, описывающий её назначение.

/**  Краткое описание библиотеки
    \author Пупкин Василий

    Подробное описание

*/

Комментарий вначале класса.

Вначале класса обязателен комментарий, описывающий её назначение.

/**
     Краткое описание класса
*/
class myclass {
 ...
}

Наименование библиотек в стиле mylib.lib.php

Файлы библиотек следует называть в стиле mylib.lib.php. В то время как исполняемые файлы («скрипты»), следует именовать маленькими буквами, с применением знака подчёркивания: clear_cache.php.

Динамическая подгрузка тяжёлых опциональных модулей.

Если требуется использовать «тяжёлую» библиотеку (скажем, отъедающую 5 Мб памяти и более), при этом, необходимость в этой библиотеке возникает лишь изредка, при определённых условиях — лучше её динамически, когда в нём возникает необходимость:

define ("", $_SERVER['DOCUMENT_ROOT']);
$include_file = DOCUMENT_ROOT."/libs/mylib.lib.php";
if ($condition) {
    if (file_exists($include_file)) {
        include_once($include_file);
    }
}

Подгрузка библиотек только по абсолютному пути.

Для указания пути к библиотеки обязательно использовать полный путь в файловой системе. Его можно получить из переменной окружения $_SERVER[’DOCUMENT_ROOT’], либо указав его в константе.

define ("", $_SERVER['DOCUMENT_ROOT']);
$include_file = DOCUMENT_ROOT."/libs/mylib.lib.php";
if ($condition) {
    if (file_exists($include_file)) {
        include_once($include_file);
    }
}

SQL, базы данных

Осмысленные названия полей и таблиц.

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

Имена таблиц и полей в обратных апострофах.

Имена таблиц, полей и их псевдонимов обязательно заключаются в обратные апострофы (символ ‘).

Форматирование SQL-запросов

Запросы длиной более 50 символов (примерно) рекомендуется разбивать на несколько строк, подгоняя текст по горизонтали. Например так:

    SELECT `fields`
      FROM `tables` `t`
     WHERE conditions
       AND more conditions
     GROUP BY `fields`
     ORDER BY `fields`
     LIMIT limits

или так:

    SELECT
        `fields`
    FROM
        `tables` `t`
    WHERE
        conditions
    AND
        more conditions
    GROUP BY
        `fields`
    ORDER BY
        `fields`
    LIMIT
        limits

Ключевые слова — заглавными буквами.

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

Названия полей и таблиц — строчными буквами.

При именовании таблиц и полей не допускается использование заглавных букв. Допускаются только строчные латинские буквы, цифры и знак подчёркивания. Пример: «name_of_the_table».

Названия таблиц — во множественном числе.

Таблицы следует именовать по-английски, во множественном числе. Например: «domains», «users».

Первичный ключ с именем «id».

В каждой таблице (за исключением таблиц, где необходимы составные ключи, например таблиц для обеспечения связей многие-ко-многим) обязательно должно быть поле с именем «id» и типом INT, для которого должен быть создан первичный ключ:

id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY

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

Ссылочные поля — с именем <tablename>_id

Все поля, использующиеся для связи с другими таблицами по их первичному ключу, именуются как »<tablename>_id», где »<tablename>» — имя таблицы в единственном числе. Примеры наименований: domain_id, user_id.

Комментарии

Кодировка комментариев на русском языке должна быть ЕДИНОЙ на протяжении всего проекта (в зависимости от принятых для этого проекта договорённостей).

Комментирование функций.

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

/**
     Краткое описание функции

    Полное описание функции
*/
function my_func(
    $xml,       //!< Описание аргумента 1
    $xsl_file   //!< Описание аргумента 2
) {
    ....
}

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

Комментирование циклов.

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

// Описание рабты цикла
foreach () {
    ...
}

Комментирование условий.

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

// Описание условия
if () {
    ...
}

Шаблоны.

Экранирование поставляемых данных во избежание XSS-атак При подстановке в шаблон данных, передаваемых пользователем (например, переданных ранее через форму на сайте), эти данные обязательно экранируются с помощью фильтра html (за исключением ОСОБЫХ случаев):

<?= htmlspecialchars($form_data);?>

Пробелы

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

Лесенка.

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

    {if $ru}
        Русский текст
    {else}
        Английский текст
    {/if}

Проверки на непустоту списков.

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

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

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

HTML-код

Не использовать спецсимволы, записанные в национальной кодировке.

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

Для каждого чекбокса должен быть label.

Для каждого элемента <input type=«checkbox» …> должен быть предусмотрен элемент <label>, для того, чтобы чекбокс срабатывал также по клику по метке:

    <label><input type="checkbox" name="test" value="1">Тестовая метка</label>

Высота textarea

Textarea в форме минимум на 10 строк высоты (очень неудобно постоянно делают 4-6 строк)

Textarea в форме минимум на 95% её ширины.

Возможно следует задать минимум в см.

Использование таблицы для формы

Использование в форме тегов th для заголовков полей и тегов td содержащих поля. При этом чекбоксы с их лэйблами хранятся в тэгах td аналогично input.

<form>
    <table>
        <tr>
            <th>Field1:</th>
            <td><input ...></td>
        </tr>
    </table>
</form>

JavaScript

Всегда объявляйте переменные.

Всегда объявляйте переменные в JavaScript, даже если синтаксис языка допускает использование переменной без её объявления. Не позволяйте себе «расслабиться»!

    var variable = 'Value';
    alert( variable );

Добавить комментарий