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/Sql.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: /**
 14:  * SQL Function
 15:  *
 16:  * @author Goragod Wiriya <admin@goragod.com>
 17:  *
 18:  * @since 1.0
 19:  */
 20: class Sql
 21: {
 22:     /**
 23:      * คำสั่ง SQL ที่เก็บไว้
 24:      *
 25:      * @var string
 26:      */
 27:     protected $sql;
 28:     /**
 29:      * ตัวแปรเก็บพารามิเตอร์สำหรับการ bind.
 30:      *
 31:      * @var array
 32:      */
 33:     protected $values;
 34: 
 35:     /**
 36:      * หาค่าเฉลี่ยของคอลัมน์ที่เลือก
 37:      *
 38:      * @assert ('id')->text() [==] 'AVG(`id`)'
 39:      *
 40:      * @param string      $column_name ชื่อคอลัมน์
 41:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
 42:      * @param bool        $distinct    false (default) นับทุกคอลัมน์, true นับเฉพาะคอลัมน์ที่ไม่ซ้ำ
 43:      *
 44:      * @return \static
 45:      */
 46:     public static function AVG($column_name, $alias = null, $distinct = false)
 47:     {
 48:         return self::create('AVG('.($distinct ? 'DISTINCT ' : '').self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
 49:     }
 50: 
 51:     /**
 52:      * สร้างคำสั่ง BETWEEN ... AND ...
 53:      *
 54:      * @assert ('create_date', 'create_date', 'U.create_date')->text() [==] "`create_date` BETWEEN `create_date` AND U.`create_date`"
 55:      * @assert ('create_date', 'table_name.field_name', 'U.`create_date`')->text() [==] "`create_date` BETWEEN `table_name`.`field_name` AND U.`create_date`"
 56:      * @assert ('create_date', '`database`.`table`', '12-1-1')->text() [==] "`create_date` BETWEEN `database`.`table` AND '12-1-1'"
 57:      * @assert ('create_date', 0, 1)->text() [==] "`create_date` BETWEEN 0 AND 1"
 58:      *
 59:      * @param string $column_name
 60:      * @param string $min
 61:      * @param string $max
 62:      *
 63:      * @return \self
 64:      */
 65:     public static function BETWEEN($column_name, $min, $max)
 66:     {
 67:         return self::create(self::fieldName($column_name).' BETWEEN '.self::fieldName($min).' AND '.self::fieldName($max));
 68:     }
 69: 
 70:     /**
 71:      * สร้างคำสั่ง CONCAT หรือ CONCAT_WS
 72:      *
 73:      * @assert (array('fname', 'lname'))->text() [==] "CONCAT(`fname`, `lname`)"
 74:      * @assert (array('U.fname', 'U.`lname`'), 'displayname')->text() [==] "CONCAT(U.`fname`, U.`lname`) AS `displayname`"
 75:      * @assert (array('fname', 'lname'), 'displayname', ' ')->text() [==] "CONCAT_WS(' ', `fname`, `lname`) AS `displayname`"
 76:      *
 77:      * @param array       $fields    รายชื่อฟิลด์
 78:      * @param string|null $alias     ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
 79:      * @param string|null $separator null (defailt) คืนค่าคำสั่ง CONCAT, ถ้าระบุเป็นค่าอื่นคืนค่าคำสั่ง CONCAT_WS
 80:      *
 81:      * @throws \InvalidArgumentException ถ้ารูปแบบของ $fields ไม่ใช่แอเรย์
 82:      *
 83:      * @return \static
 84:      */
 85:     public static function CONCAT($fields, $alias = null, $separator = null)
 86:     {
 87:         $fs = array();
 88:         if (is_array($fields)) {
 89:             foreach ($fields as $item) {
 90:                 $fs[] = self::fieldName($item);
 91:             }
 92:             return self::create(($separator === null ? 'CONCAT(' : "CONCAT_WS('$separator', ").implode(', ', $fs).($alias ? ") AS `$alias`" : ')'));
 93:         } else {
 94:             throw new \InvalidArgumentException('$fields is array only');
 95:         }
 96:     }
 97: 
 98:     /**
 99:      * นับจำนวนเร็คคอร์ดของคอลัมน์ที่เลือก
100:      *
101:      * @assert ('id')->text() [==] 'COUNT(`id`)'
102:      *
103:      * @param string      $column_name
104:      * @param string|null $alias
105:      * @param bool        $distinct    false (default) นับทุกคอลัมน์, true นับเฉพาะคอลัมน์ที่ไม่ซ้ำ
106:      *
107:      * @return \static
108:      */
109:     public static function COUNT($column_name = '*', $alias = null, $distinct = false)
110:     {
111:         $column_name = $column_name == '*' ? '*' : self::fieldName($column_name);
112:         return self::create('COUNT('.($distinct ? 'DISTINCT ' : '').$column_name.')'.($alias ? " AS `$alias`" : ''));
113:     }
114: 
115:     /**
116:      * แยกวันที่ออกจากคอลัมน์ชนิด DATETIME
117:      *
118:      * @assert ('create_date')->text() [==] 'DATE(`create_date`)'
119:      * @assert ('create_date', 'date')->text() [==] 'DATE(`create_date`) AS `date`'
120:      *
121:      * @param string      $column_name
122:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
123:      *
124:      * @return \static
125:      */
126:     public static function DATE($column_name, $alias = null)
127:     {
128:         return self::create('DATE('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
129:     }
130: 
131:     /**
132:      * หาความแตกต่างระหว่างวัน (คืนค่าเป็นจำนวนวันที่แตกต่างกัน)
133:      *
134:      * @assert ('create_date', Sql::NOW())->text() [==] "DATEDIFF(`create_date`, NOW())"
135:      * @assert ('2017-04-04', 'create_date')->text() [==] "DATEDIFF('2017-04-04', `create_date`)"
136:      *
137:      * @param string $column_name1
138:      * @param string $column_name2
139:      * @param string $alias
140:      *
141:      * @return \static
142:      */
143:     public static function DATEDIFF($column_name1, $column_name2, $alias = null)
144:     {
145:         return self::create('DATEDIFF('.self::fieldName($column_name1).', '.self::fieldName($column_name2).')'.($alias ? " AS `$alias`" : ''));
146:     }
147: 
148:     /**
149:      * จัดรูปแบบของวันที่ตอนแสดงผล
150:      *
151:      * @assert (Sql::NOW(), '%h:%i')->text() [==] "DATE_FORMAT(NOW(), '%h:%i')"
152:      * @assert ('create_date', '%Y-%m-%d', 'today')->text() [==] "DATE_FORMAT(`create_date`, '%Y-%m-%d') AS `today`"
153:      *
154:      * @param string      $column_name
155:      * @param string      $format
156:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
157:      *
158:      * @return \static
159:      */
160:     public static function DATE_FORMAT($column_name, $format, $alias = null)
161:     {
162:         return self::create('DATE_FORMAT('.self::fieldName($column_name).", '$format')".($alias ? " AS `$alias`" : ''));
163:     }
164: 
165:     /**
166:      * แยกวันที่ออกจากคอลัมน์ชนิด DATE DATETIME
167:      *
168:      * @assert ('date')->text() [==] 'DAY(`date`)'
169:      * @assert ('date', 'd')->text() [==] 'DAY(`date`) AS `d`'
170:      *
171:      * @param string      $column_name
172:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
173:      *
174:      * @return \static
175:      */
176:     public static function DAY($column_name, $alias = null)
177:     {
178:         return self::create('DAY('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
179:     }
180: 
181:     /**
182:      * คืนค่าข้ออมูลที่ไม่ซ้ำกัน
183:      *
184:      * @assert ('id')->text() [==] 'DISTINCT `id`'
185:      *
186:      * @param string $column_name
187:      *
188:      * @return \static
189:      */
190:     public static function DISTINCT($column_name)
191:     {
192:         return self::create('DISTINCT '.self::fieldName($column_name));
193:     }
194: 
195:     /**
196:      * จัดรูปแบบของคอลัมน์ตอนแสดงผล.
197:      *
198:      * @assert (Sql::NOW(), 'Y-m-d')->text() [==] "FORMAT(NOW(), 'Y-m-d')"
199:      * @assert ('create_date', 'Y-m-d', 'today')->text() [==] "FORMAT(`create_date`, 'Y-m-d') AS `today`"
200:      *
201:      * @param string      $column_name
202:      * @param string      $format
203:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
204:      *
205:      * @return \static
206:      */
207:     public static function FORMAT($column_name, $format, $alias = null)
208:     {
209:         return self::create('FORMAT('.self::fieldName($column_name).", '$format')".($alias ? " AS `$alias`" : ''));
210:     }
211: 
212:     /**
213:      * สร้างคำสั่ง GROUP_CONCAT
214:      *
215:      * @assert ('C.topic', 'topic', ', ')->text() [==] "GROUP_CONCAT(C.`topic` SEPARATOR ', ') AS `topic`"
216:      *
217:      * @param string       $column_name
218:      * @param string|null  $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
219:      * @param string       $separator   ข้อความเชื่อมฟิลด์เข้าด้วยกัน ค่าเริมต้นคือ ,
220:      * @param bool         $distinct    false (default) คืนค่ารายการที่ไม่ซ้ำ
221:      * @param string|array $order       เรียงลำดับ
222:      *
223:      * @return \self
224:      */
225:     public static function GROUP_CONCAT($column_name, $alias = null, $separator = ',', $distinct = false, $order = null)
226:     {
227:         if (!empty($order)) {
228:             $orders = array();
229:             if (is_array($order)) {
230:                 foreach ($order as $item) {
231:                     $orders[] = self::fieldName($item);
232:                 }
233:             } else {
234:                 $orders[] = self::fieldName($order);
235:             }
236:             $order = empty($orders) ? '' : ' ORDER BY '.implode(',', $orders);
237:         }
238:         return self::create('GROUP_CONCAT('.($distinct ? 'DISTINCT ' : '').self::fieldName($column_name).$order." SEPARATOR '$separator')".($alias ? " AS `$alias`" : ''));
239:     }
240: 
241:     /**
242:      * แยกชั่วโมงออกจากคอลัมน์ชนิด DATETIME.
243:      *
244:      * @assert ('create_date')->text() [==] 'HOUR(`create_date`)'
245:      * @assert ('create_date', 'date')->text() [==] 'HOUR(`create_date`) AS `date`'
246:      *
247:      * @param string      $column_name
248:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
249:      *
250:      * @return \static
251:      */
252:     public static function HOUR($column_name, $alias = null)
253:     {
254:         return self::create('HOUR('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
255:     }
256: 
257:     /**
258:      * ฟังก์ชั่นสร้างคำสั่ง IFNULL
259:      *
260:      * @assert ('create_date', 'U.create_date')->text() [==] "IFNULL(`create_date`, U.`create_date`)"
261:      * @assert ('create_date', 'U.create_date', 'test')->text() [==] "IFNULL(`create_date`, U.`create_date`) AS `test`"
262:      *
263:      * @param string      $column_name1
264:      * @param string      $column_name2
265:      * @param string|null $alias        ถ้าระบุจะมีการเติม alias ให้กับคำสั่ง
266:      *
267:      * @return \self
268:      */
269:     public static function IFNULL($column_name1, $column_name2, $alias = null)
270:     {
271:         return self::create('IFNULL('.self::fieldName($column_name1).', '.self::fieldName($column_name2).')'.($alias ? ' AS `'.$alias.'`' : ''));
272:     }
273: 
274:     /**
275:      * ฟังก์ชั่นสร้างคำสั่ง IS NOT NULL
276:      *
277:      * @assert ('U.id')->text() [==] "U.`id` IS NOT NULL"
278:      *
279:      * @param string $column_name
280:      *
281:      * @return \self
282:      */
283:     public static function ISNOTNULL($column_name)
284:     {
285:         return self::create(self::fieldName($column_name).' IS NOT NULL');
286:     }
287: 
288:     /**
289:      * ฟังก์ชั่นสร้างคำสั่ง IS NULL
290:      *
291:      * @assert ('U.id')->text() [==] "U.`id` IS NULL"
292:      *
293:      * @param string $column_name
294:      *
295:      * @return \self
296:      */
297:     public static function ISNULL($column_name)
298:     {
299:         return self::create(self::fieldName($column_name).' IS NULL');
300:     }
301: 
302:     /**
303:      * หาค่าสูงสุด
304:      *
305:      * @assert ('id')->text() [==] 'MAX(`id`)'
306:      *
307:      * @param string      $column_name
308:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
309:      *
310:      * @return \static
311:      */
312:     public static function MAX($column_name, $alias = null)
313:     {
314:         return self::create('MAX('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
315:     }
316: 
317:     /**
318:      * หาค่าต่ำสุด
319:      *
320:      * @assert ('id')->text() [==] 'MIN(`id`)'
321:      *
322:      * @param string      $column_name
323:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
324:      *
325:      * @return \static
326:      */
327:     public static function MIN($column_name, $alias = null)
328:     {
329:         return self::create('MIN('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
330:     }
331: 
332:     /**
333:      * แยกนาทีออกจากคอลัมน์ชนิด DATETIME.
334:      *
335:      * @assert ('create_date')->text() [==] 'MINUTE(`create_date`)'
336:      * @assert ('create_date', 'date')->text() [==] 'MINUTE(`create_date`) AS `date`'
337:      *
338:      * @param string      $column_name
339:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
340:      *
341:      * @return \static
342:      */
343:     public static function MINUTE($column_name, $alias = null)
344:     {
345:         return self::create('MINUTE('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
346:     }
347: 
348:     /**
349:      * แยกเดือนออกจากคอลัมน์ชนิด DATE DATETIME
350:      *
351:      * @assert ('date')->text() [==] 'MONTH(`date`)'
352:      * @assert ('date', 'm')->text() [==] 'MONTH(`date`) AS `m`'
353:      *
354:      * @param string      $column_name
355:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
356:      *
357:      * @return \static
358:      */
359:     public static function MONTH($column_name, $alias = null)
360:     {
361:         return self::create('MONTH('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
362:     }
363: 
364:     /**
365:      * ฟังก์ชั่นสร้าง SQL สำหรับหาค่าสูงสุด + 1
366:      * ใช้ในการหาค่า id ถัดไป
367:      *
368:      *
369:      * @assert ('id', '`world`')->text() [==] '(1 + IFNULL((SELECT MAX(`id`) FROM `world` AS X), 0))'
370:      * @assert ('id', '`world`', array(array('module_id', 'D.`id`')), 'next_id')->text() [==] '(1 + IFNULL((SELECT MAX(`id`) FROM `world` AS X WHERE `module_id` = D.`id`), 0)) AS `next_id`'
371:      * @assert ('id', '`world`', array(array('module_id', 'D.`id`')), null)->text() [==] '(1 + IFNULL((SELECT MAX(`id`) FROM `world` AS X WHERE `module_id` = D.`id`), 0))'
372:      *
373:      * @param string $field      ชื่อฟิลด์ที่ต้องการหาค่าสูงสุด
374:      * @param string $table_name ชื่อตาราง
375:      * @param mixed  $condition  (optional) query WHERE
376:      * @param array  $values     (optional) แอเรย์สำหรับรับค่า value สำหรับการ bind
377:      * @param string $alias      (optional) ชื่อฟิลด์ที่ใช้คืนค่า ไม่ระบุ (null) หมายถึงไม่ต้องการชื่อฟิลด์
378:      * @param string $operator   (optional) เช่น AND หรือ OR
379:      * @param string $id         (optional )ชื่อฟิลด์ที่เป็น key
380:      *
381:      * @return \static
382:      */
383:     public static function NEXT($field, $table_name, $condition = null, $alias = null, $operator = 'AND', $id = 'id')
384:     {
385:         $obj = new static();
386:         if (empty($condition)) {
387:             $condition = '';
388:         } else {
389:             $condition = ' WHERE '.$obj->buildWhere($condition, $obj->values, $operator, $id);
390:         }
391:         $obj->sql = '(1 + IFNULL((SELECT MAX(`'.$field.'`) FROM '.$table_name.' AS X'.$condition.'), 0))';
392:         if (isset($alias)) {
393:             $obj->sql .= " AS `$alias`";
394:         }
395: 
396:         return $obj;
397:     }
398: 
399:     /**
400:      * คืนค่าวันที่และเวลาปัจจุบัน
401:      *
402:      * @assert ()->text() [==] 'NOW()'
403:      * @assert ('id')->text() [==] 'NOW() AS `id`'
404:      *
405:      * @param string|null $alias ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
406:      *
407:      * @return \static
408:      */
409:     public static function NOW($alias = null)
410:     {
411:         return self::create('NOW()'.($alias ? " AS `$alias`" : ''));
412:     }
413: 
414:     /**
415:      * ค้นหาข้อความ ไม่พบคืนค่า 0, ตัวแรกคือ 1
416:      *
417:      * @assert ('find', 'C.`topic`')->text() [==] "LOCATE('find', C.`topic`)"
418:      *
419:      * @param string      $substr ข้อความที่ค้นหา ถ้าเป็นชื่อฟิลด์ต้องครอบด้วย ``
420:      * @param string      $str    ข้อความต้นฉบับ ถ้าเป็นชื่อฟิลด์ต้องครอบด้วย ``
421:      * @param string|null $alias  ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
422:      * @param int         $pos    ตำแหน่งเริ่มต้นค้นหา (default) หรือไม่ระบุ ค้นหาตั้งแต่ตัวแรก
423:      *
424:      * @return \self
425:      */
426:     public static function POSITION($substr, $str, $alias = null, $pos = 0)
427:     {
428:         $substr = strpos($substr, '`') === false ? "'$substr'" : $substr;
429:         $str = strpos($str, '`') === false ? "'$str'" : $str;
430: 
431:         return self::create("LOCATE($substr, $str".(empty($pos) ? ')' : ", $pos)").($alias ? " AS `$alias`" : ''));
432:     }
433: 
434:     /**
435:      * สุ่มตัวเลข
436:      *
437:      * @assert ()->text() [==] 'RAND()'
438:      * @assert ('id')->text() [==] 'RAND() AS `id`'
439:      *
440:      * @param string      $column_name
441:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
442:      *
443:      * @return \static
444:      */
445:     public static function RAND($alias = null)
446:     {
447:         return self::create('RAND()'.($alias ? " AS `$alias`" : ''));
448:     }
449: 
450:     /**
451:      * แยกวินาทีออกจากคอลัมน์ชนิด DATETIME
452:      *
453:      * @assert ('create_date')->text() [==] 'SECOND(`create_date`)'
454:      * @assert ('create_date', 'date')->text() [==] 'SECOND(`create_date`) AS `date`'
455:      *
456:      * @param string      $column_name
457:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
458:      *
459:      * @return \static
460:      */
461:     public static function SECOND($column_name, $alias = null)
462:     {
463:         return self::create('SECOND('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
464:     }
465: 
466:     /**
467:      * ผลรวมของคอลัมน์ที่เลือก
468:      *
469:      * @assert ('id')->text() [==] 'SUM(`id`)'
470:      * @assert ('table_name.`id`', 'id')->text() [==] 'SUM(`table_name`.`id`) AS `id`'
471:      * @assert ('U.id', 'id', true)->text() [==] 'SUM(DISTINCT U.`id`) AS `id`'
472:      * @assert ('U1.id', 'id', true)->text() [==] 'SUM(DISTINCT U1.`id`) AS `id`'
473:      *
474:      * @param string      $column_name
475:      * @param string|null $alias
476:      * @param bool        $distinct    false (default) รวมทุกคอลัมน์, true รวมเฉพาะคอลัมน์ที่ไม่ซ้ำ
477:      *
478:      * @return \static
479:      */
480:     public static function SUM($column_name, $alias = '', $distinct = false)
481:     {
482:         return self::create('SUM('.($distinct ? 'DISTINCT ' : '').self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
483:     }
484: 
485:     /**
486:      * หาความแตกต่างระหว่างเวลา (คืนค่าเป็น H:m:i ที่แตกต่างกัน)
487:      *
488:      * @assert ('create_date', Sql::NOW())->text() [==] "TIMEDIFF(`create_date`, NOW())"
489:      * @assert ('2017-04-04', 'create_date')->text() [==] "TIMEDIFF('2017-04-04', `create_date`)"
490:      *
491:      * @param string $column_name1
492:      * @param string $column_name2
493:      * @param string $alias
494:      *
495:      * @return \static
496:      */
497:     public static function TIMEDIFF($column_name1, $column_name2, $alias = null)
498:     {
499:         return self::create('TIMEDIFF('.self::fieldName($column_name1).', '.self::fieldName($column_name2).')'.($alias ? " AS `$alias`" : ''));
500:     }
501: 
502:     /**
503:      * หาความแตกต่างระหว่างเวลา (คืนค่าตามรูปแบบ $unit)
504:      *
505:      * @assert ('HOUR', 'create_date', Sql::NOW())->text() [==] "TIMESTAMPDIFF(HOUR, `create_date`, NOW())"
506:      * @assert ('MONTH', '2017-04-04', 'create_date')->text() [==] "TIMESTAMPDIFF(MONTH, '2017-04-04', `create_date`)"
507:      *
508:      * @param string $unit FRAC_SECOND (microseconds), SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or YEAR
509:      * @param string $column_name1
510:      * @param string $column_name2
511:      * @param string $alias
512:      *
513:      * @return \static
514:      */
515:     public static function TIMESTAMPDIFF($unit, $column_name1, $column_name2, $alias = null)
516:     {
517:         return self::create('TIMESTAMPDIFF('.$unit.', '.self::fieldName($column_name1).', '.self::fieldName($column_name2).')'.($alias ? " AS `$alias`" : ''));
518:     }
519: 
520:     /**
521:      * สร้างคำสั่ง WHERE
522:      *
523:      * @assert WHERE(1)->text() [==] "`id` = 1"
524:      * @assert WHERE('1')->text() [==] "`id` = '1'"
525:      * @assert WHERE(0.1)->text() [==] "`id` = 0.1"
526:      * @assert WHERE('ทดสอบ')->text() [==] "`id` = 'ทดสอบ'"
527:      * @assert WHERE(null)->text() [==] "`id` = NULL"
528:      * @assert WHERE(0x64656)->text() [==] "`id` = 411222"
529:      * @assert WHERE('SELECT * FROM')->text() [==] "`id` = :id0"
530:      * @assert WHERE(Sql::create('EXISTS SELECT FROM WHERE'))->text() [==] "EXISTS SELECT FROM WHERE"
531:      * @assert WHERE(array('id', '=', 1))->text() [==] "`id` = 1"
532:      * @assert WHERE(array('U.id', '2017-01-01 00:00:00'))->text() [==] "U.`id` = '2017-01-01 00:00:00'"
533:      * @assert WHERE(array('id', 'IN', array(1, '2', null)))->text() [==] "`id` IN (1, '2', NULL)"
534:      * @assert WHERE(array('id', 'SELECT * FROM'))->text() [==] "`id` = :id0"
535:      * @assert WHERE(array('U.`id`', 'NOT IN', Sql::create('SELECT * FROM')))->text() [==] "U.`id` NOT IN SELECT * FROM"
536:      * @assert WHERE(array(array('id', 'IN', array(1, '2', null))))->text() [==] "`id` IN (1, '2', NULL)"
537:      * @assert WHERE(array(array('U.id', 1), array('U.id', '!=', '1')))->text() [==] "U.`id` = 1 AND U.`id` != '1'"
538:      * @assert WHERE(array(array(Sql::MONTH('create_date'), 1), array(Sql::YEAR('create_date'), 1)))->text() [==] "MONTH(`create_date`) = 1 AND YEAR(`create_date`) = 1"
539:      * @assert WHERE(array(array('id', array(1, 'a')), array('id', array('G.id', 'G.`id2`'))))->text() [==] "`id` IN (1, 'a') AND `id` IN (G.`id`, G.`id2`)"
540:      * @assert WHERE(array(array('id', array('', 'th'))))->text() [==] "`id` IN ('', 'th')"
541:      * @assert WHERE(array(Sql::YEAR('create_date'), Sql::YEAR('`create_date`')))->text() [==] "YEAR(`create_date`) = YEAR(`create_date`)"
542:      * @assert WHERE(array('ip', 'NOT IN', array('', '192.168.1.2')))->text() [==] "`ip` NOT IN ('', '192.168.1.2')"
543:      * @assert WHERE(array(1, 1))->text() [==] "1 = 1"
544:      *
545:      * @param mixed  $condition
546:      * @param string $operator  (optional) เช่น AND หรือ OR
547:      * @param string $id        (optional )ชื่อฟิลด์ที่เป็น key
548:      *
549:      * @return \static
550:      */
551:     public static function WHERE($condition, $operator = 'AND', $id = 'id')
552:     {
553:         $obj = new static();
554:         $obj->sql = $obj->buildWhere($condition, $obj->values, $operator, $id);
555:         return $obj;
556:     }
557: 
558:     /**
559:      * แยกปีออกจากคอลัมน์ชนิด DATE DATETIME.
560:      *
561:      * @assert ('date')->text() [==] 'YEAR(`date`)'
562:      * @assert ('date', 'y')->text() [==] 'YEAR(`date`) AS `y`'
563:      *
564:      * @param string      $column_name
565:      * @param string|null $alias       ชื่อรองที่ต้องการ ถ้าไม่ระบุไม่มีชื่อรอง
566:      *
567:      * @return \static
568:      */
569:     public static function YEAR($column_name, $alias = null)
570:     {
571:         return self::create('YEAR('.self::fieldName($column_name).')'.($alias ? " AS `$alias`" : ''));
572:     }
573: 
574:     /**
575:      * class constructer
576:      *
577:      * @param string $sql
578:      */
579:     public function __construct($sql = null)
580:     {
581:         $this->sql = $sql;
582:         $this->values = array();
583:     }
584: 
585:     /**
586:      * สร้าง Object Sql
587:      *
588:      * @param string $sql
589:      */
590:     public static function create($sql)
591:     {
592:         return new static($sql);
593:     }
594: 
595:     /**
596:      * ใส่ `` ครอบชื่อคอลัมน์
597:      * ชื่อคอลัมน์ต้องเป็น ภาษาอังกฤษ ตัวเลข และ _ เท่านั้น
598:      * ถ้ามีอักขระอื่นนอกจากนี้ คืนค่า ข้อความที่ส่งมา ครอบด้วย ''
599:      *
600:      * @assert ('U.id') [==] 'U.`id`'
601:      * @assert ('U1.id') [==] 'U1.`id`'
602:      * @assert ('U1.id DESC') [==] 'U1.`id` DESC'
603:      * @assert ('field_name') [==] '`field_name`'
604:      * @assert ('table_name.field_name') [==] '`table_name`.`field_name`'
605:      * @assert ('`table_name`.`field_name`') [==] '`table_name`.`field_name`'
606:      * @assert ('table_name.`field_name`') [==] '`table_name`.`field_name`'
607:      * @assert ('`table_name`.field_name') [==] '`table_name`.`field_name`'
608:      * @assert ('`table_name`.field_name ASC') [==] '`table_name`.`field_name` ASC'
609:      * @assert ('0x64656') [==] "`0x64656`"
610:      * @assert (0x64656) [==] 411222
611:      * @assert ('DATE(day)') [==] "'DATE(day)'"
612:      * @assert ('DROP table') [==] "'DROP table'"
613:      * @assert (array()) [throws] InvalidArgumentException
614:      *
615:      * @param string $column_name
616:      *
617:      * @throws \InvalidArgumentException ถ้ารูปแบบของ $column_name ไม่ถูกต้อง
618:      *
619:      * @return string
620:      */
621:     public static function fieldName($column_name)
622:     {
623:         if ($column_name instanceof self) {
624:             // Sql
625:             return $column_name->text();
626:         } elseif ($column_name instanceof QueryBuilder) {
627:             // QueryBuilder
628:             return '('.$column_name->text().')';
629:         } elseif (is_string($column_name)) {
630:             if (preg_match('/^(([A-Z]{1,1}[0-9]{0,1})\.)?`?([a-zA-Z0-9_]+)`?(\s(ASC|DESC|asc|desc))?$/', $column_name, $match)) {
631:                 // U.id, U.`id`, U1.id, U1.`id`, field_name, `field_name`
632:                 return ($match[2] == '' ? "`$match[3]`" : "$match[2].`$match[3]`").(empty($match[5]) ? '' : $match[4]);
633:             } elseif (preg_match('/^`?([a-zA-Z0-9_]+)`?\.`?([a-zA-Z0-9_]+)`?(\s(ASC|DESC|asc|desc))?$/', $column_name, $match)) {
634:                 // table_name.field_name, table_name.`field_name`, `table_name`.field_name, `table_name`.`field_name`
635:                 return ("`$match[1]`.`$match[2]`").(empty($match[4]) ? '' : $match[3]);
636:             } else {
637:                 // อื่นๆ คืนค่าเป็นข้อความภายใต้เครื่องหมาย ' (อัญประกาศเดี่ยว)
638:                 return "'$column_name'";
639:             }
640:         } elseif (is_numeric($column_name)) {
641:             // ตัวเลขเท่านั้น
642:             return $column_name;
643:         }
644:         throw new \InvalidArgumentException('Invalid arguments in fieldName');
645:     }
646: 
647:     /**
648:      * คืนค่าแอเร์ยเก็บพารามิเตอร์สำหรับการ bind รวมกับ $values
649:      *
650:      * @param array $values
651:      *
652:      * @return array
653:      */
654:     public function getValues($values = array())
655:     {
656:         if (empty($values)) {
657:             return $this->values;
658:         }
659:         foreach ($this->values as $key => $value) {
660:             $values[$key] = $value;
661:         }
662: 
663:         return $values;
664:     }
665: 
666:     /**
667:      * แปลงค่า Value สำหรับใช้ใน query
668:      *
669:      * @assert ('id', 'ทดสอบ', $array) [==] "'ทดสอบ'"
670:      * @assert ('id', 'test', $array) [==] "'test'"
671:      * @assert ('id', 'abcde012345', $array) [==] "'abcde012345'"
672:      * @assert ('id', 123456, $array) [==] 123456
673:      * @assert ('id', 0.1, $array) [==] 0.1
674:      * @assert ('id', null, $array) [==] 'NULL'
675:      * @assert ('id', 'U.id', $array) [==] "U.`id`"
676:      * @assert ('id', 'U.`id`', $array) [==] 'U.`id`'
677:      * @assert ('id', 'domain.tld', $array) [==] "'domain.tld'"
678:      * @assert ('id', 'table_name.`id`', $array) [==] '`table_name`.`id`'
679:      * @assert ('id', '`table_name`.id', $array) [==] '`table_name`.`id`'
680:      * @assert ('id', '`table_name`.`id`', $array) [==] '`table_name`.`id`'
681:      * @assert ('id', 'INSERT INTO', $array) [==] ':id0'
682:      * @assert ('id', array(1, '2', null), $array) [==] "(1, '2', NULL)"
683:      * @assert ('id', '0x64656', $array) [==] ':id0'
684:      * @assert ('id', 0x64656, $array) [==] 411222
685:      * @assert ('`table_name`.`id`', '0x64656', $array) [==] ':tablenameid0'
686:      * @assert ('U1.`id`', '0x64656', $array) [==] ':u1id0'
687:      * @assert ('U.id', '0x64656', $array) [==] ':uid0'
688:      *
689:      * @param mixed $value
690:      * @param array $values แอเรย์สำหรับรับค่า value สำหรับการ bind
691:      *
692:      * @throws \InvalidArgumentException ถ้ารูปแบบของ $value ไม่ถูกต้อง
693:      *
694:      * @return string
695:      */
696:     public static function quoteValue($column_name, $value, &$values)
697:     {
698:         if (is_array($value)) {
699:             $qs = array();
700:             foreach ($value as $v) {
701:                 $qs[] = self::quoteValue($column_name, $v, $values);
702:             }
703:             $sql = '('.implode(', ', $qs).')';
704:         } elseif ($value === null) {
705:             $sql = 'NULL';
706:         } elseif ($value === '') {
707:             $sql = "''";
708:         } elseif (is_string($value)) {
709:             if (preg_match('/^([0-9\s\r\n\t\.\_\-:]+)$/', $value)) {
710:                 // ตัวเลข จำนวนเงิน เบอร์โทร วันที่
711:                 $sql = "'$value'";
712:             } elseif (preg_match('/0x[0-9]+/is', $value)) {
713:                 // 0x
714:                 $sql = ':'.strtolower(preg_replace('/[`\.\s\-_]+/', '', $column_name)).count($values);
715:                 $values[$sql] = $value;
716:             } else {
717:                 if (preg_match('/^(([A-Z]{1,1}[0-9]{0,1})|`([a-zA-Z0-9_]+)`)\.`?([a-zA-Z0-9_]+)`?$/', $value, $match)) {
718:                     // U.id U.`id` U1.id U1.`id`  `table_name`.`module_id`
719:                     $sql = $match[3] == '' ? "$match[2].`$match[4]`" : "`$match[3]`.`$match[4]`";
720:                 } elseif (preg_match('/^([a-zA-Z0-9_]+)\.`([a-zA-Z0-9_]+)`$/', $value, $match)) {
721:                     // table_name.`module_id`
722:                     $sql = "`$match[1]`.`$match[2]`";
723:                 } elseif (!preg_match('/[\s\r\n\t`;\(\)\*\=<>\/\'"]+/s', $value) && !preg_match('/(UNION|INSERT|DELETE|TRUNCATE|DROP|0x[0-9]+)/is', $value)) {
724:                     // ข้อความที่ไม่มีช่องว่างหรือรหัสที่อาจเป็น SQL
725:                     $sql = "'$value'";
726:                 } else {
727:                     $sql = ':'.strtolower(preg_replace('/[`\.\s\-_]+/', '', $column_name)).count($values);
728:                     $values[$sql] = $value;
729:                 }
730:             }
731:         } elseif (is_numeric($value)) {
732:             // ตัวเลขเท่านั้น
733:             $sql = $value;
734:         } elseif ($value instanceof self) {
735:             // Sql
736:             $sql = $value->text($column_name);
737:             $values = $value->getValues($values);
738:         } elseif ($value instanceof QueryBuilder) {
739:             // QueryBuilder
740:             $sql = '('.$value->text().')';
741:             $values = $value->getValues($values);
742:         } else {
743:             throw new \InvalidArgumentException('Invalid arguments in quoteValue');
744:         }
745:         return $sql;
746:     }
747: 
748:     /**
749:      * ฟังก์ชั่นสำหรับรับค่าเป็นสตริงค์เท่านั้น
750:      * ผลลัพท์จะถูกครอบด้วย '' (ฟันหนู)
751:      *
752:      * @param string $value
753:      *
754:      * @return \self
755:      */
756:     public static function strValue($value)
757:     {
758:         return self::create("'$value'");
759:     }
760: 
761:     /**
762:      * คืนค่าคำสั่ง SQL เป็น string
763:      * ถ้า $sql เป็น null จะคืนค่า :$key ใช้สำหรับการ bind
764:      *
765:      * @param string $key
766:      *
767:      * @return string
768:      */
769:     public function text($key = null)
770:     {
771:         if ($this->sql === null) {
772:             if (is_string($key) && $key != '') {
773:                 return ':'.preg_replace('/[\.`]/', '', strtolower($key));
774:             } else {
775:                 throw new \InvalidArgumentException('$key must be a non-empty string');
776:             }
777:         } else {
778:             return $this->sql;
779:         }
780:     }
781: 
782:     /**
783:      * create SQL WHERE command
784:      *
785:      * @param mixed  $condition
786:      * @param array  $values    แอเรย์สำหรับรับค่า value สำหรับการ bind
787:      * @param string $operator  เช่น AND หรือ OR
788:      * @param string $id        ชื่อฟิลด์ที่เป็น key
789:      *
790:      * @return string
791:      */
792:     private function buildWhere($condition, &$values, $operator, $id)
793:     {
794:         if (is_array($condition)) {
795:             $qs = array();
796:             if (is_array($condition[0])) {
797:                 foreach ($condition as $item) {
798:                     if ($item instanceof QueryBuilder) {
799:                         $qs[] = '('.$item->text().')';
800:                         $values = $item->getValues($values);
801:                     } elseif ($item instanceof self) {
802:                         $qs[] = $item->text();
803:                         $values = $item->getValues($values);
804:                     } else {
805:                         $qs[] = $this->buildWhere($item, $values, $operator, $id);
806:                     }
807:                 }
808:                 $sql = implode(' '.$operator.' ', $qs);
809:             } else {
810:                 if ($condition[0] instanceof QueryBuilder) {
811:                     $key = '('.$condition[0]->text().')';
812:                     $values = $condition[0]->getValues($values);
813:                 } elseif ($condition[0] instanceof self) {
814:                     $key = $condition[0]->text();
815:                     $values = $condition[0]->getValues($values);
816:                 } else {
817:                     $key = self::fieldName($condition[0]);
818:                 }
819:                 if (count($condition) == 2) {
820:                     if ($condition[1] instanceof QueryBuilder) {
821:                         $operator = '=';
822:                         $value = '('.$condition[1]->text().')';
823:                         $values = $condition[1]->getValues($values);
824:                     } elseif ($condition[1] instanceof self) {
825:                         $operator = '=';
826:                         $value = $condition[1]->text();
827:                         $values = $condition[1]->getValues($values);
828:                     } else {
829:                         $operator = '=';
830:                         if (is_array($condition[1]) && $operator == '=') {
831:                             $operator = 'IN';
832:                         }
833:                         $value = self::quoteValue($key, $condition[1], $values);
834:                     }
835:                 } elseif (isset($condition[2])) {
836:                     if ($condition[2] instanceof QueryBuilder) {
837:                         $operator = trim($condition[1]);
838:                         $value = '('.$condition[2]->text().')';
839:                         $values = $condition[2]->getValues($values);
840:                     } elseif ($condition[2] instanceof self) {
841:                         $operator = trim($condition[1]);
842:                         $value = $condition[2]->text();
843:                         $values = $condition[2]->getValues($values);
844:                     } else {
845:                         $operator = trim($condition[1]);
846:                         if (is_array($condition[2]) && $operator == '=') {
847:                             $operator = 'IN';
848:                         }
849:                         $value = self::quoteValue($key, $condition[2], $values);
850:                     }
851:                 }
852:                 if (isset($value)) {
853:                     $sql = $key.' '.$operator.' '.$value;
854:                 } else {
855:                     $sql = $key;
856:                 }
857:             }
858:         } elseif ($condition instanceof QueryBuilder) {
859:             $sql = '('.$condition->text().')';
860:             $values = $condition->getValues($values);
861:         } elseif ($condition instanceof self) {
862:             $sql = $condition->text();
863:             $values = $condition->getValues($values);
864:         } else {
865:             // ใช้ $id เป็น column_name
866:             $sql = self::fieldName($id).' = '.self::quoteValue($id, $condition, $values);
867:         }
868:         return $sql;
869:     }
870: }
871: 
Kotchasan API documentation generated by ApiGen