DBALException.php 2.5 KB
Newer Older
1 2
<?php

Michael Moravec's avatar
Michael Moravec committed
3 4
declare(strict_types=1);

5 6
namespace Doctrine\DBAL;

7
use Doctrine\DBAL\Driver\DriverException as DriverExceptionInterface;
8
use Doctrine\DBAL\Driver\ExceptionConverterDriver;
9 10 11
use Doctrine\DBAL\Exception\DriverException;
use Exception;
use Throwable;
12 13 14 15 16 17
use function array_map;
use function bin2hex;
use function implode;
use function is_resource;
use function is_string;
use function json_encode;
Sergei Morozov's avatar
Sergei Morozov committed
18
use function preg_replace;
19
use function sprintf;
20

21
class DBALException extends Exception
22
{
Benjamin Morel's avatar
Benjamin Morel committed
23
    /**
Sergei Morozov's avatar
Sergei Morozov committed
24
     * @param mixed[] $params
Benjamin Morel's avatar
Benjamin Morel committed
25
     */
26
    public static function driverExceptionDuringQuery(Driver $driver, Throwable $driverEx, string $sql, array $params = []) : self
27
    {
28 29 30 31 32 33 34 35 36 37 38 39
        $messageFormat = <<<'MESSAGE'
An exception occurred while executing "%s"%s:

%s
MESSAGE;

        $message = sprintf(
            $messageFormat,
            $sql,
            $params !== [] ? sprintf(' with params %s', self::formatParameters($params)) : '',
            $driverEx->getMessage()
        );
40

41
        return static::wrapException($driver, $driverEx, $message);
42 43
    }

44
    public static function driverException(Driver $driver, Throwable $driverEx) : self
45
    {
46
        return static::wrapException($driver, $driverEx, sprintf('An exception occurred in driver with message: %s', $driverEx->getMessage()));
47
    }
48

49
    private static function wrapException(Driver $driver, Throwable $driverEx, string $msg) : self
50
    {
51
        if ($driverEx instanceof DriverException) {
52 53
            return $driverEx;
        }
54

55
        if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverExceptionInterface) {
56
            return $driver->convertException($msg, $driverEx);
57
        }
58 59

        return new self($msg, 0, $driverEx);
60 61
    }

62 63 64 65
    /**
     * Returns a human-readable representation of an array of parameters.
     * This properly handles binary data by returning a hex representation.
     *
66
     * @param array<mixed, mixed> $params
67
     */
68
    private static function formatParameters(array $params) : string
69
    {
70
        return '[' . implode(', ', array_map(static function ($param) : string {
71 72 73
            if (is_resource($param)) {
                return (string) $param;
            }
74

75 76
            $json = @json_encode($param);

77
            if (! is_string($json) || $json === 'null' && is_string($param)) {
78
                // JSON encoding failed, this is not a UTF-8 string.
Sergei Morozov's avatar
Sergei Morozov committed
79
                return sprintf('"%s"', preg_replace('/.{2}/', '\\x$0', bin2hex($param)));
80 81 82 83 84
            }

            return $json;
        }, $params)) . ']';
    }
85
}