Стандарты и стили кодинга

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

Формат файлов

Все файлы должны:
- сохраняться как ASCII текст;
- иметь кодировку UTF-8;
- иметь формат Unix:
Все строки должны заканчиваться переводом строки (LF). Перевод строки должен быть представлен ординалом 10, октальным числом 012 и hex 0A. Не используйте возврат каретки (CR) как в компьютерах Macintosh или возврат каретки/перевод строки (CRLF) как в Windows.

Стандарты кодинга

Орфография

Орфография классов, функций, переменных и констант должна ориентироваться на правила British English (en_GB). Правда, возможны и некоторые исключения, например использование некоторых имён (к примеру $color), которые сопоставимы с PHP API.

Код должен быть E_STRICT-совместим

Начиная с версии 1.6, весь новый код, который предлагается для включения в Joomla, должен быть E_STRICT-совместим. Это означает, что он не должен выдавать никаких предупреждений или ошибок, когда уровень отчёта ошибок PHP (error reporting level) установлен в E_ALL | E_STRICT.

Отступы и длина строки

Используйте табуляцию для отступов, а не пробелы. Также убедитесь, что одно нажатие на табуляцию (tab-stop) установлено по длине в 4 пробела. Не существует лимита по длине строки – это остаётся на Ваше усмотрение. Придерживайтесь принципов читабельности кода.

Управляющие конструкции

Включают в себя if, for, while, switch, и т.п. Вот пример конструкции if, так как эта конструкция является наиболее сложной по структуре:

if ((condition1) || (condition2)) {
action1();
} else if ((condition3) && (condition4)) {
action2();
} else
{
// используйте «one true brace» стиль
// когда блок длиннее одной строки
defaultAction();
anotherAction();
}
 
// необязательное форматирование, для улучшения читабельности
if ((condition1) || (condition2)) {
action1();
}
else if ((condition3) && (condition4)) {
action2();
}
else {
defaultAction();
anotherAction();
}

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

В шаблонах необходимо использовать альтернативный вариант:

if ((condition1) OR (condition2)) :
action1();
elseif ((condition3) AND (condition4)) :
action2();
else :
defaultAction();
anotherAction();
endif;
 
foreach ($array as $element) :
echo $element;
endforeach;

В логических операторах условных конструкций должны использоваться слова из заглавных букв (AND, OR и т.п.), а не программные записи типа &&, ||, и т.п.

За исключением конструкции case, желательно всегда использовать изогнутые фигурные скобки, несмотря на то, что технически они не обязательны. Используя их, мы значительно улучшаем читабельность и уменьшаем возможность логических ошибок при добавлении новых строк.
Для конструкции switch:

switch (condition)
{
case 1:
doAction1();
break;
 
case 2:
doAction2();
break;
 
default:
doDefaultAction();
break;
}

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

Вызов функций

При вызове функции не используйте пробел: между именем функции и открывающей скобкой, между открывающей скобкой и первым аргументом, между закрывающей скобкой и последним аргументом, и между точкой с запятой. Используйте пробел после запятой между аргументами (если они присутствуют).
А вот и пример:

$var = foo($bar, $baz, $quux);

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

$short 		= foo($bar);
$long_variable = foo($baz);

Определение функции

При объявлении классов и функций придерживайтесь так называемого стиля «one true brace» if (cond) { }:

function fooFunction($arg1, $arg2 = '')
{
if (condition) {
statement;
}
return $val;
}
 
class fooClass
{
function fooMethod($arg1)
{
if ($arg) {
$result = true;
} else {
$result = false;
}
return $result;
}
}

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

function connect(&$dsn, $persistent = false)
{
if (is_array($dsn)) {
$dsninfo = &$dsn;
} else {
$dsninfo = DB::parseDSN($dsn);
}
 
if (!$dsninfo OR !$dsninfo['phptype']) {
return $this->raiseError();
}
 
return true;
}

Комментарии

Внутренняя документация классов должна придерживаться соглашения PHPDoc: http://www.phpdoc.org/

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

Допускаются и комментарии в стиле языка C (/* */), и стандартные C++ комментарии (//). Использование Perl/shell стиля (#) запрещено.

Подключение кода

Везде, где Вы безусловно подключаете файлы классов, используйте require_once. При условном подключении (например, в фэктори методах) используйте include_once. Так Вы будете уверены, что файл класса включён единожды. Они разделяют один и тот же список файлов, так что Вы можете не волноваться при их смешенном использовании – файл, подключённый через require_once не будет включён снова через include_once.

Тэги PHP кода

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

SQL запросы

Ключевые слова SQL должны быть написаны заглавными буквами, в то время как остальные идентификаторы должны быть написаны маленькими буквами. Не надо использовать возврат каретки (CR) так как JDatabase::getQuery сам позаботиться о форматировании. Впрочем, желательно использовать отступы для улучшения читабельности.
Запросы должны быть заключены в одинарные кавычки (так как такие текстовые блоки быстрее обрабатываются PHP).

Используйте метод nameQuote() для формирования названных элементов в запросе. Используйте метод Quote() для формирования значений.
nameQuote() – устанавливает правильность разделителей в имени поля, а Quote() – устанавливает правильность разделителей в передаваемом значении.
В названиях таблиц используйте префикс #_ а не jos_.
Перед переменными цело-числовыми (integer) или с плавающей точкой (float) используйте (int), (float) или (double) соответственно.

$state = 1;
$name = 'bill';
$db = &JFactory::getDBO();
$query = 'SELECT COUNT( c.id ) AS num_articles, u.id, u.username'.
' FROM nameQuote(‘#__content’) AS c'.
' LEFT JOIN nameQuote(‘#__users’) AS u ON u.id = c.created_by'.
' WHERE c.state = '.(int) $state
' AND u.id IS NOT NULL'.
' AND u.username <> '.$db->Quote( $name ).
' GROUP BY u.id'.
' HAVING COUNT( c.id ) > 0';
$db->setQuery();
if ($debug) {
echo $db->getQuery();
}
$stats = $db->loadObjectList();

Док блоки (DocBlocks)

Весь исходный код дистрибутива Joomla должен содержать следующий блок комментирования в заголовке:

/**
* @version $Id$
* @package Joomla
* @copyright Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
* @license GNU/GPL, see LICENSE.php
*/

Для файлов класса @package в заголовке не требуется.
Классы, функции, константы, свойства класса и методы класса также должны быть снабжены блоком:

/**
* Короткое описание класса
*
* Длинное описание (необязательно)
*
* @package PackageName
* @subpackage SubPackageName
* @link http://pear.php.net/package/PackageName
* @see NetOther, Net_Sample::Net_Sample()
* @since Class available since Release 1.2.0
* @deprecated Class deprecated in Release 2.0.0
*/

class JFooBar
{
/**
* @var int $id Primary key
*/

public $id = null;
}

Используйте следующие названия пакетов (package):
· Joomla.Administrator – все файлы, которые относятся к админке или бэкэнд приложениям
· Joomla.Installation – все файлы, которые относятся к приложению инсталляции
· Joomla.Plugin – все файлы плагина
· Joomla.Site – все файлы, которые относятся к фронтенду
· Joomla.XML-RPC – все файлы, которые относятся к XML-RPC приложению сервера

Название суб-пакета (sub-package) варьируется от типа расширения:
· Components – папка компонентов, например com_content
· Modules – папка модулей, например mod_latest_news
· Plugins – папка.элемент, например content.pagebreak
· Templates – папка шаблонов, например rhuk_milkyway
· Framework – ничего не пишем для файлов верхнего уровня (таких как factory.php). Для папки первого уровня или для папки второго уровня пишем, например utilities для joomla/utitilies/date.php, html.html для joomla/html/html/email.php

Обратите внимание на то, что код, который предназначен для ядра Joomla, не должен содержать тега @author. Философия Joomla такова, что код написан «всеми вместе», и отдельная персона не может быть владельцем какого-то из кусочков кода.

В файлах, которые подключаются из сторонних источников, Док Блоки должны оставаться неизменёнными.

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

/** $Id$ */ defined('_JEXEC') or die('Restricted access');

Соглашения названий

Классы

Имена классов должны иметь описательный характер. По возможности избегайте использования аббревиатур. Имена классов всегда должны начинаться с большой буквы и должны быть написаны в стиле CamelCase, даже несмотря на использование традиционных акронимов, состоящих только из заглавных букв (таких как XML, HTML). Исключение составляют классы фреймворка Joomla, которые должны начинаться с заглавной буквы ‘J’, и следующая буква тоже должна быть заглавной:
JHtmlHelper
JXmlParser
JModel

Разработчикам сторонних расширений желательно называть свои функции используя уникальный префикс.

Функции и методы

Функции и методы должны называться в стиле «studly caps» (известным так же как «bumpy case» или «camel caps»). Первая буква имени маленькая, а каждая буква начинающая новое «слово» должна быть заглавной. Имя функции фреймворка Joomla должно начинаться с маленькой ‘j’. Некоторые примеры:

connect();
getData();
buildSomeWidget();
jImport();
jDoSomething();

Имена закрытых членов класса должны предваряться нижним подчёркиванием. Свойства должны писаться в стиле нижнего подчёркивания (слова должны быть разделены нижним подчёркиванием) и маленькими буквами. Например:

class JFooBar
{
// более ранний формат и Joomla 1.5
var $_status = null;
 
function _sort()
{
}
 
// формат Joomla 1.6
private $_status = null;
 
protected $field_name = null;
 
protected function _sort()
{
}
}

Константы

Константы всегда должны писаться заглавными буквами, а слова разделяться нижним подчёркиванием. Предваряйте имена констант именем класса/пакета в котором они используются. Например, константы используемые классом JError все начинаются с «JERROR_».

Глобальные переменные

Если требуется определение глобальных переменных, их имя должно начинаться с нижнего подчёркивания. Далее идёт имя класса/пакета написанное заглавными буквами и ещё одно нижнее подчёркивание. Например, класс JError использует глобальную переменную $_JERROR_LEVELS.

Начиная с PHP5, Вы можете использовать статические свойства классов и константы вместо глобальных переменных:

class JWhatever
{
public static $instance = null;
const SUCCESS = 1;
const FAILURE = 0;
// Методы...
}

Регулярные переменные и переменны класса

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

Ссылки (References)

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

$ref1 = &$this->_sql;
$db = &JFactory::getDBO();

Языковые ключи

Все языковые ключи должны отображать тип строки, которую они представляют. Исключения составляют такие общие слова как: «Yes», «No», «Show», «Hide». Всегда помните, что если два расширения используют один и тот же языковой ключ, будет отображаться тот, который был загружен последним. В ключе используйте название расширения, к которому он относится. Например:

echo JText::_('Weblink Link');
echo JText::_('Weblink Title');
echo JText::_('Weblink Description');
 
echo JText::_('Exception An error occurred while saving');

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

// A table column title
<th><?php echo JText::_('Weblink Column Title');?></th>
<th><?php echo JText::_('Weblink Column Link');?></th>
 
// In the form
echo JText::_('Weblink Title');?><input name="title" />
echo JText::_('Weblink Link');?><input name="link" />

Текст Toolbar и Linkbar должен предваряться Toolbar и Linkbar соответственно.

Языковые ключи долины быть написаны как можно более натурально, и по возможности используя пробелы, а не нижние подчёркивания. Слишком длинные фразы желательно сокращать. Например, tooltips для поля редактирования могут быть написаны вот так:

echo JText::_('Weblink Title');
<input name="title" title="<span style="margin: 0px; padding: 0px; border-width: 0px; font-weight: bold; font-style: inherit; font-size: 12px; font-family: inherit; vertical-align: baseline; color: #000000;"><?php <span style="margin: 0px; padding: 0px; border-width: 0px; font-weight: inherit; font-style: inherit; font-size: 12px; font-family: inherit; vertical-align: baseline; color: #b1b100;">echo JText::_('Weblink Title Desc');?>" />

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

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

// не разрешено
echo JText::_('Deleted ').$n.JText::_(' items');
 
// разрешено
echo JText::sprintf('Message Deleted NUMBER items', $n);

В языковом файле это будет выглядеть так:
MESSAGE DELETED NUMBER ITEMS=Deleted %d Item(s)

Если же во фразе используется более одного динамического слова, то необходимо использовать printf маркеры для сортировки замены, так как другие языки могут использовать различные направления перевода. Это достигается через %[number]$[printf_type]:
Слева направо:
PAGE X OF Y=Page %1$d of %2$d
Справа налево:
PAGE X OF Y=%2$d of %1$d egaP

Контроллеры (Controllers)

Для компонентов с одним контроллером, название должно быть [Name]Controller.

/**
* Content Controller
* @package Joomla
*/

class ContentController extends JController
{
// Методы...
}

Именем файла, как правило, будет controller.php и расположен этот файл в папке компонента.
com_content
/ controller.php

Если используется несколько контроллеров, то название должно быть [Component]Controller[Name].

/**
* Banner Client Controller
* @package Joomla
*/

class BannerControllerClient extends JController
{
// Методы...
}

Файлы располагаются в папке /controllers/ внутри папки компонента. Имя файла должно отображать имя контроллера:
com_banner
/controllers/
/ banner.php
/ client.php

Модели (Models)

Придерживаемся в названии соглашения [Component]Model[Name].

/**
* Banner Client Model
* @package Joomla
*/

class BannerModelClient extends JModel
{
// Methods
}

Файлы располагаются в папке /models/ внутри папки компонента. Имя файла должно отображать имя модели.
com_banner
/models/
/ banner.php
/ client.php

Представления (Views)

Придерживаемся в названии соглашения [Component]View[Name].

/**
* Contact Category View
* @package Joomla
*/

class ContactViewCategory extends JView
{
// Методы...
}

Файлы располагаются в папке /view/ внутри папки компонента. Названия подпапок должны отображать имя Представления.
com_contact
/views/
/view name 1/
/ view.html.php
/view name 2/
/ view.html.php

Компоненты с множественным представлением могут иметь необязательный «мастер» класс представления, который расширяют специализированные представления. Располагается он в папке компонента, и обычно называется view.php. В названии придерживаемся соглашения [Component]View.
com_content
/views/
/archive/
/ view.html.php
/article/
/ view.php
view.php

/**
* Content View
* @package Joomla
*/

class ContentView extends JView
{
// Helper Методы...
}

views/archive/view.html.php

/**
* Content Archive View
* @package Joomla
*/

class ContactViewArchive extends ContentView
{
// Методы...
}

Плагины (Plugins)

Придерживаемся в названии соглашения [Folder]Plugin[Element].

class ContentPluginPagebreak extends JPlugin
{
// Методы...
}

Шаблоны (Layouts)

Компоненты могут поддерживать различные шаблоны, которые выводят данные, поступающие от Представления и его Моделей. Шаблон обычно содержит в себе HTML разметку и немного PHP кода для отображения только логики: никаких функций, никаких классов. Шаблон состоит как минимум из одного .php файла и .xml файла (названия этих файлов должны совпадать), которые расположены в папке /tmpl/ Представления. Оба они отражают внутреннее имя Шаблона. Стандартный Шаблон называетсяdefault.
com_content
/views/
/article/
/tmpl/
/ default.php
/ default.xml
/ form.php
/ form.xml
/ pagebreak.php
/ pagebreak.xml

Шаблон может использовать дополнительные .php файлы для достижения контроля над выводимым содержимым и данными.

http://docs.joomla.org/Coding_style_and_standard



Стандарты и стили кодинга - Генератор расширений Joomla и многое другое на нашем сайте посвященном работе расширений, компонентов, модулей, плагинов для линейки Joomla. Отправляйте ссылку на страницу своим друзьям и в социальные сети воспользовавшись графическими иконками выше.

Блог

Календарь приёма объявлений

Небольшой пример из повседневной практики. Организация меняет реквизиты, и они вступят в силу через  пару недель. На сайте идет приём объявлений и объявления принимаются на несколько месяцев в...

Дырка в com_content

Сегодня у товарища, сайт которого находится на старой  Joomla 1.0.3, была сильная нагрузка на сервере, просматривая логи обнаружил не вежливый запрос такого порядка: http://сайт/index2...

Лечим вирус на сайте

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

Troj/JSRedir-MH

Снова грянул гром зарежения сайтов новым вирусом  Troj/JSRedir-MH.  И так в коротко по вирусу Troj/JSRedir-MH. Вирус или троян куда интереснее чем свои предшествиники, тепер...

Доработка расширения для рассылки Send Email JK

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

Привет Ie 10 регулярка

И вот и мне пришлось столкнулся с проблемами перехода на win 8 в придачу с ie 10, некоторых постоянных пользователей моих сайтов. На многих сайтах  имеющих раздел по приёму объявлений, использ...

Kunena заменяем ссылку на профиль пользователя

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

Работает на Kunena - зачем на каждой странице?

  Все у кого стоит форум kunena мешает надпись с двумя ссылкам внизу форума "Работает на Kunena". Сея надпись висит на каждой странице форма, а также страница разработчиков содержит множество вн...

Kunena избавимся от лишних quote

Для тех кто действительно делает сайт для людей, моя следующая заметка. Расскажу вам, как избавиться от лишних quote в постах на форуме kunena. У меня несколько тематических сайтов с нормальной посеща...

Kunena решаем проблему с пропажей аватаров

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

Джомлавикам

Обработка параметров расширений joomla

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

Кunena крамсаем шаблон

1. В папке \components\com_kunena\template\ваш_шаблон\ находим файл template.xml и вставляем в него такой кусок (чтобы была возможность выбора показывать это поле или нет): <param name="l...

Подключить свои классы и методы в Joomla?

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

3 новых полезных класса в Joomla 2.5

В платформе Joomla 11.3 разработчики добавлил несколько полезных новых классов для разработчиков. Рассмотрю некоторый из них - JGrid (для построения HTML таблиц), JWebClient (для получения информац...

Репозиторий файлов на Joomla средствами Apache

Создадим две вложенные директории /files/files в корне сайта. Если вы пожелаете использовать другие имена директорий, то вам необходимо будет внести соответствующие правки в дальнейшем. ...