Completed
Push — master ( 8480f8...ee2fbd )
by Radu
01:36
created

AbstractPdoDatabase::setLastInsertId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
namespace WebServCo\Framework\Database;
3
4
use WebServCo\Framework\Exceptions\DatabaseException;
5
6
abstract class AbstractPdoDatabase extends \WebServCo\Framework\AbstractLibrary
7
{
8
    protected $db;
9
    protected $stmt;
10
    protected $rows;
11
12
    use \WebServCo\Framework\Traits\DatabaseTrait;
13
    use \WebServCo\Framework\Traits\DatabaseAddQueryTrait;
14
15
    abstract protected function getDataSourceName($host, $port, $dbname);
16
17
    public function __construct($settings = [])
18
    {
19
        parent::__construct($settings);
20
21
        try {
22
            $dsn = $this->getDataSourceName(
23
                $this->setting('connection/host', '127.0.0.1'),
24
                $this->setting('connection/port', null),
25
                $this->setting('connection/dbname', 'test')
26
            );
27
            $this->db = new \PDO(
28
                $dsn,
29
                $this->setting('connection/username', 'root'),
30
                $this->setting('connection/passwd', ''),
31
                [
32
                    \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
33
                    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
34
                    \PDO::ATTR_EMULATE_PREPARES => false,
35
                    \PDO::ATTR_PERSISTENT => false
36
                ]
37
            );
38
        } catch (\Exception $e) { // PDOException/RuntimeException/Exception
39
            throw new DatabaseException($e->getMessage(), $e);
40
        }
41
    }
42
43
    public function affectedRows()
44
    {
45
        if (!($this->stmt instanceof \PDOStatement)) {
46
            throw new DatabaseException('No Statement object available.');
47
        }
48
        return $this->stmt->rowCount();
49
    }
50
51
    public function escape($string)
52
    {
53
        return $this->db->quote($string);
54
    }
55
56
    public function getColumn($query, $params = [], $columnNumber = 0)
57
    {
58
        $this->query($query, $params);
59
        return $this->stmt->fetchColumn($columnNumber);
60
    }
61
62
    public function getRow($query, $params = [])
63
    {
64
        $this->query($query, $params);
65
        return $this->stmt->fetch(\PDO::FETCH_ASSOC);
66
    }
67
68
    public function getRows($query, $params = [])
69
    {
70
        $this->query($query, $params);
71
        $this->rows = $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
72
        return $this->rows;
73
    }
74
75
    /*
76
    * Get last inserted Id.
77
    *
78
    * https://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id
79
    * If you insert multiple rows using a single INSERT statement,
80
    * LAST_INSERT_ID() returns the value generated for the first inserted row only.
81
    * The reason for this is to make it possible to reproduce easily the same
82
    * INSERT statement against some other server.
83
    *
84
    * PDO:
85
    * Returns the ID of the last inserted row, or the last value from a sequence object,
86
    * depending on the underlying driver.
87
    * For example, PDO_PGSQL requires you to specify the name of a sequence object for the name parameter.
88
    */
89
    public function lastInsertId($name = null)
90
    {
91
        return $this->db->lastInsertId($name);
92
    }
93
94
    public function numRows()
95
    {
96
        if (!($this->stmt instanceof \PDOStatement)) {
97
            throw new DatabaseException('No Statement object available.');
98
        }
99
        if ('mysql' == $this->setting('driver')) {
100
            return $this->stmt->rowCount();
101
        }
102
        $rows = $this->rows ?: $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
103
        return count($rows);
104
    }
105
106
    public function query($query, $params = [])
107
    {
108
        if (empty($query)) {
109
            throw new DatabaseException('No query specified');
110
        }
111
112
        try {
113
            if (!empty($params)) {
114
                $this->stmt = $this->db->prepare($query);
115
                $this->bindParams($params);
116
                $this->stmt->execute();
117
            } else {
118
                $this->stmt = $this->db->query($query);
119
            }
120
            return $this->stmt;
121
        } catch (\PDOException $e) {
122
            throw new DatabaseException($e->getMessage(), $e);
123
        } catch (\RuntimeException $e) {
124
            throw new DatabaseException($e->getMessage(), $e);
125
        }
126
    }
127
128
    public function transaction($queries)
129
    {
130
        try {
131
            $this->db->beginTransaction();
132
            foreach ($queries as $item) {
133
                if (!isset($item[0])) {
134
                    throw new DatabaseException('No query specified');
135
                }
136
                $params = isset($item[1]) ? $item[1] : [];
137
                $this->query($item[0], $params);
138
            }
139
            $this->db->commit();
140
            return true;
141
        // \WebServCo\Framework\Exceptions\DatabaseException
142
        // PDOException/RuntimeException/Exception
143
        } catch (\Exception $e) {
144
            $this->db->rollBack();
145
            throw new DatabaseException($e->getMessage(), $e);
146
        }
147
    }
148
149
    protected function bindParams($data)
150
    {
151
        if (empty($data)) {
152
            return false;
153
        }
154
155
        if (!is_array($data)) {
156
            throw new DatabaseException('"Parameters" is not an array.');
157
        }
158
159
        $i = 1;
160
        foreach ($data as $item) {
161
            if (is_array($item)) {
162
                foreach ($item as $v) {
163
                    $this->validateParam($v);
164
                    $this->stmt->bindValue($i, $v, $this->getDataType($v));
165
                    $i++;
166
                }
167
            } else {
168
                $this->validateParam($item);
169
                $this->stmt->bindValue($i, $item, $this->getDataType($item));
170
                $i++;
171
            }
172
        }
173
        return true;
174
    }
175
176
    protected function getDataType($variable)
177
    {
178
        $type = gettype($variable);
179
180
        switch ($type) {
181
            case 'NULL':
182
                return \PDO::PARAM_NULL;
183
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
184
            case 'integer':
185
                return \PDO::PARAM_INT;
186
                break;
187
            case 'boolean':
188
                // causes data not to be inserted
189
                //return \PDO::PARAM_BOOL;
190
                //break;
191
            case 'string':
192
            case 'double':
193
            case 'array':
194
            case 'object':
195
            case 'resource':
196
            case 'resource (closed)':
197
            case 'unknown type':
198
            default:
199
                return \PDO::PARAM_STR;
200
                break;
201
        }
202
    }
203
204
    protected function validateParam($param)
205
    {
206
        if (is_array($param)) {
207
            throw new DatabaseException('Parameter is an array.');
208
        }
209
        return true;
210
    }
211
}
212