Недавно обсуждали в сообществе для разработчиков, кому сколько доставалось хорошо сделанных проектов на битриксе. Результаты неутешительные — 1–2 в среднем ответили разработчики.
Под “хорошо” подразумевается соблюдение базовых принципов разработки веб-проектов в целом и при работе с битриксом в частности. Многие [начинающие] разработчики не знают, как делать “хорошо”.
Поэтому решил подготовить краткую заметку на эту тему.
Помещайте весь php-код и шаблонизацию в компоненты.
Часто можно встретить сложный php-код прямо в индексной странице раздела или любой другой. Если редактировать такую страницу через виз. редактор, то легко можно “все сломать”, и вот основные причины:
Так быть не должно. Любой код отвечающий за бизнес-логику приложения должен быть вынесен в собственные компоненты и модули. На страницах должны располагаться только компоненты.
Такой подход позволит:
Материалы по теме
Результаты тяжелых вычислений и любых выборок из БД следует хранить в кеше.
Основные способы кеширования:
Даже файлов кеш будет работать на несколько порядков быстрее, чем повторная подготовка данных. Что уж говорить про кеш в оперативной памяти.
Битрикс умеет кешировать результаты работы компонентов в файлах и в memcache. Для Redis’a можно написать свой адаптер. PHP акселераторы для этих целей не рассматриваем - пусть занимаются своей основной задачей.
В итоге место хранения кеша определяется настройками в файле .settings.php.
// Создаем объект для работы с кешем (способ кеширования задается в .settings.php)
$obCache = Bitrix\Main\Data\Cache::createInstance();
// Время жизни кеша, в секундах
$timeout = 3600;
// Уникальный ключ для кешированных данных
// на основании входных данных
$cacheKey = md5( $arParams );
// Путь относительно /bitrix/cache/
// Т.о. можно сбросить часть, а не весь кеш проекта.
// Для этого надо удалить папку /bitrix/cache/my/subdir/
$cacheDir = "/my/subdir/";
// Если кэш валиден
if( $obCache->InitCache( $timeout, $cacheKey, $cacheDir ) )
{
// Извлекаем данные из кэша
$result = $obCache->GetVars();
}
// Если кэш невалиден
elseif( $obCache->StartDataCache() )
{
// Тяжелые вычисления
$result = hardWork();
// Сохраняем данные в кэш
$obCache->EndDataCache( $result );
}
// Работаем с данными ( $result )
Материалы по теме
Выносите сложную бизнес-логику в модули.
Модуль - это модель данных и API для доступа к этим данным. Статические методы классов модуля могут вызываться в компонентах, шаблонах, других модулях.
Модуль может состоять только из файлов с классами и не иметь интерфейса в админке или публичке. Главное, что код будет логически сгруппирован и размещен согласно логике битрикса. Модули намного легче поддерживать и расширять.
Материалы по теме
Основные требования к оформлению кода, кстати довольно простые:
Названия переменных, констант, классов и функций - должно быть осмысленным.
Следите за табуляцией во вложенных блоках.
Разделяйте логические блоки кода одной пустой строкой.
По большому счету код должен быть самодокументируемым. Этому способоствют семантичные названия переменных, методов и тд.
Комментарии размещайте над кодом.
/*
* Отправляем почтовые уведомления после регистрации через соц. сети,
* так как по умолчанию они не отправляются.
* В коде регистрации через соц. сети видно, что используется просто метод CUser->Add(...).
* */
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
"main",
"OnAfterUserAdd",
"socServdRegistrHandler"
);
или
// Отправляем почтовые уведомления после регистрации через соц. сети,
// так как по умолчанию они не отправляются.
// В коде регистрации через соц. сети видно, что используется просто метод CUser->Add(...).
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
"main",
"OnAfterUserAdd",
"socServdRegistrHandler"
);
Однако стоит добавлять комментарии, когда логика нетривиальна. Пожалуйста, не пишите “что здесь происходит”, а пишите “почему это происходит”. Вы пишите код для людей, которые будут работать с ним после вас, представьте себя на их месте и какие вопросы у них возникнут.
Пишите комментарии к классам - какие задачи в целом решает данный класс. Пишите комментарии к методам - в стили PhpDoc, описывайте суть метода, входные и выходные параметры и тд.
Следите за порядком в вашем коде с самого начала. Группируйте код. Используйте код повторно, но не копируйте его, а оформляйте его в виде отдельного метода и тд.
Один класс - один файл. Больше ничего не должно быть в файле с классом. Файл должен называться так же, как и класс:
// SomeClass.php
class SomeClass {
// some code
}
Не захламляйте файл init.php тоннами строк кода.
Подключайте там только “заголовочные” файлы:
// AddMessage2Log() будет записывать логи сюда и разбивать их по дням
define("LOG_FILENAME", $_SERVER["DOCUMENT_ROOT"] . "/_logs/bx/" . date("Y_m_d") . ".log");
// автозагрузчик для всех классов проекта с соблюдением стандарта PSR-4
spl_autoload_register(function ($class) {
$class = str_replace('\\', '/', $class);
$path = $_SERVER["DOCUMENT_ROOT"] .'/local/lib/'.$class.'.php';
if (is_readable($path)) {
require_once $path;
}
});
// константы
require_once($_SERVER["DOCUMENT_ROOT"] . "/local/php_interface/constants.php");
// общие функции
require_once($_SERVER["DOCUMENT_ROOT"] . "/local/php_interface/functions.php");
// регистрация обработчиков событий
require_once($_SERVER["DOCUMENT_ROOT"] . "/local/php_interface/events.php");
Когда классов в проекте мало — можно подключить их все вручную сразу или по мере необходимости.
Когда классов в проекте много — такой подход не годится. Если подключить все сразу — будем зря забивать оперативную память кодом, который может не пригодиться. Если подключать по мере необходимости — получается слишком заморочно повсюду прописывать инклуды.
В этом случае удобнее и оптимальнее использовать автозагрузку классов.
Рассмотрим два основных способа:
Между ними есть принципиальная разница в том, как они подключают файлы.
registerAutoLoadClasses — требует явно прописать список всех классов, которые могут быть подключены и пути к ним.
spl_autoload_register — на основании имени класса динамически вычисляет путь где хранится файл и подключает его.
Материалы по теме
Используйте папку local. Это особенно удобно при использовании системы контроля версий. Начиная с 14 версии продукта, появилась поддержка папки /local/. В ней можно размещать весь пользовательский код проекта:
Для классов проекта используйте папку /local/lib/. В остальном по аналогии.
Материалы по теме
Это общее правило для любых проектов.
Разработка на боевом сайте неизбежно связана с неработоспособностью сайта во время отладки, ошибками и иногда даже с падением сервера. Зачем рисковать своей репутацией и тратить нервы клиента - для него ошибка на сайте это конец света :) Так часто работают новички - они не знают как работать по-другому. И так работают лентяи и халтурщики - они думают, что так быстрее, но это не так.
Занимайтесь разработкой на локальной копии проекта - это очень удобно, весь проект, как на ладони. Особенно, если работать в IDE, а не в блокноте :)
Я работаю в PhpStorm, он идеально подходит для [локальной] разработки сайтов. Преимуществ очень много и трудно выделить несколько главных.
Используйте систему контроля версий (СКВ), например Git.
Много разработчиков, до сих пор, не понимают необходимость контролировать изменения в файлах с исходным кодом. А многие и вовсе не знают что такое СКВ, например Git, и как ей пользоваться.
К сожалению, СКВ решает задачу только применительно к файлам. Изменения в базе данных с помощью СКВ не отследить. На текущий момент СКВ для БД — это почти утопия.
Сейчас мы рассмотрим только основные причины для использования СКВ и настройку исключений.
Почему нужно использовать систему контроля версий:
Однако не все файлы следует держать под контролем, например:
Чтобы скрыть какие-либо файлы из под бдительного ока СКВ, существует служебный файл .gitignore, в котором содержаться правила исключения.
Предлагаю вам свой образец файла .gitignore при работе с битриксом:
# --- files ---
.DS_Store
Thumbs.db
/nbproject/
/.idea/
/*.sublime-project
/*.sublime-workspace
# --- core ---
/bitrix/*
!/bitrix/components
/bitrix/components/bitrix
!/bitrix/modules
/bitrix/modules/*
!/bitrix/templates
!/bitrix/php_interface
/bitrix/php_interface/after_connect.php
/bitrix/php_interface/after_connect_d7.php
/bitrix/php_interface/dbconn.php
!/bitrix/admin/
/bitrix/admin/*
# --- project modules ---
!/bitrix/modules/project*
# --- project admin scripts ---
# any project pages
!/bitrix/admin/project*
# 1c exchange custom script
!/bitrix/admin/1c_exchange_custom.php
# --- media files ---
/upload
/video
/files
/i
# --- log files ---
/_logs/
*.log
log.txt
# --- archives ---
*.tar*
*.zip*
*.rar*
# --- mysql files ---
/*.sql
# --- other ---
*.tmp
/_*
/test/
/t.php
test.php
robots.txt
sitemap*.xml
/*.txt
web.config
.htaccess.restore
*old*
*/*cache*/
cgi-bin/
google*.html
mywot*.html
wmail*.html
yandex*.html
php.ini
restore.php
bitrix_server_test.php
bitrixsetup.php
phpMyAdmin
pma
adminer.php
adminer.css
bx_1c_import.php
bx_1c_import_lite.php
/webstat
# allows fast hide any files or folders from under git's eyes
*_gitignore_*
Материалы по теме
Завершайте работу над проектом грамотно.
Чтобы избежать случайных ошибок и проблем:
Имея под рукой логи проще разобраться с возникшими проблемами и выяснить, когда и почему они начались.
Речь о логах функции AddMessage2Log(...) и секции exception_handling из файла .settings.php.
Чтобы в логах было удобнее ориентироваться — можно группировать их по датам. Формат даты "Y_m_d" — позволит файлам автоматически сортироваться в хронологическом порядке.
Все логи удобно держать в одном месте, например в папке /_logs/bx/.
В целях защиты следует закрыть доступ к папке с логами по http — настраивается в .htacces, и/или добавить к названию файла уникальный для проекта постфикс.
Папку для логов надо предварительно создать и убедиться, что битрикс (веб-сервер) имеет права на запись в нее.
define("LOG_FILENAME", $_SERVER["DOCUMENT_ROOT"] . "/_logs/bx/" . date("Y_m_d") . "_PROJECT_UNIQUE_POSTFIX.log");
'exception_handling' => array (
'value' => array (
'debug' => false, // disables error output to screen
// ошибки для вывода в лог
'handled_errors_types' => E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING,
'exception_errors_types' => E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT & ~E_COMPILE_WARNING,
'ignore_silence' => true,
'assertion_throws_exception' => true,
'assertion_error_type' => 256,
'log' => array (
'settings' => array (
'file' => "_logs/bx_error/" . date("Y_m_d") . "_PROJECT_UNIQUE_POSTFIX.log",
'log_size' => 1000000, // ~ 1Mb per file
),
),
),
'readonly' => true,
),
Материалы по теме
Я постарался собрать основные правила хорошего тона, о которых следует знать начинающим разработчикам, и не забывать опытным. Я уверен, что соблюдение этих правил поднимет качество, как при повседневной работе проекта, так и при его модернизации.
Надеюсь теперь сайтов на битриксе, которые будут сделаны “хорошо”, будут работать быстро и легко поддерживаться станет больше.
Присоединяйтесь к нам в Telegram чат для битрикс-разработчиков и участвуйте в обсуждениях.
по запросу
по запросу
по запросу
по запросу
Санкт-Петербург