Overview

Namespaces

  • Kotchasan
    • Cache
    • Database
    • Http
    • Log
    • Orm
  • None
  • PHP
  • Psr
    • Cache
    • Http
      • Message
    • Log

Classes

  • ArrayIterator
  • DateInterval
  • DOMNode
  • Kotchasan
  • Kotchasan\Accordion
  • Kotchasan\ApiController
  • Kotchasan\ArrayTool
  • Kotchasan\Cache\ApcCache
  • Kotchasan\Cache\Cache
  • Kotchasan\Cache\CacheItem
  • Kotchasan\Cache\FileCache
  • Kotchasan\CKEditor
  • Kotchasan\Collection
  • Kotchasan\Config
  • Kotchasan\Controller
  • Kotchasan\Country
  • Kotchasan\Csv
  • Kotchasan\Curl
  • Kotchasan\Currency
  • Kotchasan\Database
  • Kotchasan\Database\Db
  • Kotchasan\Database\DbCache
  • Kotchasan\Database\Driver
  • Kotchasan\Database\PdoMysqlDriver
  • Kotchasan\Database\Query
  • Kotchasan\Database\QueryBuilder
  • Kotchasan\Database\Schema
  • Kotchasan\Database\Sql
  • Kotchasan\DataTable
  • Kotchasan\Date
  • Kotchasan\DOMNode
  • Kotchasan\DOMParser
  • Kotchasan\Email
  • Kotchasan\File
  • Kotchasan\Files
  • Kotchasan\Form
  • Kotchasan\Grid
  • Kotchasan\Html
  • Kotchasan\Htmldoc
  • Kotchasan\HtmlTable
  • Kotchasan\Http\AbstractMessage
  • Kotchasan\Http\AbstractRequest
  • Kotchasan\Http\Message
  • Kotchasan\Http\NotFound
  • Kotchasan\Http\Request
  • Kotchasan\Http\Response
  • Kotchasan\Http\Stream
  • Kotchasan\Http\UploadedFile
  • Kotchasan\Http\Uri
  • Kotchasan\Image
  • Kotchasan\InputItem
  • Kotchasan\Inputs
  • Kotchasan\KBase
  • Kotchasan\Language
  • Kotchasan\ListItem
  • Kotchasan\Log\AbstractLogger
  • Kotchasan\Log\Logger
  • Kotchasan\Login
  • Kotchasan\Menu
  • Kotchasan\Mime
  • Kotchasan\Model
  • Kotchasan\Number
  • Kotchasan\ObjectTool
  • Kotchasan\Orm\Field
  • Kotchasan\Orm\Recordset
  • Kotchasan\Password
  • Kotchasan\Pdf
  • Kotchasan\Province
  • Kotchasan\Router
  • Kotchasan\Session
  • Kotchasan\Singleton
  • Kotchasan\Tab
  • Kotchasan\TableRow
  • Kotchasan\Template
  • Kotchasan\Text
  • Kotchasan\Validator
  • Kotchasan\View
  • PHPMailer
  • Psr\Log\AbstractLogger
  • Psr\Log\LogLevel
  • Psr\Log\NullLogger
  • SMTP

Interfaces

  • ArrayAccess
  • Countable
  • DateTimeInterface
  • Iterator
  • IteratorAggregate
  • Psr\Cache\CacheItemInterface
  • Psr\Cache\CacheItemPoolInterface
  • Psr\Http\Message\MessageInterface
  • Psr\Http\Message\RequestInterface
  • Psr\Http\Message\ResponseInterface
  • Psr\Http\Message\ServerRequestInterface
  • Psr\Http\Message\StreamInterface
  • Psr\Http\Message\UploadedFileInterface
  • Psr\Http\Message\UriInterface
  • Psr\Log\LoggerAwareInterface
  • Psr\Log\LoggerInterface
  • SeekableIterator
  • Serializable
  • Traversable

Traits

  • Psr\Log\LoggerTrait

Exceptions

  • Exception
  • InvalidArgumentException
  • Kotchasan\ApiException
  • Kotchasan\Cache\Exception
  • Kotchasan\Database\Exception
  • Kotchasan\InputItemException
  • LogicException
  • phpmailerException
  • RuntimeException

Functions

  • createClass
  • debug
  • getClassPath
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * @filesource Kotchasan/Database/PdoMysqlDriver.php
  4:  *
  5:  * @copyright 2016 Goragod.com
  6:  * @license http://www.kotchasan.com/license/
  7:  *
  8:  * @see http://www.kotchasan.com/
  9:  */
 10: 
 11: namespace Kotchasan\Database;
 12: 
 13: use PDO;
 14: 
 15: /**
 16:  * PDO MySQL Database Adapter Class
 17:  *
 18:  * @author Goragod Wiriya <admin@goragod.com>
 19:  *
 20:  * @since 1.0
 21:  */
 22: class PdoMysqlDriver extends Driver
 23: {
 24:     /**
 25:      * close database
 26:      */
 27:     public function close()
 28:     {
 29:         $this->connection = null;
 30:     }
 31: 
 32:     /**
 33:      * เชื่อมต่อ database
 34:      *
 35:      * @param array $param
 36:      *
 37:      * @return \static
 38:      */
 39:     public function connect($param)
 40:     {
 41:         $this->options = array(
 42:             \PDO::ATTR_STRINGIFY_FETCHES => 0,
 43:             \PDO::ATTR_EMULATE_PREPARES => 0,
 44:             \PDO::ATTR_PERSISTENT => 1,
 45:             \PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
 46:         );
 47:         foreach ($param as $key => $value) {
 48:             $this->{$key} = $value;
 49:         }
 50:         if ($this->settings->dbdriver == 'mysql') {
 51:             $this->options[\PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->settings->char_set;
 52:             $this->options[\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY] = 1;
 53:         }
 54:         $sql = $this->settings->dbdriver.':host='.$this->settings->hostname;
 55:         $sql .= empty($this->settings->port) ? '' : ';port='.$this->settings->port;
 56:         $sql .= empty($this->settings->dbname) ? '' : ';dbname='.$this->settings->dbname;
 57:         if (isset($this->settings->username) && isset($this->settings->password)) {
 58:             try {
 59:                 $this->connection = new \PDO($sql, $this->settings->username, $this->settings->password, $this->options);
 60:                 if (defined('SQL_MODE')) {
 61:                     $this->connection->query("SET SESSION sql_mode='".SQL_MODE."'");
 62:                 }
 63:             } catch (\PDOException $e) {
 64:                 throw new \Exception($e->getMessage(), 500, $e);
 65:             }
 66:         } else {
 67:             throw new \InvalidArgumentException('Database configuration is invalid');
 68:         }
 69:         return $this;
 70:     }
 71: 
 72:     /**
 73:      * จำนวนฟิลด์ทั้งหมดในผลลัพท์จากการ query
 74:      *
 75:      * @param resource $res ผลลัพท์จากการ query
 76:      */
 77:     public function fieldCount()
 78:     {
 79:         if (isset($this->result_id)) {
 80:             return $this->result_id->columnCount();
 81:         } else {
 82:             return 0;
 83:         }
 84:     }
 85: 
 86:     /**
 87:      * รายชื่อฟิลด์ทั้งหมดจากผลัพท์จองการ query
 88:      *
 89:      * @return array
 90:      */
 91:     public function getFields()
 92:     {
 93:         $filed_list = array();
 94:         for ($i = 0, $c = $this->fieldCount(); $i < $c; ++$i) {
 95:             $result = @$this->result_id->getColumnMeta($i);
 96:             if ($result) {
 97:                 $filed_list[$result['name']] = $result;
 98:             }
 99:         }
100:         return $filed_list;
101:     }
102: 
103:     /**
104:      * ฟังก์ชั่นเพิ่มข้อมูลใหม่ลงในตาราง
105:      * สำเร็จ คืนค่า id ที่เพิ่ม ผิดพลาด คืนค่า null
106:      *
107:      * @param string       $table_name ชื่อตาราง
108:      * @param array|object $save       ข้อมูลที่ต้องการบันทึก รูปแบบ array('key1'=>'value1', 'key2'=>'value2', ...)
109:      *
110:      * @return int|null
111:      */
112:     public function insert($table_name, $save)
113:     {
114:         $params = array();
115:         $sql = $this->makeInsert($table_name, $save, $params);
116:         try {
117:             $query = $this->connection->prepare($sql);
118:             $query->execute($params);
119:             $this->log('insert', $sql, $params);
120:             ++self::$query_count;
121:             return (int) $this->connection->lastInsertId();
122:         } catch (\PDOException $e) {
123:             throw new \Exception($e->getMessage(), 500, $e);
124:         }
125:     }
126: 
127:     /**
128:      * ฟังก์ชั่นเพิ่มข้อมูลใหม่ลงในตาราง
129:      * ถ้ามีข้อมูลเดิมอยู่แล้วจะเป็นการอัปเดต
130:      * (ข้อมูลเดิมตาม KEY ที่เป็น UNIQUE)
131:      * insert คืนค่า id ที่เพิ่ม
132:      * update คืนค่า 0
133:      * ผิดพลาด คืนค่า null
134:      *
135:      * @param string       $table_name ชื่อตาราง
136:      * @param array|object $save       ข้อมูลที่ต้องการบันทึก รูปแบบ array('key1'=>'value1', 'key2'=>'value2', ...)
137:      *
138:      * @return int|null
139:      */
140:     public function insertOrUpdate($table_name, $save)
141:     {
142:         $updates = array();
143:         $params = array();
144:         foreach ($save as $key => $value) {
145:             $updates[] = '`'.$key.'`=:U'.$key;
146:             $params[':U'.$key] = $value;
147:         }
148:         $sql = $this->makeInsert($table_name, $save, $params);
149:         $sql .= ' ON DUPLICATE KEY UPDATE '.implode(', ', $updates);
150:         try {
151:             $query = $this->connection->prepare($sql);
152:             $query->execute($params);
153:             $this->log(__FUNCTION__, $sql);
154:             ++self::$query_count;
155: 
156:             return (int) $this->connection->lastInsertId();
157:         } catch (\PDOException $e) {
158:             throw new \Exception($e->getMessage(), 500, $e);
159:         }
160:     }
161: 
162:     /**
163:      * ฟังก์ชั่นสร้างคำสั่ง sql query
164:      * คืนค่า sql command
165:      *
166:      * @assert (array('update' => '`user`', 'where' => '`id` = 1', 'set' => array('`id` = 1', "`email` = 'admin@localhost'"))) [==] "UPDATE `user` SET `id` = 1, `email` = 'admin@localhost' WHERE `id` = 1"
167:      * @assert (array('insert' => '`user`', 'keys' => array('id' => ':id', 'email' => ':email'))) [==] "INSERT INTO `user` (`id`, `email`) VALUES (:id, :email)"
168:      * @assert (array('insert' => '`user`', 'keys' => array('id' => ':id'), 'orupdate' => array('`id`=VALUES(`id`)'))) [==] "INSERT INTO `user` (`id`) VALUES (:id) ON DUPLICATE KEY UPDATE `id`=VALUES(`id`)"
169:      * @assert (array('select'=>'*', 'from'=>'`user`','where'=>'`id` = 1', 'order' => '`id`', 'start' => 1, 'limit' => 10, 'join' => array(" INNER JOIN ..."))) [==] "SELECT * FROM `user` INNER JOIN ... WHERE `id` = 1 ORDER BY `id` LIMIT 1,10"
170:      * @assert (array('select'=>'*', 'from'=>'`user`','where'=>'`id` = 1', 'order' => '`id`', 'start' => 1, 'limit' => 10, 'group' => '`id`')) [==] "SELECT * FROM `user` WHERE `id` = 1 GROUP BY `id` ORDER BY `id` LIMIT 1,10"
171:      * @assert (array('delete' => '`user`', 'where' => '`id` = 1')) [==] "DELETE FROM `user` WHERE `id` = 1"
172:      *
173:      * @param array $sqls คำสั่ง sql จาก query builder
174:      *
175:      * @return string
176:      */
177:     public function makeQuery($sqls)
178:     {
179:         $sql = '';
180:         if (!empty($sqls['explain'])) {
181:             $sql = 'EXPLAIN ';
182:         }
183:         if (isset($sqls['insert'])) {
184:             $keys = array_keys($sqls['keys']);
185:             $sql .= 'INSERT INTO '.$sqls['insert'].' (`'.implode('`, `', $keys);
186:             $sql .= '`) VALUES ('.implode(', ', $sqls['keys']).')';
187:             if (isset($sqls['orupdate'])) {
188:                 $sql .= ' ON DUPLICATE KEY UPDATE '.implode(', ', $sqls['orupdate']);
189:             }
190:         } else {
191:             if (isset($sqls['union'])) {
192:                 if (isset($sqls['select'])) {
193:                     $sql .= 'SELECT '.$sqls['select'].' FROM (('.implode(') UNION (', $sqls['union']).')) AS U9';
194:                 } else {
195:                     $sql .= '('.implode(') UNION (', $sqls['union']).')';
196:                 }
197:             } elseif (isset($sqls['unionAll'])) {
198:                 if (isset($sqls['select'])) {
199:                     $sql .= 'SELECT '.$sqls['select'].' FROM (('.implode(') UNION ALL (', $sqls['unionAll']).')) AS U9';
200:                 } else {
201:                     $sql .= '('.implode(') UNION ALL (', $sqls['unionAll']).')';
202:                 }
203:             } else {
204:                 if (isset($sqls['select'])) {
205:                     $sql .= 'SELECT '.$sqls['select'];
206:                     if (isset($sqls['from'])) {
207:                         $sql .= ' FROM '.$sqls['from'];
208:                     }
209:                 } elseif (isset($sqls['update'])) {
210:                     $sql .= 'UPDATE '.$sqls['update'];
211:                 } elseif (isset($sqls['delete'])) {
212:                     $sql .= 'DELETE FROM '.$sqls['delete'];
213:                 }
214:             }
215:             if (isset($sqls['join'])) {
216:                 foreach ($sqls['join'] as $join) {
217:                     $sql .= $join;
218:                 }
219:             }
220:             if (isset($sqls['set'])) {
221:                 $sql .= ' SET '.implode(', ', $sqls['set']);
222:             }
223:             if (isset($sqls['where'])) {
224:                 $sql .= ' WHERE '.$sqls['where'];
225:             }
226:             if (isset($sqls['group'])) {
227:                 $sql .= ' GROUP BY '.$sqls['group'];
228:             }
229:             if (isset($sqls['having'])) {
230:                 $sql .= ' HAVING '.$sqls['having'];
231:             }
232:             if (isset($sqls['order'])) {
233:                 $sql .= ' ORDER BY '.$sqls['order'];
234:             }
235:             if (isset($sqls['limit'])) {
236:                 $sql .= ' LIMIT '.(empty($sqls['start']) ? '' : $sqls['start'].',').$sqls['limit'];
237:             }
238:         }
239:         return $sql;
240:     }
241: 
242:     /**
243:      * เรียกดูข้อมูล
244:      * คืนค่าผลลัพท์ในรูป array ถ้าไม่สำเร็จ คืนค่าแอเรย์ว่าง
245:      *
246:      * @param string $table_name ชื่อตาราง
247:      * @param mixed  $condition  query WHERE
248:      * @param array  $sort       เรียงลำดับ
249:      * @param int    $limit      จำนวนข้อมูลที่ต้องการ
250:      *
251:      * @return array
252:      */
253:     public function select($table_name, $condition, $sort = array(), $limit = 0)
254:     {
255:         $values = array();
256:         $condition = $this->buildWhere($condition);
257:         if (is_array($condition)) {
258:             $values = $condition[1];
259:             $condition = $condition[0];
260:         }
261:         $sql = 'SELECT * FROM '.$table_name.' WHERE '.$condition;
262:         if (!empty($sort)) {
263:             if (is_string($sort) && preg_match('/^([a-z0-9_]+)\s(asc|desc)$/i', trim($sort), $match)) {
264:                 $sql .= ' ORDER BY `'.$match[1].'`'.(empty($match[2]) ? '' : ' '.$match[2]);
265:             } elseif (is_array($sort)) {
266:                 $qs = array();
267:                 foreach ($sort as $item) {
268:                     if (preg_match('/^([a-z0-9_]+)\s(asc|desc)$/i', trim($item), $match)) {
269:                         $qs[] = '`'.$match[1].'`'.(empty($match[2]) ? '' : ' '.$match[2]);
270:                     }
271:                 }
272:                 if (count($qs) > 0) {
273:                     $sql .= ' ORDER BY '.implode(', ', $qs);
274:                 }
275:             }
276:         }
277:         if (is_int($limit) && $limit > 0) {
278:             $sql .= ' LIMIT '.$limit;
279:         }
280:         return $this->doCustomQuery($sql, $values);
281:     }
282: 
283:     /**
284:      * เลือกฐานข้อมูล
285:      * คืนค่า false หากไม่สำเร็จ
286:      *
287:      * @param string $database
288:      *
289:      * @return bool
290:      */
291:     public function selectDB($database)
292:     {
293:         $this->settings->dbname = $database;
294:         $result = $this->connection->query("USE $database");
295:         ++self::$query_count;
296:         return $result === false ? false : true;
297:     }
298: 
299:     /**
300:      * ฟังก์ชั่นแก้ไขข้อมูล
301:      * สำเร็จ คืนค่า true, ผิดพลาด คืนค่า false
302:      *
303:      * @param string       $table_name ชื่อตาราง
304:      * @param mixed        $condition  query WHERE
305:      * @param array|object $save       ข้อมูลที่ต้องการบันทึก รูปแบบ array('key1'=>'value1', 'key2'=>'value2', ...)
306:      *
307:      * @return bool
308:      */
309:     public function update($table_name, $condition, $save)
310:     {
311:         $sets = array();
312:         $values = array();
313:         foreach ($save as $key => $value) {
314:             if ($value instanceof QueryBuilder) {
315:                 $sets[] = '`'.$key.'` = ('.$value->text().')';
316:             } elseif ($value instanceof Sql) {
317:                 $sets[] = '`'.$key.'` = '.$value->text();
318:                 $values = $value->getValues($values);
319:             } else {
320:                 $k = ':'.$key.count($values);
321:                 $sets[] = '`'.$key.'` = '.$k;
322:                 $values[$k] = $value;
323:             }
324:         }
325:         $q = Sql::WHERE($condition);
326:         $sql = 'UPDATE '.$table_name.' SET '.implode(', ', $sets).' WHERE '.$q->text();
327:         $values = $q->getValues($values);
328:         try {
329:             $query = $this->connection->prepare($sql);
330:             $query->execute($values);
331:             $this->log(__FUNCTION__, $sql, $values);
332:             ++self::$query_count;
333: 
334:             return true;
335:         } catch (\PDOException $e) {
336:             throw new \Exception($e->getMessage(), 500, $e);
337:         }
338:     }
339: 
340:     /**
341:      * ประมวลผลคำสั่ง SQL สำหรับสอบถามข้อมูล คืนค่าผลลัพท์เป็นแอเรย์ของข้อมูลที่ตรงตามเงื่อนไข
342:      * คืนค่าผลการทำงานเป็น record ของข้อมูลทั้งหมดที่ตรงตามเงื่อนไข หรือคืนค่า false หามีข้อผิดพลาด
343:      *
344:      * @param string $sql    query string
345:      * @param array  $values ถ้าระบุตัวแปรนี้จะเป็นการบังคับใช้คำสั่ง prepare แทน query
346:      *
347:      * @return array|bool
348:      */
349:     protected function doCustomQuery($sql, $values = array())
350:     {
351:         $action = $this->cache->getAction();
352:         if ($action) {
353:             $cache = $this->cache->init($sql, $values);
354:             $result = $this->cache->get($cache);
355:         } else {
356:             $result = false;
357:         }
358:         if (!$result) {
359:             try {
360:                 if (empty($values)) {
361:                     $this->result_id = $this->connection->query($sql);
362:                 } else {
363:                     $this->result_id = $this->connection->prepare($sql);
364:                     $this->result_id->execute($values);
365:                 }
366:                 ++self::$query_count;
367:                 $result = $this->result_id->fetchAll(\PDO::FETCH_ASSOC);
368:                 if ($action == 1) {
369:                     $this->cache->save($cache, $result);
370:                 } elseif ($action == 2) {
371:                     $this->cache_item = $cache;
372:                 }
373:             } catch (\PDOException $e) {
374:                 throw new \Exception($e->getMessage(), 500, $e);
375:             }
376:             $this->log('Database', $sql, $values);
377:         } else {
378:             $this->cache->setAction(0);
379:             $this->cache_item = null;
380:             $this->log('Cached', $sql, $values);
381:         }
382:         return $result;
383:     }
384: 
385:     /**
386:      * ประมวลผลคำสั่ง SQL ที่ไม่ต้องการผลลัพท์ เช่น CREATE INSERT UPDATE
387:      * สำเร็จคืนค่าจำนวนแถวที่มีผล ไม่สำเร็จคืนค่า false
388:      *
389:      * @param string $sql
390:      * @param array  $values ถ้าระบุตัวแปรนี้จะเป็นการบังคับใช้คำสั่ง prepare แทน query
391:      *
392:      * @return int|bool
393:      */
394:     protected function doQuery($sql, $values = array())
395:     {
396:         try {
397:             if (empty($values)) {
398:                 $query = $this->connection->query($sql);
399:             } else {
400:                 $query = $this->connection->prepare($sql);
401:                 $query->execute($values);
402:             }
403:             ++self::$query_count;
404:             $this->log(__FUNCTION__, $sql, $values);
405: 
406:             return $query->rowCount();
407:         } catch (\PDOException $e) {
408:             throw new \Exception($e->getMessage(), 500, $e);
409:         }
410:     }
411: 
412:     /**
413:      * ฟังก์ชั่นสร้างคำสั่ง SQL สำหรับการ INSERT ข้อมูล
414:      *
415:      * @param string       $table_name ชื่อตาราง
416:      * @param array|object $save       ข้อมูลที่ต้องการบันทึก รูปแบบ array('key1'=>'value1', 'key2'=>'value2', ...)
417:      * @param array        $params     ตัวแปร Array สำหรับรับค่า params ส่งให้ execute
418:      *
419:      * @return string
420:      */
421:     private function makeInsert($table_name, $save, &$params)
422:     {
423:         $keys = array();
424:         $values = array();
425:         foreach ($save as $key => $value) {
426:             if ($value instanceof QueryBuilder) {
427:                 $keys[] = $key;
428:                 $values[] = '('.$value->text().')';
429:             } elseif ($value instanceof Sql) {
430:                 $keys[] = $key;
431:                 $values[] = $value->text();
432:                 $params = $value->getValues($params);
433:             } else {
434:                 $keys[] = $key;
435:                 $values[] = ':'.$key;
436:                 $params[':'.$key] = $value;
437:             }
438:         }
439:         return 'INSERT INTO '.$table_name.' (`'.implode('`,`', $keys).'`) VALUES ('.implode(',', $values).')';
440:     }
441: }
442: 
Kotchasan API documentation generated by ApiGen