├── .travis.yml
├── tests
├── bootstrap.php
└── OneDBTest.php
├── phpunit_mysql.xml
├── LICENSE
├── README.md
└── src
└── OneDB.php
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.5
5 | - 5.4
6 |
7 | env:
8 | - DB=mysql
9 |
10 | before_script:
11 | - mysql -e 'create database onedb_test;'
12 |
13 | script: phpunit --configuration phpunit_mysql.xml --coverage-text --debug
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ./tests/
13 |
14 |
15 |
16 |
17 |
18 | ./
19 |
20 | ./tests
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Christoph von Gellhorn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tests/OneDBTest.php:
--------------------------------------------------------------------------------
1 | $GLOBALS['db_database'],
30 | 'user' => $GLOBALS['db_user'],
31 | 'password' => $GLOBALS['db_password']
32 | ));
33 |
34 | // Init test data and perform test on query method
35 | self::$_db->query(
36 | 'CREATE TABLE IF NOT EXISTS ' . self::$_table . ' ('
37 | . 'id INT(9) NOT NULL PRIMARY KEY AUTO_INCREMENT,'
38 | . 'name VARCHAR(50) NOT NULL,'
39 | . 'email VARCHAR(50) NOT NULL,'
40 | . 'tel VARCHAR(30) NOT NULL'
41 | . ') ENGINE = InnoDB'
42 | );
43 | }
44 |
45 | public static function tearDownAfterClass()
46 | {
47 | self::$_db->query('DROP TABLE IF EXISTS ' . self::$_table);
48 | }
49 |
50 | public function testGetPDO()
51 | {
52 | $this->assertInstanceOf('PDO', self::$_db->getPDO());
53 | }
54 |
55 | public function testQuote()
56 | {
57 | $this->assertEquals("'test'", self::$_db->quote('test'));
58 | }
59 |
60 | public function testBtick()
61 | {
62 | $this->assertEquals("`test`", self::$_db->btick('test'));
63 | }
64 |
65 | public function testInsert()
66 | {
67 | $aID = self::$_db->insert(self::$_table, array(
68 | 'name' => 'John Doe',
69 | 'email' => 'jd@jd.com',
70 | 'tel' => 55555555
71 | ));
72 |
73 | $this->assertTrue(is_int($aID) && $aID > 0);
74 |
75 | $bID = self::$_db->insert(self::$_table, array(
76 | 'name' => 'Skywalker',
77 | 'email' => 'sw@sw.com',
78 | 'tel' => 44444444
79 | ));
80 |
81 | $this->assertTrue(is_int($bID) && $bID > 0);
82 | }
83 |
84 | public function testMultiInsert()
85 | {
86 | self::$_db->multiInsert(self::$_table,
87 | array('name', 'email', 'tel'),
88 | array(
89 | array(
90 | 'John Doe',
91 | 'john@doe.com',
92 | 12345678
93 | ),
94 | array(
95 | 'John Smith',
96 | 'john@smith.com',
97 | 11223344
98 | ),
99 | array(
100 | 'Jack Smith',
101 | 'jack@smith.com',
102 | 87654321
103 | )
104 | )
105 | );
106 |
107 | $result = self::$_db->fetchRow(
108 | 'SELECT * FROM ' . self::$_table . ' WHERE tel = 87654321'
109 | );
110 |
111 | // Check if last value was inserted successfully
112 | $this->assertEquals('jack@smith.com', $result['email']);
113 | }
114 |
115 | public function testSave()
116 | {
117 | $testTel = '22222222';
118 |
119 | $tmpId = self::$_db->save(self::$_table, array(
120 | 'name' => 'Bill Gates',
121 | 'email' => 'bg@microsoft.com',
122 | 'tel' => '11111111'
123 | ));
124 |
125 | $id = self::$_db->save(self::$_table, array(
126 | 'id' => $tmpId,
127 | 'name' => 'Bill Gates',
128 | 'email' => 'bg@microsoft.com',
129 | 'tel' => $testTel
130 | ));
131 |
132 | $this->assertSame($tmpId, $id);
133 |
134 | $tel = self::$_db->fetchOne(
135 | 'SELECT tel FROM ' . self::$_table . ' WHERE id = ' . $tmpId
136 | );
137 |
138 | $this->assertEquals($tel, $testTel);
139 | }
140 |
141 | public function testUpdate()
142 | {
143 | $testName = 'Steve Jobs';
144 |
145 | self::$_db->update(
146 | self::$_table,
147 | array('name' => $testName),
148 | array('id = ?' => 1)
149 | );
150 |
151 | $result = self::$_db->fetchRow(
152 | 'SELECT * FROM ' . self::$_table . ' WHERE id = 1'
153 | );
154 |
155 | $this->assertEquals($testName, $result['name']);
156 | }
157 |
158 | public function testFetchAll()
159 | {
160 | $result = self::$_db->fetchAll(
161 | 'SELECT * FROM ' . self::$_table
162 | );
163 |
164 | $this->assertTrue(is_array($result[0]));
165 | $this->assertArrayHasKey('name', $result[0]);
166 | }
167 |
168 | public function testFetchAssoc()
169 | {
170 | $result = self::$_db->fetchAssoc(
171 | 'SELECT * FROM ' . self::$_table
172 | );
173 |
174 | $this->assertTrue(count($result) > 0);
175 |
176 | foreach ($result as $id => $row) {
177 | // Compare int with string
178 | $this->assertTrue($id == $row['id']);
179 | }
180 | }
181 |
182 | public function testFetchRow()
183 | {
184 | $result = self::$_db->fetchRow(
185 | 'SELECT * FROM ' . self::$_table . ' WHERE id = 1'
186 | );
187 |
188 | $this->assertArrayHasKey('name', $result);
189 | }
190 |
191 | public function testFetchOne()
192 | {
193 | $name = 'Steve Jobs';
194 |
195 | $result = self::$_db->fetchOne(
196 | 'SELECT name FROM ' . self::$_table . ' WHERE id = 1'
197 | );
198 |
199 | $this->assertEquals($name, $result);
200 | }
201 |
202 | public function testQuery()
203 | {
204 | $testName = 'Steve Jobs';
205 |
206 | // Perform tests on fetching modes
207 | $fetchAll = self::$_db->query(
208 | 'SELECT * FROM ' . self::$_table
209 | );
210 | $fetchRow = self::$_db->query(
211 | 'SELECT * FROM ' . self::$_table . ' WHERE id = 1'
212 | );
213 | $fetchOne = self::$_db->query(
214 | 'SELECT name FROM ' . self::$_table . ' WHERE id = 1'
215 | );
216 |
217 | $this->assertTrue(is_array($fetchAll[0]));
218 | $this->assertArrayHasKey('name', $fetchAll[0]);
219 | $this->assertEquals($testName, $fetchRow['name']);
220 | $this->assertEquals($testName, $fetchOne);
221 | }
222 |
223 | public function testDelete()
224 | {
225 | self::$_db->delete(
226 | self::$_table,
227 | array('name = ?' => 'Skywalker')
228 | );
229 |
230 | $result = self::$_db->fetchOne(
231 | 'SELECT name FROM ' . self::$_table . ' WHERE id = 2'
232 | );
233 |
234 | $this->assertNull($result);
235 | }
236 |
237 | public function testTruncte()
238 | {
239 | self::$_db->truncate(self::$_table);
240 |
241 | $result = self::$_db->fetchAll('SELECT * FROM ' . self::$_table);
242 | $this->assertEmpty($result);
243 | }
244 |
245 | public function testDescribe()
246 | {
247 | $result = self::$_db->describe(self::$_table);
248 |
249 | $realKeys = array('id', 'name', 'email', 'tel');
250 | $resultKeys = array_keys($result);
251 |
252 | $this->assertSame(
253 | array_diff($realKeys, $resultKeys),
254 | array_diff($resultKeys, $realKeys)
255 | );
256 | }
257 |
258 | public function testDrop()
259 | {
260 | self::$_db->drop(self::$_table);
261 | }
262 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | OneDB [](https://travis-ci.org/cvgellhorn/OneDB)
2 | ===========
3 |
4 | > A lightweight/single file PHP database framework
5 |
6 | ## Overview
7 | OneDB is using the PDO_MYSQL extension and is based on three classes:
8 |
9 | * OneDB - Main database framework
10 | * OneExpr - Database expression
11 | * OneException - Exception
12 |
13 | All tests are based on the [PHPUnit](http://phpunit.de/) testing framework. You can easily set up your own phpunit.xml, for local unit testing. It's also very lightweight, only around 13 kb and all packed in a single PHP file.
14 |
15 | ### Server Requirements:
16 |
17 | * PHP >= 5.4
18 | * PDO_MYSQL extension
19 |
20 | ## Getting started
21 | ```php
22 | // Include OneDB
23 | require_once 'OneDB.php';
24 |
25 | // Create OneDB instance and have fun
26 | $database = OneDB::load([
27 | 'database' => 'application',
28 | 'user' => 'root',
29 | 'password' => 'admin123#'
30 | ]);
31 |
32 | // After initializing, you can always get the current instance with
33 | $database = OneDB::load();
34 |
35 |
36 | // Or create a new connection by name (for multiple connections)
37 | $dbWrite = OneDB::getConnection('write', [
38 | 'database' => 'application',
39 | 'user' => 'root',
40 | 'password' => 'admin123#'
41 | ]);
42 |
43 | // Reload connection again later
44 | $dbWrite = OneDB::getConnection('write');
45 | ```
46 |
47 | ## Configuration
48 | You can also set the database host, port and charset.
49 | ```php
50 | $database = OneDB::load([
51 | 'host' => 'sql.mydomain.com',
52 | 'port' => '3307',
53 | 'charset' => 'utf16',
54 | 'database' => 'application',
55 | 'user' => 'root',
56 | 'password' => 'admin123#'
57 | ]);
58 | ```
59 |
60 | Default settings
61 | ```php
62 | 'host' => 'localhost'
63 | 'port' => '[default_mysql_port]'
64 | 'charset' => 'utf8'
65 | ```
66 |
67 | ## Basic Usage
68 | ### Insert
69 | Insert new records in table, returns LAST_INSERT_ID.
70 |
71 | ```php
72 | insert($table : string, $data : array)
73 | ```
74 |
75 | Example:
76 | ```php
77 | $lastInsertId = $database->insert('user', [
78 | 'name' => 'John Doe',
79 | 'email' => 'john@doe.com',
80 | 'tel' => 12345678
81 | ]);
82 | ```
83 |
84 | ### Update
85 | Edit data in table. You can use any given operator in the WHERE clause to filter the records. The ? represents the placeholder for the given param.
86 |
87 | ```php
88 | update($table : string, $data : array, [$where : array])
89 | ```
90 |
91 | Example:
92 | ```php
93 | $database->update('user',
94 | [
95 | 'name' => 'John Smith',
96 | 'email' => 'john@smith.com',
97 | 'tel' => 87654321
98 | ],
99 | [
100 | 'id = ?' => 23
101 | ]
102 | );
103 | ```
104 |
105 | ### Delete
106 | Remove data from table. Just as update, the ? represents the placeholder for the given param.
107 |
108 | ```php
109 | delete($table : string, [$where : array])
110 | ```
111 |
112 | Example:
113 | ```php
114 | $database->delete('user', [
115 | 'id = ?' => 23
116 | ]);
117 | ```
118 |
119 | ### Fetch All
120 | Retrieve all the rows of the result set in one step as an array.
121 | ```php
122 | fetchAll($sql : string)
123 | ```
124 |
125 | Example:
126 | ```php
127 | $database->fetchAll('SELECT * FROM `user`');
128 | ```
129 |
130 | ### Fetch Assoc
131 | Retrieve all the rows of the result set in one step as an array, using the first column or the given key as the array index.
132 | ```php
133 | fetchAssoc($sql : string, [$key : string])
134 | ```
135 |
136 | Example:
137 | ```php
138 | $database->fetchAssoc('SELECT * FROM `user`', 'username');
139 | ```
140 |
141 | ### Fetch Row
142 | Retrieve a single row of the result set as an array.
143 | ```php
144 | fetchRow($sql : string)
145 | ```
146 |
147 | Example:
148 | ```php
149 | $database->fetchRow('SELECT * FROM `user` WHERE `id` = 1');
150 | ```
151 |
152 | ### Fetch One
153 | Retrieve a single result value.
154 | ```php
155 | fetchOne($sql : string)
156 | ```
157 |
158 | Example:
159 | ```php
160 | $database->fetchOne('SELECT `username` FROM `user` WHERE `id` = 1');
161 | ```
162 |
163 | ### Query
164 | Send an SQL query. If there is a result, you will automatically get the matched result type: fetch all, fetch row or fetch one.
165 | ```php
166 | query($sql : string)
167 | ```
168 |
169 | Example:
170 | ```php
171 | $database->query('DELETE FROM `user` WHERE `id` = 1');
172 |
173 | // With result
174 | $result = $database->query('SELECT * FROM `user`');
175 | ```
176 |
177 | ### Last Insert ID
178 | Returns the ID of the last inserted row.
179 | ```php
180 | lastInsertId()
181 | ```
182 |
183 | Example:
184 | ```php
185 | $database->lastInsertId();
186 | ```
187 |
188 |
189 | ## Advanced Usage
190 | ### Expression
191 | You can also use database expressions in your statement, by using the OneExpr object.
192 | ```php
193 | $lastInsertId = $database->insert('user', [
194 | 'name' => 'John Doe',
195 | 'email' => 'john@doe.com',
196 | 'tel' => 12345678,
197 | 'created' => new OneExpr('NOW()')
198 | ]);
199 | ```
200 |
201 | ### Truncate
202 | Truncate database table.
203 | ```php
204 | truncate($table : string)
205 | ```
206 |
207 | Example:
208 | ```php
209 | $database->truncate('user');
210 | ```
211 |
212 | ### Drop
213 | Drop database table.
214 | ```php
215 | drop($table : string)
216 | ```
217 |
218 | Example:
219 | ```php
220 | $database->drop('user');
221 | ```
222 |
223 | ### Describe
224 | Describe database table, returns the table attributes as array keys.
225 | ```php
226 | describe($table : string)
227 | ```
228 |
229 | Example:
230 | ```php
231 | $database->describe('user');
232 | ```
233 |
234 | ### Transaction
235 | Run a database transaction.
236 | ```php
237 | try {
238 | // Start transaction
239 | $database->beginTransaction();
240 |
241 | // Do stuff
242 | $database->insert('user', [
243 | 'name' => 'Skywalker'
244 | ]);
245 | $database->delete('user', [
246 | 'id = ?' => 3
247 | ]);
248 |
249 | // Check transaction status, returns bool
250 | $status = $database->inTransaction();
251 |
252 | // Commit transaction if no error occurred
253 | $database->commit();
254 | } catch (OneException $e) {
255 | // Rollback on error
256 | $database->rollBack();
257 | }
258 | ```
259 |
260 | ### Quote
261 | Add quotes to the given value.
262 | ```php
263 | quote($val : string)
264 | ```
265 |
266 | Example:
267 | ```php
268 | $database->quote($value);
269 | ```
270 |
271 | ### Backtick
272 | Add backticks to the given field name.
273 | ```php
274 | btick($val : string)
275 | ```
276 |
277 | Example:
278 | ```php
279 | $database->btick('user');
280 | ```
281 |
282 | ### PDO
283 | Returns the current PDO object.
284 | ```php
285 | getPDO()
286 | ```
287 |
288 | Example:
289 | ```php
290 | $database->getPDO();
291 | ```
292 |
293 |
294 | ## Special Usage
295 | ### Multi Insert
296 | Insert multiple records into database table.
297 | ```php
298 | multiInsert($table : string, $keys : array, $data : array)
299 | ```
300 |
301 | Example:
302 | ```php
303 | $database->multiInsert('user',
304 | ['name', 'email', 'tel'],
305 | [
306 | [
307 | 'John Doe',
308 | 'john@doe.com',
309 | 12345678
310 | ],
311 | [
312 | 'John Smith',
313 | 'john@smith.com',
314 | 11223344
315 | ),
316 | [
317 | 'Jack Smith',
318 | 'jack@smith.com',
319 | 87654321
320 | ]
321 | ]
322 | );
323 | ```
324 |
325 | ### Save
326 | Update data if exist, otherwise insert new data. Using the ON DUPLICATE KEY UPDATE expression. Returns the ID of the last inserted or updated row.
327 | ```php
328 | save($table : string, $data : array)
329 | ```
330 | Example:
331 | ```php
332 | $id = $database->save('user', [
333 | 'id' => 1,
334 | 'name' => 'John Doe',
335 | 'email' => 'john@doe.com',
336 | 'tel' => 12345678
337 | ]);
338 | ```
339 |
340 |
341 | ## Debug
342 | You can activate the debug mode by using the following statement. It will show you all executed SQL queries and the parameter bindings.
343 | ```php
344 | $database->debug();
345 | ```
346 |
347 | It's also possible to change the debug style with the debugStyle attribute.
348 | ```php
349 | $database->debugStyle = [
350 | 'border: 2px solid #d35400',
351 | 'border-radius: 3px',
352 | 'background-color: #e67e22',
353 | 'margin: 5px 0 5px 0',
354 | 'color: #ffffff',
355 | 'padding: 5px'
356 | ];
357 | ```
358 |
--------------------------------------------------------------------------------
/src/OneDB.php:
--------------------------------------------------------------------------------
1 | 'mysql',
52 | 'host' => 'localhost',
53 | 'charset' => 'utf8',
54 | 'database' => null,
55 | 'user' => null,
56 | 'password' => null
57 | ];
58 |
59 | /**
60 | * Debug style
61 | *
62 | * @var array
63 | */
64 | public $debugStyle = [
65 | 'border: 2px solid #d35400',
66 | 'border-radius: 3px',
67 | 'background-color: #e67e22',
68 | 'margin: 5px 0 5px 0',
69 | 'color: #ffffff',
70 | 'padding: 5px'
71 | ];
72 |
73 | /**
74 | * Single pattern implementation
75 | *
76 | * @param array $config Connection configs
77 | * @return OneDB
78 | */
79 | public static function load($config = [])
80 | {
81 | if (null === self::$_instance) {
82 | self::$_instance = self::_create($config);
83 | }
84 | return self::$_instance;
85 | }
86 |
87 | /**
88 | * Handle database connections
89 | *
90 | * @param string $name Connection name
91 | * @param array $config Connection configs
92 | * @return OneDB
93 | */
94 | public static function getConnection($name = null, $config = [])
95 | {
96 | if (null === $name) {
97 | return self::_create($config);
98 | } else {
99 | if (!isset(self::$_connections[$name])) {
100 | self::$_connections[$name] = self::_create($config);
101 | }
102 | return self::$_connections[$name];
103 | }
104 | }
105 |
106 | /**
107 | * Create new OneDB connection
108 | *
109 | * @param array $config Connection configs
110 | * @return OneDB
111 | * @throws OneException
112 | */
113 | protected static function _create($config)
114 | {
115 | if (!empty($config)) {
116 | return new self($config);
117 | } else {
118 | throw new OneException('OneDB configuration is not set');
119 | }
120 | }
121 |
122 | /**
123 | * Create DB object and connect to database
124 | *
125 | * @throws OneException
126 | */
127 | protected function __construct($config)
128 | {
129 | try {
130 | if (!extension_loaded('pdo_mysql')) {
131 | throw new OneException('pdo_mysql extension is not installed');
132 | }
133 |
134 | // Prepare database configuration
135 | $config = $this->_prepareConfig($config);
136 |
137 | $this->_pdo = new PDO(
138 | $config['pdo_type'] . ':' . $config['dsn'],
139 | $config['user'],
140 | $config['password']
141 | );
142 |
143 | // Always use exceptions
144 | $this->_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
145 |
146 | // Set character encoding
147 | $this->_pdo->exec('SET CHARACTER SET ' . $config['charset']);
148 | } catch (PDOException $e) {
149 | throw new OneException($e->getMessage());
150 | }
151 | }
152 |
153 | /**
154 | * Prepare database configuration
155 | *
156 | * @param array $config Connection configs
157 | * @return array Matched connection configs
158 | * @throws OneException
159 | */
160 | protected function _prepareConfig($config)
161 | {
162 | $config = array_merge($this->_config, $config);
163 | foreach ($config as $key => $val) {
164 | if (null === $val) {
165 | throw new OneException('Could not connect to database, missing parameter: ' . $key);
166 | }
167 | }
168 |
169 | $dsn = [
170 | 'host=' . $config['host'],
171 | 'dbname=' . $config['database'],
172 | 'charset=' . $config['charset']
173 | ];
174 |
175 | if (isset($config['port'])) {
176 | $dsn[] = 'port=' . $config['port'];
177 | }
178 |
179 | $config['dsn'] = implode(';', $dsn);
180 | return $config;
181 | }
182 |
183 | /**
184 | * Prepare SQL statement for executing
185 | *
186 | * @param string $sql SQL statement
187 | * @return OneDB
188 | */
189 | protected function _prepare($sql)
190 | {
191 | $this->_stmt = $this->_pdo->prepare($sql);
192 | return $this;
193 | }
194 |
195 | /**
196 | * Build where clause
197 | *
198 | * @param array $where Where conditions
199 | * @param string $query Query string
200 | */
201 | protected function _buildWhere(&$where, &$query)
202 | {
203 | if (!empty($where)) {
204 | $expr = [];
205 | foreach ($where as $key => $val) {
206 | if ($val instanceof OneExpr) {
207 | $expr[] = str_replace('?', $val, $key);
208 | unset($where[$key]);
209 | }
210 | }
211 | $query .= ' WHERE ' . implode(' AND ', array_keys($where))
212 | . ((!empty($expr)) ? ' AND ' . implode(' AND ', $expr) : '');
213 | }
214 | }
215 |
216 | /**
217 | * Bind SQL query params to PDO statement object
218 | *
219 | * @param array $data SQL query params
220 | * @return OneDB
221 | */
222 | protected function _bindParams($data)
223 | {
224 | if ($this->_debugMode) $this->dump(print_r($data, true));
225 |
226 | $count = count($data);
227 | for ($i = 0; $i < $count; $i++) {
228 | $this->_stmt->bindParam($i + 1, $data[$i]);
229 | }
230 |
231 | return $this;
232 | }
233 |
234 | /**
235 | * Execute SQL statement
236 | *
237 | * @return PDOStatement
238 | * @throws OneException
239 | */
240 | protected function _execute()
241 | {
242 | try {
243 | if ($this->_debugMode) $this->dump($this->_stmt->queryString);
244 | $this->_stmt->execute();
245 | } catch (PDOException $e) {
246 | throw new OneException('PDO Mysql execution error: ' . $e->getMessage());
247 | }
248 |
249 | return $this->_stmt;
250 | }
251 |
252 | /**
253 | * Get the current PDO object
254 | *
255 | * @return PDO
256 | */
257 | public function getPDO()
258 | {
259 | return $this->_pdo;
260 | }
261 |
262 | /**
263 | * Return given value with quotes
264 | *
265 | * @param string $val Value
266 | * @return string Value with quotes
267 | */
268 | public function quote($val)
269 | {
270 | return "'$val'";
271 | }
272 |
273 | /**
274 | * Return given value with backticks
275 | *
276 | * @param string $val Value
277 | * @return string Value with backticks
278 | */
279 | public function btick($val)
280 | {
281 | return "`$val`";
282 | }
283 |
284 | /**
285 | * Set debug mode
286 | *
287 | * @param bool $status Debug mode status
288 | * @return $this
289 | */
290 | public function debug($status = true)
291 | {
292 | $this->_debugMode = $status;
293 | return $this;
294 | }
295 |
296 | /**
297 | * Debug dump
298 | *
299 | * @param mixed $val Value to dump
300 | */
301 | public function dump($val)
302 | {
303 | echo '
';
304 | }
305 |
306 | /**
307 | * Initiates a transaction
308 | *
309 | * @return bool TRUE on success or FALSE on failure
310 | */
311 | public function beginTransaction()
312 | {
313 | return $this->_pdo->beginTransaction();
314 | }
315 |
316 | /**
317 | * Commits a transaction
318 | *
319 | * @return bool TRUE on success or FALSE on failure
320 | */
321 | public function commit()
322 | {
323 | return $this->_pdo->commit();
324 | }
325 |
326 | /**
327 | * Rolls back a transaction
328 | *
329 | * @return bool TRUE on success or FALSE on failure
330 | */
331 | public function rollBack()
332 | {
333 | return $this->_pdo->rollBack();
334 | }
335 |
336 | /**
337 | * Checks if inside a transaction
338 | *
339 | * @return bool TRUE on success or FALSE on failure
340 | */
341 | public function inTransaction()
342 | {
343 | return $this->_pdo->inTransaction();
344 | }
345 |
346 | /**
347 | * Get last insert ID
348 | *
349 | * @return int Last insert ID
350 | */
351 | public function lastInsertId()
352 | {
353 | return (int) $this->_pdo->lastInsertId();
354 | }
355 |
356 | /**
357 | * Fetch all data by SQL statement
358 | *
359 | * @param string $sql SQL statement
360 | * @return array SQL result
361 | */
362 | public function fetchAll($sql)
363 | {
364 | return $this->_prepare($sql)->_execute()->fetchAll(PDO::FETCH_ASSOC);
365 | }
366 |
367 | /**
368 | * Fetch all data by SQL statement and merge by field
369 | *
370 | * @param string $sql SQL statement
371 | * @param string $key Optional | array key
372 | * @return array SQL result
373 | */
374 | public function fetchAssoc($sql, $key = null)
375 | {
376 | // Raw result data
377 | $data = $this->_prepare($sql)->_execute()->fetchAll(PDO::FETCH_ASSOC);
378 |
379 | $result = [];
380 | if (!empty($data)) {
381 | $key = ($key && isset($data[0][$key])) ? $key : key($data[0]);
382 | foreach ($data as $d) {
383 | $result[$d[$key]] = $d;
384 | }
385 | }
386 |
387 | return $result;
388 | }
389 |
390 | /**
391 | * Fetch row by SQL statement
392 | *
393 | * @param string $sql SQL statement
394 | * @return array SQL result
395 | */
396 | public function fetchRow($sql)
397 | {
398 | return $this->_prepare($sql)->_execute()->fetch(PDO::FETCH_ASSOC);
399 | }
400 |
401 | /**
402 | * Fetch single value by SQL statement
403 | *
404 | * @param string $sql SQL statement
405 | * @return mixed Result value
406 | */
407 | public function fetchOne($sql)
408 | {
409 | $result = $this->_prepare($sql)->_execute()->fetch(PDO::FETCH_NUM);
410 | return isset($result[0]) ? $result[0] : null;
411 | }
412 |
413 | /**
414 | * Executes an SQL statement
415 | *
416 | * @param string $sql SQL statement
417 | * @return array|bool|mixed|null SQL result
418 | * @throws OneException
419 | */
420 | public function query($sql)
421 | {
422 | try {
423 | /*** @var $result PDOStatement */
424 | $result = $this->_pdo->query($sql);
425 | } catch (PDOException $e) {
426 | throw new OneException('PDO Mysql statement error: ' . $e->getMessage());
427 | }
428 |
429 | $columnCount = $result->columnCount();
430 | $rowCount = $result->rowCount();
431 |
432 | // If statment is as SELECT statement
433 | if ($columnCount > 0) {
434 | // Equal to fetchOne
435 | if ($columnCount === 1 && $rowCount === 1) {
436 | $res = $result->fetch(PDO::FETCH_NUM);
437 | return isset($res[0]) ? $res[0] : null;
438 |
439 | // Equal to fetchRow
440 | } else if ($columnCount > 1 && $rowCount === 1) {
441 | return $result->fetch(PDO::FETCH_ASSOC);
442 |
443 | // Equal to fetchAll
444 | } else {
445 | return $result->fetchAll(PDO::FETCH_ASSOC);
446 | }
447 | } else {
448 | // No result
449 | return true;
450 | }
451 | }
452 |
453 | /**
454 | * Insert given data into database
455 | *
456 | * @param string $table DB table name
457 | * @param array $data Data to insert
458 | * @return int Last insert ID
459 | */
460 | public function insert($table, $data)
461 | {
462 | $keys = [];
463 | $values = [];
464 | foreach ($data as $key => $val) {
465 | $keys[] = $this->btick($key);
466 | if ($val instanceof OneExpr) {
467 | $values[] = $val;
468 | unset($data[$key]);
469 | } else {
470 | $values[] = '?';
471 | }
472 | }
473 |
474 | $query = 'INSERT INTO ' . $this->btick($table)
475 | . ' (' . implode(', ', $keys) . ')'
476 | . ' VALUES (' . implode(', ', $values) . ')';
477 |
478 | $this->_prepare($query)->_bindParams(array_values($data))->_execute();
479 | return $this->lastInsertId();
480 | }
481 |
482 | /**
483 | * Do a multi insert
484 | *
485 | * @param string $table DB table name
486 | * @param array $keys DB table columns
487 | * @param array $data Data to insert
488 | */
489 | public function multiInsert($table, $keys, $data)
490 | {
491 | foreach ($keys as &$key) {
492 | $key = $this->btick($key);
493 | }
494 |
495 | $values = [];
496 | foreach ($data as $vals) {
497 | foreach ($vals as &$val) {
498 | $val = $this->quote($val);
499 | }
500 | $values[] = '(' . implode(',', $vals) . ')';
501 | }
502 |
503 | $query = 'INSERT INTO ' . $this->btick($table)
504 | . ' (' . implode(',', $keys) . ')'
505 | . ' VALUES ' . implode(',', $values);
506 |
507 | $this->_prepare($query)->_execute();
508 | }
509 |
510 | /**
511 | * Update data if exist, otherwise insert new data
512 | *
513 | * @param string $table DB table name
514 | * @param array $data Data to insert or update
515 | * @return int ID of the last inserted or updated row
516 | */
517 | public function save($table, $data)
518 | {
519 | $keys = [];
520 | $values = [];
521 | $updateVals = [];
522 |
523 | foreach ($data as $key => $val) {
524 | $keys[] = $field = $this->btick($key);
525 | if ($val instanceof OneExpr) {
526 | $values[] = $val;
527 | $updateVals[] = $field . '=' . $val;
528 | unset($data[$key]);
529 | } else {
530 | $values[] = '?';
531 | $updateVals[] = $field . '=?';
532 | }
533 | }
534 |
535 | $query = 'INSERT INTO ' . $this->btick($table)
536 | . ' (' . implode(', ', $keys) . ')'
537 | . ' VALUES (' . implode(', ', $values) . ')'
538 | . ' ON DUPLICATE KEY UPDATE ' . implode(',', $updateVals);
539 |
540 | $vals = array_values($data);
541 | $this->_prepare($query)->_bindParams(array_merge($vals, $vals))->_execute();
542 |
543 | return $this->lastInsertId();
544 | }
545 |
546 | /**
547 | * Update data by given condition
548 | *
549 | * @param string $table DB table name
550 | * @param array $data Data to update
551 | * @param array $where Update condition
552 | */
553 | public function update($table, $data, $where = [])
554 | {
555 | $values = [];
556 | foreach ($data as $key => $val) {
557 | if ($val instanceof OneExpr) {
558 | $values[] = $this->btick($key) . ' = ' . $val;
559 | unset($data[$key]);
560 | } else {
561 | $values[] = $this->btick($key) . ' = ?';
562 | }
563 | }
564 |
565 | $query = 'UPDATE ' . $this->btick($table) . ' SET ' . implode(', ', $values);
566 | $this->_buildWhere($where, $query);
567 |
568 | $params = array_merge(
569 | array_values($data),
570 | array_values($where)
571 | );
572 |
573 | $this->_prepare($query)->_bindParams($params)->_execute();
574 | }
575 |
576 | /**
577 | * Delete from database table
578 | *
579 | * @param string $table DB table name
580 | * @param array $where Delete condition
581 | */
582 | public function delete($table, $where = [])
583 | {
584 | $query = 'DELETE FROM ' . $this->btick($table);
585 | $this->_buildWhere($where, $query);
586 |
587 | $this->_prepare($query);
588 | if (!empty($where)) {
589 | $this->_bindParams(array_values($where));
590 | }
591 |
592 | $this->_execute();
593 | }
594 |
595 | /**
596 | * Truncate database table
597 | *
598 | * @param string $table DB table name
599 | */
600 | public function truncate($table)
601 | {
602 | $this->_prepare('TRUNCATE TABLE ' . $this->btick($table))->_execute();
603 | }
604 |
605 | /**
606 | * Drop database table
607 | *
608 | * @param string $table DB table name
609 | */
610 | public function drop($table)
611 | {
612 | $this->_prepare('DROP TABLE ' . $this->btick($table))->_execute();
613 | }
614 |
615 | /**
616 | * Describe database table
617 | *
618 | * @param string $table DB table name
619 | * @return array Table structure
620 | */
621 | public function describe($table)
622 | {
623 | return $this->fetchAssoc('DESCRIBE ' . $this->btick($table));
624 | }
625 | }
626 |
627 |
628 | /**
629 | * OneDB database expression
630 | */
631 | class OneExpr
632 | {
633 | /**
634 | * @var string Database expression
635 | */
636 | public $expr;
637 |
638 | /**
639 | * Expression constructor
640 | *
641 | * @param string $expr Database expression
642 | */
643 | public function __construct($expr)
644 | {
645 | $this->expr = $expr;
646 | }
647 |
648 | /**
649 | * Magic to string method
650 | *
651 | * @return string Database expression
652 | */
653 | public function __toString()
654 | {
655 | return $this->expr;
656 | }
657 | }
658 |
659 |
660 | /**
661 | * OneDB Exception class
662 | */
663 | class OneException extends Exception
664 | {}
--------------------------------------------------------------------------------