1
|
|
|
<?php
|
2
|
|
|
namespace DBAL;
|
3
|
|
|
|
4
|
|
|
use PDO;
|
5
|
|
|
use DBAL\Modifiers\SafeString;
|
6
|
|
|
use DBAL\Modifiers\Operators;
|
7
|
|
|
|
8
|
|
|
/**
|
9
|
|
|
* PDO Database connection class
|
10
|
|
|
*
|
11
|
|
|
* @author Adam Binnersley <[email protected]>
|
12
|
|
|
* @version PDO Database Class
|
13
|
|
|
*/
|
14
|
|
|
final class Database implements DBInterface{
|
15
|
|
|
protected $db;
|
16
|
|
|
public $sql;
|
17
|
|
|
private $key;
|
18
|
|
|
|
19
|
|
|
protected $logLocation;
|
20
|
|
|
public $logErrors = true;
|
21
|
|
|
public $logQueries = false;
|
22
|
|
|
public $displayErrors = false;
|
23
|
|
|
|
24
|
|
|
protected $database;
|
25
|
|
|
protected $cacheEnabled = false;
|
26
|
|
|
protected $cacheObj;
|
27
|
|
|
protected $cacheValue;
|
28
|
|
|
protected $modified = false;
|
29
|
|
|
|
30
|
|
|
private $query;
|
31
|
|
|
private $values = [];
|
32
|
|
|
private $prepare = [];
|
33
|
|
|
|
34
|
|
|
private static $connectors = array(
|
35
|
|
|
'cubrid' => 'cubrid:host=%s;port=%d;dbname=%s',
|
36
|
|
|
'dblib' => 'dblib:host=%s:%d;dbname=%s',
|
37
|
|
|
'mssql' => 'sqlsrv:Server=%s,%d;Database=%s',
|
38
|
|
|
'mysql' => 'mysql:host=%s;port=%d;dbname=%s',
|
39
|
|
|
'pgsql' => 'pgsql:host=%s;port=%d;dbname=%s',
|
40
|
|
|
'sqlite' => 'sqlite::memory:'
|
41
|
|
|
);
|
42
|
|
|
|
43
|
|
|
/**
|
44
|
|
|
* Connect to database using PDO connection
|
45
|
|
|
* @param string $hostname This should be the host of the database e.g. 'localhost'
|
46
|
|
|
* @param string $username This should be the username for the chosen database
|
47
|
|
|
* @param string $password This should be the password for the chosen database
|
48
|
|
|
* @param string $database This should be the database that you wish to connect to
|
49
|
|
|
* @param string|false $backuphost If you have a replication server set up put the hostname or IP address incase the primary server goes down
|
50
|
|
|
* @param object|false $cache If you want to cache the queries with Memcache(d)/Redis/APC/Xcache This should be the object else set to false
|
51
|
|
|
* @param boolean $persistent If you want a persistent database connection set to true
|
52
|
|
|
* @param string $type The type of connection that you wish to make can be 'mysql', 'cubrid', 'dblib', 'mssql', 'odbc', 'pgsql, or 'sqlite'
|
53
|
|
|
* @param int $port This should be the port number of the MySQL database connection
|
54
|
|
|
*/
|
55
|
1 |
|
public function __construct($hostname, $username, $password, $database, $backuphost = false, $cache = false, $persistent = false, $type = 'mysql', $port = 3306) {
|
56
|
1 |
|
$this->setLogLocation();
|
57
|
|
|
try{
|
58
|
1 |
|
$this->connectToServer($username, $password, $database, $hostname, $persistent, $type, $port);
|
59
|
|
|
}
|
60
|
1 |
|
catch(\Exception $e) {
|
61
|
1 |
|
if($backuphost !== false) {
|
62
|
|
|
$this->connectToServer($username, $password, $database, $backuphost, $persistent, $type, $port);
|
63
|
|
|
}
|
64
|
1 |
|
$this->error($e);
|
65
|
|
|
}
|
66
|
1 |
|
if(is_object($cache)) {
|
67
|
|
|
$this->setCaching($cache);
|
68
|
|
|
}
|
69
|
1 |
|
}
|
70
|
|
|
|
71
|
|
|
/**
|
72
|
|
|
* Closes the PDO database connection when Database object unset
|
73
|
|
|
*/
|
74
|
|
|
public function __destruct() {
|
75
|
|
|
$this->closeDatabase();
|
76
|
|
|
}
|
77
|
|
|
|
78
|
|
|
/**
|
79
|
|
|
* Connect to the database using PDO connection
|
80
|
|
|
* @param string $username This should be the username for the chosen database
|
81
|
|
|
* @param string $password This should be the password for the chosen database
|
82
|
|
|
* @param string $database This should be the database that you wish to connect to
|
83
|
|
|
* @param string $hostname The hostname for the database
|
84
|
|
|
* @param boolean $persistent If you want a persistent database connection set to true
|
85
|
|
|
* @param string $type The type of connection that you wish to make can be 'mysql', 'cubrid', 'dblib', 'mssql', 'pgsql, or 'sqlite'
|
86
|
|
|
* @param int $port The port number to connect to the MySQL server
|
87
|
|
|
*/
|
88
|
2 |
|
protected function connectToServer($username, $password, $database, $hostname, $persistent = false, $type = 'mysql', $port = 3306) {
|
89
|
2 |
|
if(!$this->db) {
|
90
|
2 |
|
$this->database = $database;
|
91
|
2 |
|
$this->db = new PDO(sprintf(self::$connectors[$type], $hostname, $port, $database), $username, $password,
|
92
|
2 |
|
array_merge(
|
93
|
2 |
|
($persistent !== false ? array(PDO::ATTR_PERSISTENT => true) : array()),
|
94
|
2 |
|
($type === 'mysql' ? array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, PDO::ATTR_EMULATE_PREPARES => true) : array())
|
95
|
|
|
)
|
96
|
|
|
);
|
97
|
2 |
|
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
98
|
|
|
}
|
99
|
2 |
|
}
|
100
|
|
|
|
101
|
|
|
/**
|
102
|
|
|
* Enables the caching and set the caching object to the one provided
|
103
|
|
|
* @param object $caching This should be class of the type of caching you are using
|
104
|
|
|
*/
|
105
|
|
|
public function setCaching($caching) {
|
106
|
|
|
if(is_object($caching)) {
|
107
|
|
|
$this->cacheObj = $caching;
|
108
|
|
|
$this->cacheEnabled = true;
|
109
|
|
|
}
|
110
|
|
|
return $this;
|
111
|
|
|
}
|
112
|
|
|
|
113
|
|
|
/**
|
114
|
|
|
* This query function is used for more advanced SQL queries for which non of the other methods fit
|
115
|
|
|
* @param string $sql This should be the SQL query which you wish to run
|
116
|
|
|
* @param array $variables This should be an array of values to execute as the values in a prepared statement
|
117
|
|
|
* @return array Returns array of results for the query that has just been run
|
118
|
|
|
*/
|
119
|
1 |
|
public function query($sql, $variables = array(), $cache = true) {
|
120
|
|
|
try{
|
121
|
1 |
|
$this->sql = $sql;
|
122
|
1 |
|
$this->query = $this->db->prepare($this->sql);
|
123
|
1 |
|
$this->query->execute($variables);
|
124
|
1 |
|
if(strpos($this->sql, 'SELECT') !== false) {
|
125
|
1 |
|
return $this->query->fetchAll(PDO::FETCH_ASSOC);
|
126
|
|
|
}
|
127
|
|
|
}
|
128
|
|
|
catch(\Exception $e) {
|
129
|
|
|
$this->error($e);
|
130
|
|
|
}
|
131
|
1 |
|
}
|
132
|
|
|
|
133
|
|
|
/**
|
134
|
|
|
* Returns a single record for a select query for the chosen table
|
135
|
|
|
* @param string $table This should be the table you wish to select the values from
|
136
|
|
|
* @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
|
137
|
|
|
* @param string|array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
|
138
|
|
|
* @param array|string $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC')
|
139
|
|
|
* @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
|
140
|
|
|
* @return array Returns a single table record as the standard array when running SQL queries
|
141
|
|
|
*/
|
142
|
1 |
|
public function select($table, $where = array(), $fields = '*', $order = array(), $cache = true) {
|
143
|
1 |
|
return $this->selectAll($table, $where, $fields, $order, 1, $cache);
|
|
|
|
|
144
|
|
|
}
|
145
|
|
|
|
146
|
|
|
/**
|
147
|
|
|
* Returns a multidimensional array of the results from the selected table given the given parameters
|
148
|
|
|
* @param string $table This should be the table you wish to select the values from
|
149
|
|
|
* @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
|
150
|
|
|
* @param string|array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
|
151
|
|
|
* @param array $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC')
|
152
|
|
|
* @param integer|array $limit The number of results you want to return 0 is default and returns all results, else should be formated either as a standard integer or as an array as the start and end values e.g. array(0 => 150)
|
153
|
|
|
* @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
|
154
|
|
|
* @return array Returns a multidimensional array with the chosen fields from the table
|
155
|
|
|
*/
|
156
|
3 |
|
public function selectAll($table, $where = array(), $fields = '*', $order = array(), $limit = 0, $cache = true) {
|
157
|
3 |
|
$this->buildSelectQuery(SafeString::makeSafe($table), $where, $fields, $order, $limit);
|
158
|
3 |
|
$result = $this->executeQuery($cache);
|
159
|
3 |
|
if(!$result) {
|
160
|
3 |
|
if($limit === 1) {$result = $this->query->fetch(PDO::FETCH_ASSOC);} // Reduce the memory usage if only one record and increase performance
|
161
|
2 |
|
else{$result = $this->query->fetchAll(PDO::FETCH_ASSOC);}
|
162
|
3 |
|
if($cache && $this->cacheEnabled) {$this->setCache($this->key, $result);}
|
163
|
|
|
}
|
164
|
3 |
|
return $result ? $result : false;
|
165
|
|
|
}
|
166
|
|
|
|
167
|
|
|
/**
|
168
|
|
|
* Returns a single column value for a given query
|
169
|
|
|
* @param string $table This should be the table you wish to select the values from
|
170
|
|
|
* @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
|
171
|
|
|
* @param array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
|
172
|
|
|
* @param int $colNum This should be the column number you wish to get (starts at 0)
|
173
|
|
|
* @param array $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC') so it can be done in both directions
|
174
|
|
|
* @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
|
175
|
|
|
* @return mixed If a result is found will return the value of the colum given else will return false
|
176
|
|
|
*/
|
177
|
2 |
|
public function fetchColumn($table, $where = array(), $fields = '*', $colNum = 0, $order = array(), $cache = true) {
|
178
|
2 |
|
$this->buildSelectQuery(SafeString::makeSafe($table), $where, $fields, $order, 1);
|
179
|
2 |
|
$result = $this->executeQuery($cache);
|
180
|
2 |
|
if(!$result) {
|
181
|
2 |
|
$column = $this->query->fetchColumn(intval($colNum));
|
182
|
2 |
|
if($cache && $this->cacheEnabled) {$this->setCache($this->key, $column);}
|
183
|
|
|
}
|
184
|
2 |
|
return ($column ? $column : false);
|
|
|
|
|
185
|
|
|
}
|
186
|
|
|
|
187
|
|
|
/**
|
188
|
|
|
* Inserts into database using the prepared PDO statements
|
189
|
|
|
* @param string $table This should be the table you wish to insert the values into
|
190
|
|
|
* @param array $records This should be the field names and values in the format of array('fieldname' => 'value', 'fieldname2' => 'value2', etc.)
|
191
|
|
|
* @return boolean If data is inserted returns true else returns false
|
192
|
|
|
*/
|
193
|
2 |
|
public function insert($table, $records) {
|
194
|
2 |
|
unset($this->prepare);
|
195
|
|
|
|
196
|
2 |
|
$this->sql = sprintf("INSERT INTO `%s` (%s) VALUES (%s);", SafeString::makeSafe($table), $this->fields($records, true), implode(', ', $this->prepare));
|
197
|
2 |
|
$this->executeQuery(false);
|
198
|
2 |
|
return $this->numRows() ? true : false;
|
199
|
|
|
}
|
200
|
|
|
|
201
|
|
|
/**
|
202
|
|
|
* Updates values in a database using the provide variables
|
203
|
|
|
* @param string $table This should be the table you wish to update the values for
|
204
|
|
|
* @param array $records This should be the field names and new values in the format of array('fieldname' => 'newvalue', 'fieldname2' => 'newvalue2', etc.)
|
205
|
|
|
* @param array $where Should be the field names and values you wish to update in the form of an array e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
|
206
|
|
|
* @param int $limit The number of results you want to return 0 is default and will update all results that match the query, else should be formated as a standard integer
|
207
|
|
|
* @return boolean Returns true if update is successful else returns false
|
208
|
|
|
*/
|
209
|
2 |
|
public function update($table, $records, $where = array(), $limit = 0) {
|
210
|
2 |
|
$this->sql = sprintf("UPDATE `%s` SET %s %s%s;", SafeString::makeSafe($table), $this->fields($records), $this->where($where), $this->limit($limit));
|
211
|
2 |
|
$this->executeQuery(false);
|
212
|
2 |
|
return $this->numRows() ? true : false;
|
213
|
|
|
}
|
214
|
|
|
|
215
|
|
|
/**
|
216
|
|
|
* Deletes records from the given table based on the variables given
|
217
|
|
|
* @param string $table This should be the table you wish to delete the records from
|
218
|
|
|
* @param array $where This should be an array of for the where statement
|
219
|
|
|
* @param int $limit The number of results you want to return 0 is default and will delete all results that match the query, else should be formated as a standard integer
|
220
|
|
|
*/
|
221
|
2 |
|
public function delete($table, $where, $limit = 0) {
|
222
|
2 |
|
$this->sql = sprintf("DELETE FROM `%s` %s%s;", SafeString::makeSafe($table), $this->where($where), $this->limit($limit));
|
223
|
2 |
|
$this->executeQuery(false);
|
224
|
2 |
|
return $this->numRows() ? true : false;
|
225
|
|
|
}
|
226
|
|
|
|
227
|
|
|
/**
|
228
|
|
|
* Count the number of return results
|
229
|
|
|
* @param string $table The table you wish to count the result of
|
230
|
|
|
* @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
|
231
|
|
|
* @param boolean $cache If the query should be cached or loaded from cache set to true else set to false
|
232
|
|
|
* @return int Returns the number of results
|
233
|
|
|
*/
|
234
|
1 |
|
public function count($table, $where = array(), $cache = true) {
|
235
|
1 |
|
$this->sql = sprintf("SELECT count(*) FROM `%s`%s;", SafeString::makeSafe($table), $this->where($where));
|
236
|
1 |
|
$this->key = md5($this->database.$this->sql.serialize($this->values));
|
237
|
|
|
|
238
|
1 |
|
$result = $this->executeQuery($cache);
|
239
|
1 |
|
if(!$result) {
|
240
|
1 |
|
$result = $this->query->fetchColumn();
|
241
|
1 |
|
if($cache && $this->cacheEnabled) {$this->setCache($this->key, $result);}
|
242
|
|
|
}
|
243
|
1 |
|
return $result;
|
244
|
|
|
}
|
245
|
|
|
|
246
|
|
|
/**
|
247
|
|
|
* Truncates a given table from the selected database so there are no values in the table
|
248
|
|
|
* @param string $table This should be the table you wish to truncate
|
249
|
|
|
* @return boolean If the table is emptied returns true else returns false
|
250
|
|
|
*/
|
251
|
|
|
public function truncate($table) {
|
252
|
|
|
try{
|
253
|
|
|
$this->sql = sprintf("TRUNCATE TABLE `%s`", SafeString::makeSafe($table));
|
254
|
|
|
$this->query = $this->db->exec($this->sql);
|
255
|
|
|
}
|
256
|
|
|
catch(\Exception $e) {
|
257
|
|
|
$this->error($e);
|
258
|
|
|
}
|
259
|
|
|
return $this->query ? true : false;
|
260
|
|
|
}
|
261
|
|
|
|
262
|
|
|
/**
|
263
|
|
|
* Returns the number of rows for the last query sent
|
264
|
|
|
* @return int Returns the number of rows for the last query
|
265
|
|
|
*/
|
266
|
7 |
|
public function numRows() {
|
267
|
7 |
|
if(isset($this->query)) {
|
268
|
7 |
|
return $this->query->rowCount();
|
269
|
|
|
}
|
270
|
|
|
return 0;
|
271
|
|
|
}
|
272
|
|
|
|
273
|
|
|
/**
|
274
|
|
|
* Returns the number of rows for the last query sent (Looks a the numRows() function just added incase of habbit)
|
275
|
|
|
* @return int Returns the number of rows for the last query
|
276
|
|
|
*/
|
277
|
1 |
|
public function rowCount() {
|
278
|
1 |
|
return $this->numRows();
|
279
|
|
|
}
|
280
|
|
|
|
281
|
|
|
/**
|
282
|
|
|
* Returns the ID of the last record last inserted
|
283
|
|
|
* @param string $name This should be the name of the sequence object you wish to retrieve
|
284
|
|
|
* @return int|string Returns the last inserted ID of the last insert item if $name is null else returns string with sequenced object
|
285
|
|
|
*/
|
286
|
1 |
|
public function lastInsertId($name = null) {
|
287
|
1 |
|
return $this->db->lastInsertId($name);
|
288
|
|
|
}
|
289
|
|
|
|
290
|
|
|
/**
|
291
|
|
|
* Checks to see if a connection has been made to the server
|
292
|
|
|
* @return boolean
|
293
|
|
|
*/
|
294
|
2 |
|
public function isConnected() {
|
295
|
2 |
|
return is_object($this->db) ? true : false;
|
296
|
|
|
}
|
297
|
|
|
|
298
|
|
|
/**
|
299
|
|
|
* Returns the server version information
|
300
|
|
|
*/
|
301
|
|
|
public function serverVersion() {
|
302
|
|
|
return $this->db->getAttribute(PDO::ATTR_SERVER_VERSION);
|
303
|
|
|
}
|
304
|
|
|
|
305
|
|
|
/**
|
306
|
|
|
* Sets the location of the log files
|
307
|
|
|
* @param string $location This should be where you wish the logs to be stored
|
308
|
|
|
* @return $this
|
309
|
|
|
*/
|
310
|
|
|
public function setLogLocation($location = false) {
|
311
|
|
|
if($location === false) {
|
312
|
|
|
$location = dirname(__FILE__).DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR;
|
313
|
|
|
}
|
314
|
|
|
$this->logLocation = $location;
|
315
|
|
|
if (!file_exists($location)) {
|
316
|
|
|
mkdir($location, 0777, true);
|
317
|
|
|
}
|
318
|
|
|
return $this;
|
319
|
|
|
}
|
320
|
|
|
|
321
|
|
|
/**
|
322
|
|
|
* Displays the error massage which occurs
|
323
|
|
|
* @param \Exception $error This should be an instance of Exception
|
324
|
|
|
*/
|
325
|
1 |
|
private function error($error) {
|
326
|
1 |
|
if($this->logErrors) {
|
327
|
1 |
|
$file = $this->logLocation.'db-errors.txt';
|
328
|
1 |
|
$current = file_get_contents($file);
|
329
|
1 |
|
$current .= date('d/m/Y H:i:s')." ERROR: ".$error->getMessage()." on ".$this->sql."\n";
|
330
|
1 |
|
file_put_contents($file, $current);
|
331
|
|
|
}
|
332
|
1 |
|
if($this->displayErrors) {
|
333
|
|
|
die('ERROR: '.$error->getMessage().' on '.$this->sql);
|
334
|
|
|
}
|
335
|
1 |
|
}
|
336
|
|
|
|
337
|
|
|
/**
|
338
|
|
|
* Writes all queries to a log file
|
339
|
|
|
*/
|
340
|
|
|
public function writeQueryToLog() {
|
341
|
|
|
$file = $this->logLocation.'queries.txt';
|
342
|
|
|
$current = file_get_contents($file);
|
343
|
|
|
$current .= "SQL: ".$this->sql.":".serialize($this->values)."\n";
|
344
|
|
|
file_put_contents($file, $current);
|
345
|
|
|
}
|
346
|
|
|
|
347
|
|
|
/**
|
348
|
|
|
* Closes the PDO database connection by setting the connection to NULL
|
349
|
|
|
*/
|
350
|
|
|
public function closeDatabase() {
|
351
|
|
|
$this->db = null;
|
352
|
|
|
}
|
353
|
|
|
|
354
|
|
|
/**
|
355
|
|
|
* Build the SQL query but doesn't execute it
|
356
|
|
|
* @param string $table This should be the table you wish to select the values from
|
357
|
|
|
* @param array $where Should be the field names and values you wish to use as the where query e.g. array('fieldname' => 'value', 'fieldname2' => 'value2', etc).
|
358
|
|
|
* @param string|array $fields This should be the records you wis to select from the table. It should be either set as '*' which is the default or set as an array in the following format array('field', 'field2', 'field3', etc).
|
359
|
|
|
* @param array $order This is the order you wish the results to be ordered in should be formatted as follows array('fieldname' => 'ASC') or array("'fieldname', 'fieldname2'" => 'DESC') so it can be done in both directions
|
360
|
|
|
* @param integer|array $limit The number of results you want to return 0 is default and returns all results, else should be formated either as a standard integer or as an array as the start and end values e.g. array(0 => 150)
|
361
|
|
|
*/
|
362
|
5 |
|
protected function buildSelectQuery($table, $where = array(), $fields = '*', $order = array(), $limit = 0) {
|
363
|
5 |
|
if(is_array($fields)) {
|
364
|
|
|
$selectfields = array();
|
365
|
|
|
foreach($fields as $field => $value) {
|
366
|
|
|
$selectfields[] = sprintf("`%s`", SafeString::makeSafe($value));
|
367
|
|
|
}
|
368
|
|
|
$fieldList = implode(', ', $selectfields);
|
369
|
|
|
}
|
370
|
5 |
|
else{$fieldList = '*';}
|
371
|
|
|
|
372
|
5 |
|
$this->sql = sprintf("SELECT %s FROM `%s`%s%s%s;", $fieldList, SafeString::makeSafe($table), $this->where($where), $this->orderBy($order), $this->limit($limit));
|
373
|
5 |
|
$this->key = md5($this->database.$this->sql.serialize($this->values));
|
374
|
5 |
|
}
|
375
|
|
|
|
376
|
|
|
/**
|
377
|
|
|
* Execute the current query if no cache value is available
|
378
|
|
|
* @param boolean $cache If the cache should be checked for the checked for the values of the query set to true else set to false
|
379
|
|
|
* @return mixed If a cached value exists will be returned else if cache is not checked and query is executed will not return anything
|
380
|
|
|
*/
|
381
|
12 |
|
protected function executeQuery($cache = true) {
|
382
|
12 |
|
if($this->logQueries) {$this->writeQueryToLog();}
|
383
|
12 |
|
if($cache && $this->cacheEnabled && $this->getCache($this->key)) {
|
384
|
|
|
return $this->cacheValue;
|
385
|
|
|
}
|
386
|
|
|
try{
|
387
|
12 |
|
$this->query = $this->db->prepare($this->sql);
|
388
|
12 |
|
$this->bindValues($this->values);
|
389
|
12 |
|
$this->query->execute();
|
390
|
12 |
|
unset($this->values);
|
391
|
12 |
|
$this->values = [];
|
392
|
|
|
}
|
393
|
2 |
|
catch(\Exception $e) {
|
394
|
2 |
|
$this->error($e);
|
395
|
|
|
}
|
396
|
12 |
|
}
|
397
|
|
|
|
398
|
|
|
/**
|
399
|
|
|
* This outputs the SQL where query based on a given array
|
400
|
|
|
* @param array $where This should be an array that you wish to create the where query for in the for array('field1' => 'test') or array('field1' => array('>=', 0))
|
401
|
|
|
* @return string|false If the where query is an array will return the where string and set the values else returns false if no array sent
|
402
|
|
|
*/
|
403
|
|
|
private function where($where) {
|
404
|
|
|
if(is_array($where) && !empty($where)) {
|
405
|
|
|
$wherefields = array();
|
406
|
|
|
foreach($where as $field => $value) {
|
407
|
|
|
$wherefields[] = $this->formatValues($field, $value);
|
408
|
|
|
}
|
409
|
|
|
if(!empty($wherefields)) {
|
410
|
|
|
return " WHERE ".implode(' AND ', $wherefields);
|
411
|
|
|
}
|
412
|
|
|
}
|
413
|
|
|
return false;
|
414
|
|
|
}
|
415
|
|
|
|
416
|
|
|
/**
|
417
|
|
|
* Sets the order sting for the SQL query based on an array or string
|
418
|
|
|
* @param array|string $order This should be either set to array('fieldname' => 'ASC/DESC') or RAND()
|
419
|
|
|
* @return string|false If the SQL query has an valid order by will return a string else returns false
|
420
|
|
|
*/
|
421
|
1 |
|
private function orderBy($order) {
|
422
|
1 |
|
if(is_array($order) && !empty(array_filter($order))) {
|
423
|
1 |
|
$string = array();
|
424
|
1 |
|
foreach($order as $fieldorder => $fieldvalue) {
|
425
|
1 |
|
if(!empty($fieldorder) && !empty($fieldvalue)) {
|
426
|
1 |
|
$string[] = sprintf("`%s` %s", SafeString::makeSafe($fieldorder), strtoupper(SafeString::makeSafe($fieldvalue)));
|
427
|
|
|
}
|
428
|
|
|
elseif($fieldvalue === 'RAND()') {
|
429
|
1 |
|
$string[] = $fieldvalue;
|
430
|
|
|
}
|
431
|
|
|
}
|
432
|
1 |
|
return sprintf(" ORDER BY %s", implode(", ", $string));
|
433
|
|
|
}
|
434
|
|
|
elseif($order == 'RAND()') {
|
435
|
|
|
return " ORDER BY RAND()";
|
436
|
|
|
}
|
437
|
|
|
return false;
|
438
|
|
|
}
|
439
|
|
|
|
440
|
|
|
/**
|
441
|
|
|
* Build the field list for the query
|
442
|
|
|
* @param array $records This should be an array listing all of the fields
|
443
|
|
|
* @param boolean $insert If this is an insert statement should be set to true to create the correct amount of queries for the prepared statement
|
444
|
|
|
* @return string The fields list will be returned as a string to insert into the SQL query
|
445
|
|
|
*/
|
446
|
|
|
private function fields($records, $insert = false) {
|
447
|
|
|
$fields = array();
|
448
|
|
|
|
449
|
|
|
foreach($records as $field => $value) {
|
450
|
|
|
if($insert === true) {
|
451
|
|
|
$fields[] = sprintf("`%s`", SafeString::makeSafe($field));
|
452
|
|
|
$this->prepare[] = '?';
|
453
|
|
|
}
|
454
|
|
|
else{
|
455
|
|
|
$fields[] = sprintf("`%s` = ?", SafeString::makeSafe($field));
|
456
|
|
|
}
|
457
|
|
|
$this->values[] = $value;
|
458
|
|
|
}
|
459
|
|
|
return implode(', ', $fields);
|
460
|
|
|
}
|
461
|
|
|
|
462
|
|
|
/**
|
463
|
|
|
* Returns the limit SQL for the current query as a string
|
464
|
|
|
* @param integer|array $limit This should either be set as an integer or should be set as an array with a start and end value
|
465
|
|
|
* @return string|false Will return the LIMIT string for the current query if it is valid else returns false
|
466
|
|
|
*/
|
467
|
1 |
|
private function limit($limit = 0) {
|
468
|
1 |
|
if(is_array($limit) && !empty(array_filter($limit))) {
|
469
|
|
|
foreach($limit as $start => $end) {
|
470
|
|
|
return " LIMIT ".intval($start).", ".intval($end);
|
471
|
|
|
}
|
472
|
|
|
}
|
473
|
1 |
|
elseif((int)$limit > 0) {
|
474
|
1 |
|
return " LIMIT ".intval($limit);
|
475
|
|
|
}
|
476
|
1 |
|
return false;
|
477
|
|
|
}
|
478
|
|
|
|
479
|
|
|
|
480
|
|
|
/**
|
481
|
|
|
* Set the cache with a key and value
|
482
|
|
|
* @param string $key The unique key to store the value against
|
483
|
|
|
* @param mixed $value The value of the MYSQL query
|
484
|
|
|
*/
|
485
|
|
|
public function setCache($key, $value) {
|
486
|
|
|
if($this->cacheEnabled) {
|
487
|
|
|
$this->cacheObj->save($key, $value);
|
488
|
|
|
}
|
489
|
|
|
}
|
490
|
|
|
|
491
|
|
|
/**
|
492
|
|
|
* Get the results for a given key
|
493
|
|
|
* @param string $key The unique key to check for stored variables
|
494
|
|
|
* @return mixed Returned the cached results from
|
495
|
|
|
*/
|
496
|
|
|
public function getCache($key) {
|
497
|
|
|
if($this->modified === true || !$this->cacheEnabled) {return false;}
|
498
|
|
|
else{
|
499
|
|
|
$this->cacheValue = $this->cacheObj->fetch($key);
|
500
|
|
|
return $this->cacheValue;
|
501
|
|
|
}
|
502
|
|
|
}
|
503
|
|
|
|
504
|
|
|
/**
|
505
|
|
|
* Clears the cache
|
506
|
|
|
*/
|
507
|
|
|
public function flushDB() {
|
508
|
|
|
$this->cacheObj->deleteAll();
|
509
|
|
|
}
|
510
|
|
|
|
511
|
|
|
/**
|
512
|
|
|
* Format the where queries and set the prepared values
|
513
|
|
|
* @param string $field This should be the field name in the database
|
514
|
|
|
* @param mixed $value This should be the value which should either be a string or an array if it contains an operator
|
515
|
|
|
* @return string This should be the string to add to the SQL query
|
516
|
|
|
*/
|
517
|
2 |
|
protected function formatValues($field, $value) {
|
518
|
2 |
|
if(!is_array($value) && Operators::isOperatorValid($value) && !Operators::isOperatorPrepared($value)) {
|
519
|
|
|
return sprintf("`%s` %s", SafeString::makeSafe($field), Operators::getOperatorFormat($value));
|
520
|
|
|
}
|
521
|
2 |
|
elseif(is_array($value)) {
|
522
|
2 |
|
if(!is_array(array_values($value)[0])) {
|
523
|
2 |
|
$this->values[] = (isset($value[1]) ? $value[1] : array_values($value)[0]);
|
524
|
2 |
|
$operator = (isset($value[0]) ? $value[0] : key($value));
|
525
|
|
|
}
|
526
|
|
|
else{
|
527
|
|
|
foreach(array_values($value)[0] as $op => $array_value) {
|
528
|
|
|
$this->values[] = $array_value;
|
529
|
|
|
}
|
530
|
|
|
$operator = key($value);
|
531
|
|
|
}
|
532
|
2 |
|
return sprintf("`%s` %s", SafeString::makeSafe($field), Operators::getOperatorFormat($operator));
|
533
|
|
|
|
534
|
|
|
}
|
535
|
|
|
$this->values[] = $value;
|
536
|
|
|
return sprintf("`%s` = ?", SafeString::makeSafe($field));
|
537
|
|
|
}
|
538
|
|
|
|
539
|
|
|
/**
|
540
|
|
|
* Band values to use in the query
|
541
|
|
|
* @param array $values This should be the values being used in the query
|
542
|
|
|
*/
|
543
|
11 |
|
protected function bindValues($values) {
|
544
|
11 |
|
if(is_array($values)) {
|
545
|
11 |
|
foreach($values as $i => $value) {
|
546
|
11 |
|
if(is_numeric($value) && intval($value) == $value) {$type = PDO::PARAM_INT; $value = intval($value);}
|
547
|
11 |
|
elseif(is_null($value) || $value === 'NULL') {$type = PDO::PARAM_NULL; $value = NULL;}
|
548
|
11 |
|
elseif(is_bool($value)) {$type = PDO::PARAM_BOOL;}
|
549
|
11 |
|
else{$type = PDO::PARAM_STR;}
|
550
|
11 |
|
$this->query->bindValue(intval($i + 1), $value, $type);
|
551
|
|
|
}
|
552
|
|
|
}
|
553
|
11 |
|
}
|
554
|
|
|
}
|
555
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.