PDOStatement.php 6.26 KB
Newer Older
romanb's avatar
romanb committed
1 2
<?php

3 4
namespace Doctrine\DBAL\Driver;

5
use Doctrine\DBAL\FetchMode;
6
use Doctrine\DBAL\ParameterType;
7
use PDO;
8
use const E_USER_DEPRECATED;
Sergei Morozov's avatar
Sergei Morozov committed
9
use function array_slice;
Sergei Morozov's avatar
Sergei Morozov committed
10
use function assert;
Sergei Morozov's avatar
Sergei Morozov committed
11
use function func_get_args;
Sergei Morozov's avatar
Sergei Morozov committed
12
use function is_array;
13 14
use function sprintf;
use function trigger_error;
15

16 17 18 19
/**
 * The PDO implementation of the Statement interface.
 * Used by all PDO-based drivers.
 */
20
class PDOStatement extends \PDOStatement implements Statement
21
{
22 23 24 25
    private const PARAM_TYPE_MAP = [
        ParameterType::NULL         => PDO::PARAM_NULL,
        ParameterType::INTEGER      => PDO::PARAM_INT,
        ParameterType::STRING       => PDO::PARAM_STR,
26
        ParameterType::BINARY       => PDO::PARAM_LOB,
27 28 29 30 31 32 33 34 35 36 37 38 39
        ParameterType::LARGE_OBJECT => PDO::PARAM_LOB,
        ParameterType::BOOLEAN      => PDO::PARAM_BOOL,
    ];

    private const FETCH_MODE_MAP = [
        FetchMode::ASSOCIATIVE     => PDO::FETCH_ASSOC,
        FetchMode::NUMERIC         => PDO::FETCH_NUM,
        FetchMode::MIXED           => PDO::FETCH_BOTH,
        FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ,
        FetchMode::COLUMN          => PDO::FETCH_COLUMN,
        FetchMode::CUSTOM_OBJECT   => PDO::FETCH_CLASS,
    ];

Benjamin Morel's avatar
Benjamin Morel committed
40
    /**
41
     * Protected constructor.
Benjamin Morel's avatar
Benjamin Morel committed
42
     */
43
    protected function __construct()
Benjamin Morel's avatar
Benjamin Morel committed
44 45
    {
    }
46

Benjamin Morel's avatar
Benjamin Morel committed
47 48 49
    /**
     * {@inheritdoc}
     */
50
    public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null)
51
    {
52 53
        $fetchMode = $this->convertFetchMode($fetchMode);

54 55 56 57
        // This thin wrapper is necessary to shield against the weird signature
        // of PDOStatement::setFetchMode(): even if the second and third
        // parameters are optional, PHP will not let us remove it from this
        // declaration.
58 59 60 61 62 63 64 65 66 67 68 69
        try {
            if ($arg2 === null && $arg3 === null) {
                return parent::setFetchMode($fetchMode);
            }

            if ($arg3 === null) {
                return parent::setFetchMode($fetchMode, $arg2);
            }

            return parent::setFetchMode($fetchMode, $arg2, $arg3);
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
70
        }
71
    }
72 73 74 75

    /**
     * {@inheritdoc}
     */
76
    public function bindValue($param, $value, $type = ParameterType::STRING)
77
    {
78 79
        $type = $this->convertParamType($type);

80 81 82 83 84
        try {
            return parent::bindValue($param, $value, $type);
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
        }
85 86 87 88 89
    }

    /**
     * {@inheritdoc}
     */
90
    public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null)
91
    {
92 93
        $type = $this->convertParamType($type);

94
        try {
Sergei Morozov's avatar
Sergei Morozov committed
95
            return parent::bindParam($column, $variable, $type, ...array_slice(func_get_args(), 3));
96 97 98
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
        }
99 100
    }

101 102 103 104 105 106 107 108 109 110 111 112 113 114
    /**
     * {@inheritdoc}
     */
    public function closeCursor()
    {
        try {
            return parent::closeCursor();
        } catch (\PDOException $exception) {
            // Exceptions not allowed by the interface.
            // In case driver implementations do not adhere to the interface, silence exceptions here.
            return true;
        }
    }

115 116 117 118 119
    /**
     * {@inheritdoc}
     */
    public function execute($params = null)
    {
120 121 122 123 124
        try {
            return parent::execute($params);
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
        }
125 126 127 128 129
    }

    /**
     * {@inheritdoc}
     */
130
    public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
131
    {
Sergei Morozov's avatar
Sergei Morozov committed
132
        $args = func_get_args();
133

Sergei Morozov's avatar
Sergei Morozov committed
134 135 136
        if (isset($args[0])) {
            $args[0] = $this->convertFetchMode($args[0]);
        }
137

Sergei Morozov's avatar
Sergei Morozov committed
138 139
        try {
            return parent::fetch(...$args);
140 141
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
javer's avatar
javer committed
142
        }
143 144 145 146 147
    }

    /**
     * {@inheritdoc}
     */
javer's avatar
javer committed
148
    public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
149
    {
Sergei Morozov's avatar
Sergei Morozov committed
150 151 152 153 154
        $args = func_get_args();

        if (isset($args[0])) {
            $args[0] = $this->convertFetchMode($args[0]);
        }
155

Sergei Morozov's avatar
Sergei Morozov committed
156 157 158 159 160 161 162 163 164
        if ($fetchMode === null && $fetchArgument === null && $ctorArgs === null) {
            $args = [];
        } elseif ($fetchArgument === null && $ctorArgs === null) {
            $args = [$fetchMode];
        } elseif ($ctorArgs === null) {
            $args = [$fetchMode, $fetchArgument];
        } else {
            $args = [$fetchMode, $fetchArgument, $ctorArgs];
        }
165

Sergei Morozov's avatar
Sergei Morozov committed
166 167 168
        try {
            $data = parent::fetchAll(...$args);
            assert(is_array($data));
169

Sergei Morozov's avatar
Sergei Morozov committed
170
            return $data;
171 172
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
javer's avatar
javer committed
173
        }
174 175 176 177 178 179 180
    }

    /**
     * {@inheritdoc}
     */
    public function fetchColumn($columnIndex = 0)
    {
181 182 183 184 185
        try {
            return parent::fetchColumn($columnIndex);
        } catch (\PDOException $exception) {
            throw new PDOException($exception);
        }
186
    }
187 188 189 190 191 192 193 194

    /**
     * Converts DBAL parameter type to PDO parameter type
     *
     * @param int $type Parameter type
     */
    private function convertParamType(int $type) : int
    {
Sergei Morozov's avatar
Sergei Morozov committed
195
        if (! isset(self::PARAM_TYPE_MAP[$type])) {
196 197 198 199 200 201 202
            // TODO: next major: throw an exception
            @trigger_error(sprintf(
                'Using a PDO parameter type (%d given) is deprecated and will cause an error in Doctrine 3.0',
                $type
            ), E_USER_DEPRECATED);

            return $type;
203 204 205 206 207 208 209 210
        }

        return self::PARAM_TYPE_MAP[$type];
    }

    /**
     * Converts DBAL fetch mode to PDO fetch mode
     *
Sergei Morozov's avatar
Sergei Morozov committed
211
     * @param int $fetchMode Fetch mode
212
     */
Sergei Morozov's avatar
Sergei Morozov committed
213
    private function convertFetchMode(int $fetchMode) : int
214
    {
Sergei Morozov's avatar
Sergei Morozov committed
215
        if (! isset(self::FETCH_MODE_MAP[$fetchMode])) {
216 217 218 219 220 221 222 223
            // TODO: next major: throw an exception
            @trigger_error(sprintf(
                'Using a PDO fetch mode or their combination (%d given)' .
                ' is deprecated and will cause an error in Doctrine 3.0',
                $fetchMode
            ), E_USER_DEPRECATED);

            return $fetchMode;
224 225 226 227
        }

        return self::FETCH_MODE_MAP[$fetchMode];
    }
228
}