Completed
Push — master ( 72a69a...90f27b )
by Mikael
01:59
created

Database::fetchInto()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 3
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Anax\Database;
4
5
/**
6
 * Database wrapper, provides a database API on top of PHP PDO for
7
 * enhancing the API and dealing with error reporting and tracking.
8
 */
9
class Database
10
{
11
    /**
12
     * @var array        $options used when creating the PDO object
13
     * @var PDO          $pdo     the PDO object
14
     * @var PDOStatement $stmt    the latest PDOStatement used
15
     */
16
    private $options;
17
    private $pdo = null;
18
    private $stmt = null;
19
20
21
22
    /**
23
     * Constructor creating a PDO object connecting to a choosen database.
24
     *
25
     * @param array $options containing details for connecting to the database.
26
     */
27 7
    public function __construct($options = [])
28
    {
29 7
        $this->setOptions($options);
30 7
    }
31
32
33
34
    /**
35
     * Set options and connection details.
36
     *
37
     * @param array $options containing details for connecting to the database.
38
     *
39
     * @return void
40
     */
41 7
    public function setOptions($options = [])
42
    {
43
        $default = [
44 7
            'dsn'             => null,
45 7
            'username'        => null,
46 7
            'password'        => null,
47 7
            'driver_options'  => null,
48 7
            'table_prefix'    => null,
49 7
            'fetch_mode'      => \PDO::FETCH_OBJ,
50 7
            'session_key'     => 'Anax\Database',
51 7
            'verbose'         => null,
52 7
            'debug_connect'   => false,
53 7
        ];
54 7
        $this->options = array_merge($default, $options);
55 7
    }
56
57
58
59
    /**
60
     * Connect to the database.
61
     *
62
     * @return self
63
     *
64
     * @throws \Anax\Database\Exception
65
     */
66 7
    public function connect()
67
    {
68 7
        if (!isset($this->options['dsn'])) {
69 1
            throw new Exception("You can not connect, missing dsn.");
70
        }
71
72
        try {
73 7
            $this->pdo = new \PDO(
74 7
                $this->options['dsn'],
75 7
                $this->options['username'],
76 7
                $this->options['password'],
77 7
                $this->options['driver_options']
78 7
            );
79
80 7
            $this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, $this->options['fetch_mode']);
81 7
            $this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
82 7
        } catch (\PDOException $e) {
83 1
            if ($this->options['debug_connect']) {
84 1
                throw $e;
85
            }
86
            throw new Exception("Could not connect to database, hiding connection details.");
87
        }
88
89 7
        return $this;
90
    }
91
92
93
94
    /**
95
     * Support arrays in params, extract array items and add to $params
96
     * and insert ? for each entry in the array.
97
     *
98
     * @param string $query  as the query to prepare.
99
     * @param array  $params the parameters that may contain arrays.
100
     *
101
     * @return array with query and params.
102
     */
103 3
    private function expandParamArray($query, $params)
104
    {
105 3
        $param = [];
106 3
        $offset = -1;
107
108 3
        foreach ($params as $val) {
109 1
            $offset = strpos($query, '?', $offset + 1);
110
111 1
            if (is_array($val)) {
112
                $nrOfItems = count($val);
113
114
                if ($nrOfItems) {
115
                    $query = substr($query, 0, $offset)
116
                        . str_repeat('?,', $nrOfItems  - 1)
117
                        . '?'
118
                        . substr($query, $offset + 1);
119
                    $param = array_merge($param, $val);
120
                } else {
121
                    $param[] = null;
122
                }
123
            } else {
124 1
                $param[] = $val;
125
            }
126 3
        }
127
128 3
        return [$query, $param];
129
    }
130
131
132
133
    /**
134
     * Execute a select-query with arguments and return the resultset.
135
     *
136
     * @param string $query  the SQL statement
137
     * @param array  $params the params array
138
     *
139
     * @return array with resultset
140
     */
141
    public function executeFetchAll($query, $params = [])
142
    {
143
        $this->execute($query, $params);
144
        return $this->fetchAll();
145
    }
146
147
148
149
    /**
150
     * Fetch all resultset.
151
     *
152
     * @return array with resultset.
153
     */
154
    public function fetchAll()
155
    {
156
        return $this->stmt->fetchAll();
157
    }
158
159
160
161
    /**
162
     * Fetch one resultset.
163
     *
164
     * @return array with resultset.
165
     */
166
    public function fetchOne()
167
    {
168
        return $this->stmt->fetch();
169
    }
170
171
172
173
    /**
174
     * Fetch one resultset as an object from this class.
175
     *
176
     * @param object $class which type of object to instantiate.
177
     *
178
     * @return array with resultset.
179
     */
180
    public function fetchObject($class)
181
    {
182
        return $this->stmt->fetchObject($class);
183
    }
184
185
186
187
    /**
188
     * Fetch one resultset into an object.
189
     *
190
     * @param object $object to insert values into.
191
     *
192
     * @return array with resultset.
193
     */
194
    public function fetchInto($object)
195
    {
196
        $this->stmt->setFetchMode(\PDO::FETCH_INTO, $object);
197
        return $this->stmt->fetch();
198
    }
199
200
201
202
    /**
203
     * Execute a SQL-query and ignore the resultset.
204
     *
205
     * @param string $query  the SQL statement
206
     * @param array  $params the params array
207
     *
208
     * @return boolean returns TRUE on success or FALSE on failure.
209
     *
210
     * @throws Exception when failing to prepare question.
211
     */
212 3
    public function execute($query, $params = [])
213
    {
214 3
        list($query, $params) = $this->expandParamArray($query, $params);
215
216 3
        $this->stmt = $this->pdo->prepare($query);
217 3
        if (!$this->stmt) {
218
            $this->statementException($sql, $param);
0 ignored issues
show
Bug introduced by
The variable $sql does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $param does not exist. Did you mean $params?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
219
        }
220
221 3
        $res = $this->stmt->execute($params);
222 3
        if (!$res) {
223
            $this->statementException($sql, $param);
0 ignored issues
show
Bug introduced by
The variable $param does not exist. Did you mean $params?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
224
        }
225
226 3
        return $res;
227
    }
228
229
230
231
    /**
232
     * Through exception with detailed message.
233
     *
234
     * @param string       $sql     statement to execute
235
     * @param array        $param   to match ? in statement
236
     *
237
     * @return void
238
     *
239
     * @throws \Anax\Database\Exception
240
     */
241
    private function statementException($sql, $param)
242
    {
243
        throw new Exception(
244
            $this->stmt->errorInfo()[2]
245
            . "<br><br>SQL:<br><pre>$sql</pre><br>PARAMS:<br><pre>"
246
            . implode($param, "\n")
247
            . "</pre>"
248
        );
249
    }
250
251
252
253
    /**
254
     * Return last insert id from autoincremented key on INSERT.
255
     *
256
     * @return integer as last insert id.
257
     */
258
    public function lastInsertId()
259
    {
260
        return $this->pdo->lastInsertId();
261
    }
262
263
264
265
    /**
266
    * Return rows affected of last INSERT, UPDATE, DELETE
267
    *
268
    * @return integer as rows affected on last statement
269
    */
270
    public function rowCount()
271
    {
272
        return $this->stmt->rowCount();
273
    }
274
}
275