Мой вариант диагностической функции для битрикс-разработчиков
Когда только начинал работать - выводил просто var_dump() и все. Далее узнал о функции print_r() - стал чередовать эти 2 функции.
Потом, когда начались работы по доработкам на боевых сайтах - потребовалась проверка того, чтобы диагностические сообщения были доступны только админам - конструкция обросла еще и проверкой того, что пользователь админ (с периодической заменой проверки на админа, на проверку на конкретный ID-пользователя).
И вот, уже больше года пользуюсь своей собственной функцией:
function pre($var,$stop=false,$inconsole = false, $UID = false){ $bt = debug_backtrace(); $bt = $bt[0]; $dRoot = $_SERVER["DOCUMENT_ROOT"]; $dRoot = str_replace("/", "\\", $dRoot); $bt["file"] = str_replace($dRoot, "", $bt["file"]); $dRoot = str_replace("\\", "/", $dRoot); $bt["file"] = str_replace($dRoot, "", $bt["file"]); if ($GLOBALS['USER']->IsAdmin()){ if($UID && intval($UID)!==$GLOBALS['USER']->GetID()) return; if($inconsole){ echo "<script>console.log('File: ".$bt['file']." [".$bt['line']."]');console.log(".json_encode($var).");</script>"; } else{ echo '<div style="padding:3px 5px; background:#99CCFF; font-weight:bold;">File: '.$bt["file"].' ['.$bt["line"].']</div>'; echo '<pre>'; ((is_array($var) || is_object($var)) ? print_r($var) : var_dump($var)); echo '</pre>'; } if($stop) exit(0); } }
$var - переменная для анализа; $stop - флаг, который при необходимости останавливает выполненеи дальнейших операций после данной функции; $inconsole - при истинном значении вывод осуществляется не в окно пользователю, а в консоль браузера; $UID - используется для вывода диагностического сообщения только пользователю с заданным ID.
Функция эта уже давным давно не актуальна, давно уже использую для этих целей полноценный Debug-класс. Вот модифицированная данная функция:
Дебаг-функция в пределах дебаг-класса
Подключаем класс в init.php:
CModule::AddAutoloadClasses('', ['\Pai\CDev' => '/local/php_interface/include/classes/CDev.php',]);
И по указанному пути размещаем сам файл с классом "CDev":
namespace Pai; use ReflectionClass; class CDev { ... /** * Улучшенная debug-функция с поддержкой eval() * * @param mixed $var Переменная для отладки * @param array $options Дополнительные опции: * - 'depth' => int Глубина вложенности (по умолчанию 3) * - 'showHidden' => bool Показывать скрытые свойства (по умолчанию false) * - 'stop' => bool Остановить выполнение после вывода (по умолчанию false) * - 'toConsole' => bool Выводить в консоль браузера (по умолчанию false) * - 'onlyForUser' => int|false Показывать только для пользователя с указанным ID (по * умолчанию false - для всех) * - 'rawOutput' => bool Выводить как raw HTML (по умолчанию false, автоматически * определяется) */ public static function debug($var, array $options = []) { // Настройки по умолчанию $defaults = [ 'depth' => 3, 'showHidden' => false, 'stop' => false, 'toConsole' => false, 'onlyForUser' => false, 'rawOutput' => null, // Автоматическое определение ]; $options = array_merge($defaults, $options); // Автоматическое определение rawOutput if ($options['rawOutput'] === null) { // Определяем контекст выполнения $isHttp = isset($_SERVER['HTTP_HOST']) || isset($_SERVER['REQUEST_URI']); $isCli = php_sapi_name() === 'cli' || defined('STDIN'); $isEval = false; // Проверяем, выполняется ли код через eval() $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); foreach ($backtrace as $trace) { if (isset($trace['function']) && $trace['function'] === 'eval') { $isEval = true; break; } } // Логика определения формата вывода $options['rawOutput'] = ($isHttp && !$isCli && !$isEval); } if ($options['toJson']) { header('Content-Type: application/json'); echo json_encode(['debug' => $var, 'trace' => $backtrace], JSON_PRETTY_PRINT); exit; } // Проверка прав доступа global $USER; if ($options['onlyForUser'] !== false && (!$USER->IsAuthorized() || $USER->GetID() != $options['onlyForUser'])) { return; } // Получаем информацию о месте вызова $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]; $file = str_replace($_SERVER['DOCUMENT_ROOT'], '', $backtrace['file']); $line = $backtrace['line']; // Формируем заголовок с информацией о месте вызова $header = sprintf( 'Debug: %s [Line: %d] [Type: %s]', $file, $line, is_object($var) ? get_class($var) : gettype($var) ); // Если вывод в консоль браузера if ($options['toConsole']) { $output = [ 'header' => $header, 'data' => $var, 'backtrace' => $backtrace ]; echo ''; if ($options['stop']) { die(); } return; } // Подготовка вывода ob_start(); if ($options['rawOutput']) { // Вывод как HTML echo ''; echo ''; // JavaScript для переключения видимости echo ''; } else { // Вывод как текст (для eval и CLI) echo "=== DEBUG ===\n"; echo $header . "\n"; self::printDebugVariable($var, $options['depth'], $options['showHidden'], 0, false); echo "\n=============\n"; } $output = ob_get_clean(); // Для AJAX-запросов устанавливаем правильный Content-Type if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { header('Content-Type: ' . ($options['rawOutput'] ? 'text/html' : 'text/plain') . '; charset=utf-8'); } echo $output; if ($options['stop']) { die(); } } /** * Рекурсивная функция для вывода переменной */ protected static function printDebugVariable($var, $depth = 3, $showHidden = false, $level = 0, $isHtml = true) { if ($depth <= 0) { if ($isHtml) { echo '[max depth reached]'; } else { echo '[max depth reached]'; } return; } $type = gettype($var); if ($isHtml) { // HTML-вывод switch ($type) { case 'string': echo '"' . htmlspecialchars($var) . '"'; echo ' (string, length: ' . strlen($var) . ')'; break; case 'integer': echo '' . $var . ''; echo ' (integer)'; break; case 'double': echo '' . $var . ''; echo ' (float)'; break; case 'boolean': echo '' . ($var ? 'true' : 'false') . ''; echo ' (boolean)'; break; case 'NULL': echo 'null'; echo ' (null)'; break; case 'array': echo 'array (count: ' . count($var) . ')'; if (!empty($var)) { $id = uniqid('array_'); echo ' ▶'; echo ' '; } break; case 'object': $class = get_class($var); echo 'object(' . $class . ')'; $id = uniqid('object_'); echo ' ▶'; echo ' '; break; default: echo '' . print_r($var, true) . ''; echo ' (' . $type . ')'; } } else { // Текстовый вывод (для eval и CLI) switch ($type) { case 'string': echo '"' . $var . '" (string, length: ' . strlen($var) . ')'; break; case 'integer': echo $var . ' (integer)'; break; case 'double': echo $var . ' (float)'; break; case 'boolean': echo ($var ? 'true' : 'false') . ' (boolean)'; break; case 'NULL': echo 'null (null)'; break; case 'array': echo 'array (count: ' . count($var) . ')'; if (!empty($var)) { echo "\n"; foreach ($var as $key => $value) { echo str_repeat(' ', $level + 1) . '[' . $key . '] => '; self::printDebugVariable($value, $depth - 1, $showHidden, $level + 1, $isHtml); echo "\n"; } } break; case 'object': $class = get_class($var); echo 'object(' . $class . ')'; echo "\n"; // Выводим свойства объекта $reflection = new ReflectionClass($var); $properties = $reflection->getProperties(); foreach ($properties as $property) { $property->setAccessible(true); if (!$showHidden && $property->isPrivate()) { continue; } echo str_repeat(' ', $level + 1); echo $property->isPrivate() ? 'private ' : ($property->isProtected() ? 'protected ' : 'public '); echo '$' . $property->getName() . ' = '; self::printDebugVariable( $property->getValue($var), $depth - 1, $showHidden, $level + 1, $isHtml ); echo "\n"; } break; default: echo print_r($var, true) . ' (' . $type . ')'; } } } ... }' . $header . ''; echo ''; self::printDebugVariable($var, $options['depth'], $options['showHidden'], 0, true); echo '
Обращение к функции идет в таком виде:
// В обычном веб-контексте (HTML) Pai\CDev::debug($variable); // В eval() или CLI (текстовый вывод) Pai\CDev::debug($variable, ['rawOutput' => false]); // С максимальной глубиной 5 Pai\CDev::debug($variable, ['depth' => 5]); // С выводом скрытых свойств Pai\CDev::debug($variable, ['showHidden' => true]);
Разработка сайта
Подайте заявку на разработку сайта на базе готового решения от компании 1С-Битрикс или одного из партнеров компании. Максимально подробно опишите, чему будет посвящен сайт, если это интернет-магазин - что он будет продавать, нужна ли мультиязычность, будут ли разные типы цен (розница, опт, крупный опт), будет ли интеграция с 1С, будет ли выгрузка товаров на различные торговые площадки...
Сопровождение сайта
Вы можете подать заявку на сопровождение вашего сайта на базе 1С-Битрикс. Сопровождение включает в себя: проверка актуальности обновлений сайта, проверка актуальности резервной копии, консультации по сайту. Опишите в заявке, какие еще объемы планируются на сопровождении и на какой срок вы планируете заключить договор на сопровождение - мы подберем подходящий вам бюджет на сопровождение
Работы по сайту
Вы можете подать заявку на выполнение определенного объема работ по сайту. Опишите в заявке объем работ. Это может быть разработка какого-то нового функционала, доработки по имеющемуся функционалу, доработки под требования сео-специалистов. На основании заявки вам будет сформирован бюджет работ, а также названы сроки на выполнение тех или иных работ.