class Error

Same name in other branches
  1. 9 core/lib/Drupal/Core/Utility/Error.php \Drupal\Core\Utility\Error
  2. 8.9.x core/lib/Drupal/Core/Utility/Error.php \Drupal\Core\Utility\Error
  3. 10 core/lib/Drupal/Core/Utility/Error.php \Drupal\Core\Utility\Error

Drupal error utility class.

Hierarchy

  • class \Drupal\Core\Utility\Error

Expanded class hierarchy of Error

36 files declare their use of Error
AnnounceFetcher.php in core/modules/announcements_feed/src/AnnounceFetcher.php
bootstrap.inc in core/includes/bootstrap.inc
Functions that need to be loaded on every Drupal request.
BrowserHtmlDebugTrait.php in core/tests/Drupal/Tests/BrowserHtmlDebugTrait.php
BrowserTestBase.php in core/tests/Drupal/Tests/BrowserTestBase.php
ComponentLoader.php in core/lib/Drupal/Core/Template/Loader/ComponentLoader.php

... See full list

93 string references to 'Error'
AjaxTest::testUiAjaxException in core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php
Tests that Ajax errors are visible in the UI.
ajax_forms_test_advanced_commands_invoke_callback in core/modules/system/tests/modules/ajax_forms_test/ajax_forms_test.module
Ajax form callback: Selects 'invoke'.
AnalyzeTest::testAnalyzeBasic in core/modules/views_ui/tests/src/Functional/AnalyzeTest.php
Tests that analyze works in general.
BlockUiTest::testBlockValidateErrors in core/modules/block/tests/src/Functional/BlockUiTest.php
Tests if validation errors are passed plugin form to the parent form.
ConfigTargetTest::testIncorrectKey in core/modules/system/tests/src/Functional/Form/ConfigTargetTest.php
Tests #config_target with an incorrect key.

... See full list

File

core/lib/Drupal/Core/Utility/Error.php, line 16

Namespace

Drupal\Core\Utility
View source
class Error {
    
    /**
     * The error severity level.
     *
     * @var int
     */
    const ERROR = 3;
    
    /**
     * The default message for logging errors.
     */
    const DEFAULT_ERROR_MESSAGE = '%type: @message in %function (line %line of %file).';
    
    /**
     * An array of ignored functions.
     *
     * @var array
     */
    protected static $ignoredFunctions = [
        'debug',
        '_drupal_error_handler',
        '_drupal_exception_handler',
    ];
    
    /**
     * Decodes an exception and retrieves the correct caller.
     *
     * @param \Throwable $exception
     *   The exception object that was thrown.
     *
     * @return array
     *   An error in the format expected by _drupal_log_error().
     */
    public static function decodeException(\Throwable $exception) : array {
        $message = $exception->getMessage();
        $backtrace = $exception->getTrace();
        // Add the line throwing the exception to the backtrace.
        array_unshift($backtrace, [
            'line' => $exception->getLine(),
            'file' => $exception->getFile(),
        ]);
        // For PDOException errors, we try to return the initial caller,
        // skipping internal functions of the database layer.
        if ($exception instanceof \PDOException || $exception instanceof DatabaseExceptionWrapper) {
            $driver_namespace = Database::getConnectionInfo()['default']['namespace'];
            $backtrace = Connection::removeDatabaseEntriesFromDebugBacktrace($backtrace, $driver_namespace);
            if (isset($exception->query_string, $exception->args)) {
                $message .= ": " . $exception->query_string . "; " . print_r($exception->args, TRUE);
            }
        }
        $caller = static::getLastCaller($backtrace);
        return [
            '%type' => get_class($exception),
            // The standard PHP exception handler considers that the exception message
            // is plain-text. We mimic this behavior here.
'@message' => $message,
            '%function' => $caller['function'],
            '%file' => $caller['file'],
            '%line' => $caller['line'],
            'severity_level' => static::ERROR,
            'backtrace' => $backtrace,
            '@backtrace_string' => $exception->getTraceAsString(),
            'exception' => $exception,
        ];
    }
    
    /**
     * Log a formatted exception message to the provided logger.
     *
     * @param \Psr\Log\LoggerInterface $logger
     *   The logger.
     * @param \Throwable $exception
     *   The exception.
     * @param string $message
     *   (optional) The message.
     * @param array $additional_variables
     *   (optional) Any additional variables.
     * @param string $level
     *   The PSR log level. Must be valid constant in \Psr\Log\LogLevel.
     */
    public static function logException(LoggerInterface $logger, \Throwable $exception, string $message = Error::DEFAULT_ERROR_MESSAGE, array $additional_variables = [], string $level = LogLevel::ERROR) : void {
        $logger->log($level, $message, static::decodeException($exception) + $additional_variables);
    }
    
    /**
     * Renders an exception error message without further exceptions.
     *
     * @param \Exception|\Throwable $exception
     *   The exception object that was thrown.
     *
     * @return string
     *   An error message.
     */
    public static function renderExceptionSafe($exception) {
        $decode = static::decodeException($exception);
        $backtrace = $decode['backtrace'];
        unset($decode['backtrace'], $decode['exception']);
        // Remove 'main()'.
        array_shift($backtrace);
        // Even though it is possible that this method is called on a public-facing
        // site, it is only called when the exception handler itself threw an
        // exception, which normally means that a code change caused the system to
        // no longer function correctly (as opposed to a user-triggered error), so
        // we assume that it is safe to include a verbose backtrace.
        $decode['@backtrace'] = Error::formatBacktrace($backtrace);
        return new FormattableMarkup(Error::DEFAULT_ERROR_MESSAGE . ' <pre class="backtrace">@backtrace</pre>', $decode);
    }
    
    /**
     * Gets the last caller from a backtrace.
     *
     * @param array $backtrace
     *   A standard PHP backtrace. Passed by reference.
     *
     * @return array
     *   An associative array with keys 'file', 'line' and 'function'.
     */
    public static function getLastCaller(array &$backtrace) {
        // Errors that occur inside PHP internal functions do not generate
        // information about file and line. Ignore the ignored functions.
        while ($backtrace && !isset($backtrace[0]['line']) || isset($backtrace[1]['function']) && in_array($backtrace[1]['function'], static::$ignoredFunctions)) {
            array_shift($backtrace);
        }
        // The first trace is the call itself.
        // It gives us the line and the file of the last call.
        $call = $backtrace[0];
        // The second call gives us the function where the call originated.
        if (isset($backtrace[1])) {
            if (isset($backtrace[1]['class'])) {
                $call['function'] = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()';
            }
            else {
                $call['function'] = $backtrace[1]['function'] . '()';
            }
        }
        else {
            $call['function'] = 'main()';
        }
        return $call;
    }
    
    /**
     * Formats a backtrace into a plain-text string.
     *
     * The calls show values for scalar arguments and type names for complex ones.
     *
     * @param array $backtrace
     *   A standard PHP backtrace.
     *
     * @return string
     *   A plain-text line-wrapped string ready to be put inside <pre>.
     */
    public static function formatBacktrace(array $backtrace) {
        $return = '';
        foreach ($backtrace as $trace) {
            $call = [
                'function' => '',
                'args' => [],
            ];
            if (isset($trace['class'])) {
                $call['function'] = $trace['class'] . $trace['type'] . $trace['function'];
            }
            elseif (isset($trace['function'])) {
                $call['function'] = $trace['function'];
            }
            else {
                $call['function'] = 'main';
            }
            if (isset($trace['args'])) {
                foreach ($trace['args'] as $arg) {
                    if (is_scalar($arg)) {
                        $call['args'][] = is_string($arg) ? '\'' . Xss::filter($arg) . '\'' : $arg;
                    }
                    else {
                        $call['args'][] = ucfirst(gettype($arg));
                    }
                }
            }
            $line = '';
            if (isset($trace['line'])) {
                $line = " (Line: {$trace['line']})";
            }
            $return .= $call['function'] . '(' . implode(', ', $call['args']) . "){$line}\n";
        }
        return $return;
    }
    
    /**
     * Returns the current PHP error handler as a callable.
     *
     * @return callable|null
     *   The current error handler as a callable, or NULL if none is set.
     */
    public static function currentErrorHandler() : ?callable {
        $currentHandler = set_error_handler('var_dump');
        restore_error_handler();
        return $currentHandler;
    }

}

Members

Title Sort descending Modifiers Object type Summary
Error::$ignoredFunctions protected static property An array of ignored functions.
Error::currentErrorHandler public static function Returns the current PHP error handler as a callable.
Error::decodeException public static function Decodes an exception and retrieves the correct caller.
Error::DEFAULT_ERROR_MESSAGE constant The default message for logging errors.
Error::ERROR constant The error severity level.
Error::formatBacktrace public static function Formats a backtrace into a plain-text string.
Error::getLastCaller public static function Gets the last caller from a backtrace.
Error::logException public static function Log a formatted exception message to the provided logger.
Error::renderExceptionSafe public static function Renders an exception error message without further exceptions.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.