Kotchasan Framework Documentation

Kotchasan Framework Documentation

QueryBuilder - ตัวสร้างคำสั่ง SQL

TH 05 Feb 2026 07:20

QueryBuilder - ตัวสร้างคำสั่ง SQL

ภาพรวม

QueryBuilder เป็นระบบสำหรับสร้างคำสั่ง SQL แบบ Object-Oriented ใน Kotchasan Framework ช่วยให้นักพัฒนาสามารถสร้างคำสั่ง SQL ที่ซับซ้อนได้อย่างง่ายดายและปลอดภัย โดยไม่ต้องเขียน SQL โดยตรง

คุณสมบัติหลัก

  • Type Safety: ป้องกัน SQL Injection โดยอัตโนมัติด้วย Named Parameters
  • Database Agnostic: รองรับฐานข้อมูลหลายประเภท (MySQL, PostgreSQL, SQLite, SQL Server)
  • Method Chaining: เขียนโค้ดแบบต่อเนื่องได้ (Fluent Interface)
  • Subquery Support: รองรับ Subquery ที่ซับซ้อนและ Nested Queries
  • Raw SQL Integration: ผสมผสาน Raw SQL กับ Query Builder ได้
  • Automatic Parameter Binding: จัดการ Parameter Binding อัตโนมัติ
  • Query Optimization: เพิ่มประสิทธิภาพการทำงานของ SQL

สารบัญ

  1. การติดตั้งและการใช้งานเบื้องต้น
  2. SelectBuilder - การสร้างคำสั่ง SELECT
  3. InsertBuilder - การสร้างคำสั่ง INSERT
  4. UpdateBuilder - การสร้างคำสั่ง UPDATE
  5. DeleteBuilder - การสร้างคำสั่ง DELETE
  6. Advanced Features - ฟีเจอร์ขั้นสูง
  7. Best Practices - แนวทางปฏิบัติที่ดี

การติดตั้งและการใช้งานเบื้องต้น

การสร้าง QueryBuilder Instance

use Kotchasan\Database;
use Kotchasan\Database\Sql;
use Kotchasan\QueryBuilder\SelectBuilder;
use Kotchasan\QueryBuilder\InsertBuilder;
use Kotchasan\QueryBuilder\UpdateBuilder;
use Kotchasan\QueryBuilder\DeleteBuilder;

// วิธีที่ 1: สร้างผ่าน Kotchasan\Database (แนะนำ)
$db = Kotchasan\Database::create();
$selectQuery = $db->select(['id', 'name', 'email']);
$insertQuery = $db->insert('users');
$updateQuery = $db->update('users');
$deleteQuery = $db->delete('users');

// วิธีที่ 2: สร้างโดยตรง
$connection = Kotchasan\Database::getConnection();
$selectQuery = new SelectBuilder($connection);
$insertQuery = new InsertBuilder($connection);

การใช้งานพื้นฐาน

use Kotchasan\Database;
// SELECT พื้นฐาน
$users = Kotchasan\Database::create()
    ->select(['id', 'name', 'email'])
    ->from('user')
    ->where(['status', 'active'])
    ->fetchAll();

// INSERT พื้นฐาน
$userId = Kotchasan\Database::create()
    ->insert('user')
    ->values([
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'created_at' => date('Y-m-d H:i:s')
    ])
    ->execute();

// UPDATE พื้นฐาน
$affected = Kotchasan\Database::create()
    ->update('user')
    ->set(['last_login' => date('Y-m-d H:i:s')])
    ->where(['id', 123])
    ->execute();

// DELETE พื้นฐาน
$deleted = Kotchasan\Database::create()
    ->delete('user')
    ->where(['status', 'inactive'])
    ->where(['last_login', '<', '2023-01-01'])
    ->execute();

SelectBuilder - การสร้างคำสั่ง SELECT

SelectBuilder เป็นคลาสสำหรับสร้างคำสั่ง SELECT ที่ซับซ้อน รองรับ JOIN, Subquery, Grouping, และ Aggregation Functions

เมธอดหลักของ SelectBuilder

select($columns = '*')

กำหนดคอลัมน์ที่ต้องการเลือก

use Kotchasan\Database;
// เลือกคอลัมน์เดียว
$query->select('name');

// เลือกหลายคอลัมน์
$query->select(['id', 'name', 'email']);

// เลือกทั้งหมด
$query->select('*');

// เลือกพร้อม alias
$query->select([
    'id',
    'name',
    ['email', 'user_email'],
    ['COUNT(*)', 'total']
]);

// เลือกด้วย Subquery
$subquery = Kotchasan\Database::create()
    ->select(Sql::GROUP_CONCAT('D.value', null, ',', true))
    ->from('user_meta D')
    ->where(['D.member_id', '=', Sql::column('U.id')])
    ->where(['D.name', '=', 'department']);

$query->select(['U.*', [$subquery, 'department']]);

from(string $table, ?string $alias = null)

กำหนดตารางหลัก

// ตารางเดียว
$query->from('user');

// ตารางพร้อม alias
$query->from('user', 'U');

// หรือแบบสั้น
$query->from('user U');

where($condition, string $operator = 'AND')

เพิ่มเงื่อนไข WHERE

// เงื่อนไขพื้นฐาน
$query->where(['status', 'active']);
$query->where(['age', '>', 18]);
$query->where(['name', 'LIKE', 'John%']);

// หลายเงื่อนไข
$query->where(['status', 'active'])
      ->where(['age', '>', 18]);

// IN clause
$query->where(['id', [1, 2, 3, 4, 5]]);

// Column to column comparison
$query->where(['user_id', '=', Sql::column('profile.user_id')]);

// Raw SQL condition
$query->whereRaw('FIND_IN_SET(?, tags)', 'AND', [5]);

// Nested conditions
$query->where(function ($q) {
    $q->where(['status', 'active'])
      ->orWhere(['status', 'pending']);
})->where(['age', '>', 18]);

orWhere($condition)

เพิ่มเงื่อนไข OR WHERE

$query->where(['status', 'active'])
      ->orWhere(['status', 'pending']);

join($table, $condition, string $type = 'INNER')

เพิ่ม JOIN

// INNER JOIN
$query->join('profile P', 'U.id = P.user_id');

// LEFT JOIN
$query->leftJoin('profile P', 'U.id = P.user_id');

// RIGHT JOIN
$query->rightJoin('department D', 'U.department_id = D.id');

// หลาย JOIN
$query->from('user U')
      ->leftJoin('profile P', 'U.id = P.user_id')
      ->leftJoin('department D', 'U.department_id = D.id')
      ->where(['U.status', 'active']);

groupBy($columns)

จัดกลุ่มข้อมูล

// Group by คอลัมน์เดียว
$query->groupBy('department_id');

// Group by หลายคอลัมน์
$query->groupBy(['department_id', 'status']);

having($condition, string $operator = 'AND')

เงื่อนไข HAVING สำหรับ GROUP BY

$query->select(['department_id', 'COUNT(*) as total'])
      ->groupBy('department_id')
      ->having('COUNT(*)', '>', 5);

orderBy($column, string $direction = 'ASC')

เรียงลำดับผลลัพธ์

// เรียงเดียว
$query->orderBy('name', 'ASC');

// เรียงหลายคอลัมน์
$query->orderBy('department_id', 'ASC')
      ->orderBy('name', 'DESC');

// เรียงด้วย Raw SQL
$query->orderBy('FIELD(status, "active", "pending", "inactive")');

limit(int $limit, int $offset = 0)

จำกัดจำนวนผลลัพธ์

// จำกัด 10 รายการ
$query->limit(10);

// จำกัด 10 รายการ เริ่มจากลำดับที่ 20
$query->limit(10, 20);

// Pagination
$page = 2;
$perPage = 1; // 5;
$query->limit($perPage, ($page - 1) * $perPage);

ตัวอย่างการใช้งาน SelectBuilder

ตัวอย่างที่ 1: การ Query พื้นฐาน

use Kotchasan\Database;

// ดึงข้อมูลผู้ใช้ที่ active
$activeUsers = Kotchasan\Database::create()
    ->select(['id', 'name', 'email', 'created_at'])
    ->from('user')
    ->where(['status', 'active'])
    ->orderBy('name', 'ASC')
    ->fetchAll();

// ดึงข้อมูลผู้ใช้คนเดียว
$user = Kotchasan\Database::create()
    ->select('*')
    ->from('user')
    ->where(['id', 123])
    ->first();

ตัวอย่างที่ 2: การ JOIN ตาราง

use Kotchasan\Database;
// ดึงข้อมูลผู้ใช้พร้อมข้อมูล profile และ department
$usersWithProfile = Kotchasan\Database::create()
    ->select([
        'U.id',
        'U.name',
        'U.email',
        'P.phone',
        'P.address',
        'D.name as department_name'
    ])
    ->from('user U')
    ->leftJoin('profile P', 'U.id = P.user_id')
    ->leftJoin('department D', 'U.department_id = D.id')
    ->where(['U.status', 'active'])
    ->orderBy('U.name')
    ->fetchAll();

ตัวอย่างที่ 3: การใช้ Subquery

use Kotchasan\Database;
use Kotchasan\Database\Sql;

// สร้าง Subquery เพื่อดึง metadata
$metaSubquery = Kotchasan\Database::create()
    ->select(Sql::GROUP_CONCAT('D.value', null, ',', true))
    ->from('user_meta D')
    ->where(['D.member_id', '=', Sql::column('U.id')])
    ->where(['D.name', '=', 'skills']);

// Query หลักที่ใช้ Subquery
$usersWithSkills = Kotchasan\Database::create()
    ->select([
        'U.id',
        'U.name',
        'U.email',
        [$metaSubquery, 'skills']
    ])
    ->from('user U')
    ->where(['U.status', 'active'])
    ->orderBy('U.name')
    ->fetchAll();

ตัวอย่างที่ 4: การใช้ GROUP BY และ HAVING

use Kotchasan\Database;
// สถิติผู้ใช้ตาม department
$departmentStats = Kotchasan\Database::create()
    ->select([
        'D.name as department_name',
        'COUNT(U.id) as user_count',
        'AVG(U.salary) as avg_salary'
    ])
    ->from('user U')
    ->leftJoin('department D', 'U.department_id = D.id')
    ->where(['U.status', 'active'])
    ->groupBy('D.id')
    ->having('COUNT(U.id)', '>', 5)
    ->orderBy('user_count', 'DESC')
    ->fetchAll();

ตัวอย่างที่ 5: การใช้ WHERE ซับซ้อน

use Kotchasan\Database;
// ค้นหาผู้ใช้ด้วยเงื่อนไขซับซ้อน
$complexSearch = Kotchasan\Database::create()
    ->select(['id', 'name', 'email', 'department_id'])
    ->from('user')
    ->where(function ($q) {
        $q->where(['status', 'active'])
          ->orWhere(['status', 'pending']);
    })
    ->where(['age', '>=', 18])
    ->where(['department_id', [1, 2, 3, 5]])
    ->where(['created_at', '>=', '2023-01-01'])
    ->orderBy('created_at', 'DESC')
    ->limit(50)
    ->fetchAll();
public function limit(int $limit, int $offset = 0): QueryBuilderInterface;
public function toSql(): string;
public function execute(?array $params = null): ResultInterface;

}


### 2. QueryBuilder (Abstract Class)

คลาสพื้นฐานที่ implement QueryBuilderInterface และมีฟังก์ชันพื้นฐานร่วมกัน

```php
abstract class QueryBuilder implements QueryBuilderInterface
{
    protected ConnectionInterface $connection;
    protected string $table = '';
    protected ?string $alias = null;
    protected array $columns = [];
    protected array $wheres = [];
    protected array $joins = [];
    protected array $orders = [];
    protected array $namedBindings = [];
}

การใช้งาน SELECT Queries

SelectBuilder

คลาสสำหรับสร้างคำสั่ง SELECT

use Kotchasan\Database;

// SELECT พื้นฐาน
$query = Kotchasan\Database::createQuery()
    ->select(['id', 'name', 'email'])
    ->from('user U')
    ->where(['U.status', 'active'])
    ->orderBy('U.name', 'ASC')
    ->limit(10);

$users = $query->fetchAll();

การเลือกคอลัมน์

// เลือกคอลัมน์เฉพาะ
$query->select(['id', 'name', 'email']);

// เลือกทั้งหมด
$query->select('*');

// เลือกด้วย Alias
$query->select(['U.name AS username', 'U.email AS user_email']);

// เลือกด้วย SQL Function
$query->select(['COUNT(*) AS total', 'MAX(created_at) AS latest']);

การใช้ DISTINCT

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select(['category'])
    ->distinct()
    ->from('product');

การใช้ Subquery ในการเลือกคอลัมน์

use Kotchasan\Database;
// Subquery เป็นคอลัมน์
$subquery = Kotchasan\Database::createQuery()
    ->select('COUNT(*)')
    ->from('order O')
    ->where(['O.user_id', Sql::column('U.id')]);

$users = Kotchasan\Database::createQuery()
    ->select(['U.', [$subquery, 'order_count']])
    ->from('user U')
    ->fetchAll();

การใช้งาน WHERE Conditions

WHERE พื้นฐาน

// เงื่อนไขเดียว
$query->where(['status', 'active']);

// เงื่อนไขหลายแบบ
$query->where(['status', 'active'])
      ->where(['age', '>', 18])
      ->where(['city', 'Bangkok']);

รูปแบบการเขียน WHERE

// รูปแบบ [column, value] - ใช้ = เป็นค่าเริ่มต้น
$query->where(['username', 'admin']);

// รูปแบบ [column, operator, value]
$query->where(['age', '>', 18]);
$query->where(['status', '!=', 'inactive']);

// NULL checking
$query->where(['deleted_at', null]); // IS NULL
$query->where(['deleted_at', '!=', null]); // IS NOT NULL

// IN clause
$query->where(['id', [1, 2, 3, 4]]);
$query->where(['status', ['active', 'pending']]);

// NOT IN clause
$query->where(['id', '!=', [1, 2, 3]]);

OR WHERE

$query->where(['status', 'active'])
      ->orWhere(['status', 'pending']);

Nested WHERE (กลุ่มเงื่อนไข)

$query->where(function($q) {
    $q->where(['status', 'active'])
      ->orWhere(['status', 'pending']);
})->where(['age', '>', 18]);

// ผลลัพธ์: WHERE ((status = 'active' OR status = 'pending') AND age > 18)

Raw WHERE

// ใช้ Raw SQL
$query->whereRaw('FIND_IN_SET(?, tags)', 'AND', [5]);
$query->where('DATE(created_at) = CURDATE()');

Column-to-Column Comparison

use Kotchasan\Database\Sql;

$query->where(['U.created_at', '>', Sql::column('U.updated_at')]);
$query->where(['A.user_id', '=', Sql::column('B.id')]);

การใช้งาน JOIN

INNER JOIN

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select(['U.name', 'P.title'])
    ->from('user U')
    ->join('post P', 'U.id = P.user_id')
    ->fetchAll();

LEFT JOIN

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select(['U.name', 'P.title'])
    ->from('user U')
    ->leftJoin('post P', 'U.id = P.user_id');

RIGHT JOIN

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select(['U.name', 'P.title'])
    ->from('user U')
    ->rightJoin('post P', 'U.id = P.user_id');

JOIN ด้วยเงื่อนไขหลายแบบ

// JOIN ด้วย Array Conditions
$query->join('post P', [
    ['U.id', 'P.user_id'],
    ['P.status', 'published'],
    ['P.created_at', '>', '2024-01-01']
]);

// JOIN ด้วย Closure
$query->join('post P', function($join) {
    $join->where(['U.id', 'P.user_id'])
         ->where(['P.status', 'published']);
});

การใช้งาน ORDER BY, GROUP BY, HAVING

ORDER BY

// เรียงลำดับเดียว
$query->orderBy('name', 'ASC');
$query->orderBy('created_at', 'DESC');

// เรียงลำดับหลายคอลัมน์
$query->orderBy('status', 'ASC')
      ->orderBy('name', 'ASC');

GROUP BY

$query->select(['category', 'COUNT(*) as count'])
      ->from('product')
      ->groupBy('category');

// GROUP BY หลายคอลัมน์
$query->groupBy(['category', 'status']);

HAVING

$query->select(['category', 'COUNT(*) as count'])
      ->from('product')
      ->groupBy('category')
      ->having('COUNT(*)', '>', 5);

การใช้งาน LIMIT และ OFFSET

// LIMIT เท่านั้น
$query->limit(10);

// LIMIT และ OFFSET
$query->limit(10, 20); // LIMIT 10 OFFSET 20

// Pagination
$page = 2;
$perPage = 1; // 0;
$offset = ($page - 1) * $perPage;
$query->limit($perPage, $offset);

การดำเนินการและการดึงข้อมูล

การดึงข้อมูลทั้งหมด

// ดึงเป็น Array
$results = $query->fetchAll(true);

// ดึงเป็น Object
$results = $query->fetchAll(false);

การดึงข้อมูลแถวเดียว

// ดึงแถวแรก เป็น Array
$user = $query->first(true);

// ดึงแถวแรก เป็น Object
$user = $query->first(false);

// ตรวจสอบว่ามีข้อมูลหรือไม่
if ($user) {
    echo $user['name']; // หรือ $user->name
}

การนับจำนวน

use Kotchasan\Database;
$count = Kotchasan\Database::createQuery()
    ->selectCount()
    ->from('user')
    ->where(['status', 'active'])
    ->first()['count'];

การ Execute แบบกำหนดเอง

$result = $query->execute();
while ($row = $result->fetch()) {
    // ประมวลผลแต่ละแถว
}

การใช้งาน Subqueries

Subquery ใน WHERE

use Kotchasan\Database;
$subquery = Kotchasan\Database::createQuery()
    ->select('user_id')
    ->from('order')
    ->where(['status', 'completed']);

$users = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->where(['id', 'IN', $subquery])
    ->fetchAll();

Subquery ใน SELECT

use Kotchasan\Database;
$orderCount = Kotchasan\Database::createQuery()
    ->select('COUNT(*)')
    ->from('order O')
    ->where(['O.user_id', Sql::column('U.id')]);

$users = Kotchasan\Database::createQuery()
    ->select(['U.', [$orderCount, 'order_count']])
    ->from('user U')
    ->fetchAll();

Subquery ใน FROM

use Kotchasan\Database;
$subquery = Kotchasan\Database::createQuery()
    ->select(['user_id', 'COUNT(*) as order_count'])
    ->from('order')
    ->groupBy('user_id');

$result = Kotchasan\Database::createQuery()
    ->select(['U.name', 'S.order_count'])
    ->from([$subquery, 'S'])
    ->leftJoin('user U', 'U.id = S.user_id')
    ->fetchAll();

การใช้งาน SQL Functions

SQL Functions พื้นฐาน

use Kotchasan\Database\Sql;

// Date Functions
$query->select([
    Sql::YEAR('created_at'),
    Sql::MONTH('created_at'),
    Sql::DATE('created_at')
]);

// String Functions
$query->select([
    Sql::CONCAT('first_name', ' ', 'last_name'),
    Sql::UPPER('name'),
    Sql::LOWER('email')
]);

// Aggregate Functions
$query->select([
    Sql::COUNT('*'),
    Sql::SUM('amount'),
    Sql::AVG('score'),
    Sql::MAX('created_at'),
    Sql::MIN('created_at')
]);

GROUP_CONCAT

$query->select([
    'category',
    Sql::GROUP_CONCAT('name', null, ',', true)
])
->from('product')
->groupBy('category');

การใช้งาน INSERT Queries

InsertBuilder

use Kotchasan\Database;

// INSERT แถวเดียว
// INSERT แถวเดียว
$db = Kotchasan\Database::create();
$db->insert('user')
    ->values([
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'status' => 'active'
    ])
    ->execute();

$newId = $db->lastInsertId();

INSERT IGNORE

use Kotchasan\Database;
$result = Kotchasan\Database::createQuery()
    ->insert('user')
    ->ignore()
    ->values([
        'email' => 'john@example.com',
        'name' => 'John Doe'
    ])
    ->execute();

Batch INSERT

use Kotchasan\Database;
$users = [
    ['name' => 'John', 'email' => 'john@example.com'],
    ['name' => 'Jane', 'email' => 'jane@example.com'],
    ['name' => 'Bob', 'email' => 'bob@example.com']
];

$result = Kotchasan\Database::createQuery()
    ->insert('user')
    ->rows($users)
    ->execute();

การใช้งาน UPDATE Queries

UpdateBuilder

use Kotchasan\Database;
// UPDATE พื้นฐาน
$result = Kotchasan\Database::createQuery()
    ->update('user')
    ->set([
        'name' => 'John Smith',
        'updated_at' => date('Y-m-d H:i:s')
    ])
    ->where(['id', 1])
    ->execute();

$affectedRows = $result->rowCount();

UPDATE ด้วยเงื่อนไขซับซ้อน

use Kotchasan\Database;
$result = Kotchasan\Database::createQuery()
    ->update('user')
    ->set(['status' => 'inactive'])
    ->where(['last_login', '<', '2024-01-01'])
    ->where(['status', 'active'])
    ->limit(100)
    ->execute();

UPDATE ด้วย JOIN

use Kotchasan\Database;
$result = Kotchasan\Database::createQuery()
    ->update('user U')
    ->join('profile P', 'U.id = P.user_id')
    ->set(['U.status' => 'verified'])
    ->where(['P.verified', 1])
    ->execute();

การใช้งาน DELETE Queries

DeleteBuilder

use Kotchasan\Database;
// DELETE พื้นฐาน
$result = Kotchasan\Database::createQuery()
    ->delete('user')
    ->where(['status', 'inactive'])
    ->execute();

$deletedRows = $result->rowCount();

DELETE ด้วยเงื่อนไขซับซ้อน

use Kotchasan\Database;
$result = Kotchasan\Database::createQuery()
    ->delete('user')
    ->where(['created_at', '<', '2023-01-01'])
    ->where(['status', 'inactive'])
    ->limit(1000)
    ->execute();

DELETE ด้วย Subquery

use Kotchasan\Database;
$inactiveUsers = Kotchasan\Database::createQuery()
    ->select('id')
    ->from('user')
    ->where(['last_login', '<', '2023-01-01']);

$result = Kotchasan\Database::createQuery()
    ->delete('user_log')
    ->where(['user_id', 'IN', $inactiveUsers])
    ->execute();

การใช้งาน Caching

เปิดใช้งาน Cache

use Kotchasan\Database;
// Cache ด้วย TTL เริ่มต้น (3600 วินาที)
$users = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->cacheOn()
    ->fetchAll();

// Cache ด้วย TTL กำหนดเอง
$users = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->cacheOn(true, 7200) // 2 ชั่วโมง
    ->fetchAll();

ปิดใช้งาน Cache

use Kotchasan\Database;
$users = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->cacheOff()
    ->fetchAll();

Manual Cache Saving

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->cacheOn(false); // ไม่ save อัตโนมัติ

$users = $query->fetchAll();

// Save cache manually
$query->saveCache($users);

การ Debug และ Troubleshooting

การดู SQL ที่สร้างขึ้น

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->where(['status', 'active']);

// แสดง SQL
echo $query->debug(true);

// หรือ
$sql = $query->toSql();
echo $sql;

การดู Parameter Bindings

$bindings = $query->getBindings();
var_dump($bindings);

การใช้ EXPLAIN

use Kotchasan\Database;
$result = Kotchasan\Database::createQuery()
    ->select('*')
    ->from('user')
    ->where(['status', 'active'])
    ->explain()
    ->execute();

Best Practices

1. ใช้ Named Parameters

// ดี - ใช้ array format
$query->where(['status', $userStatus]);

// หลีกเลี่ยง - Raw SQL
$query->where("status = '$userStatus'"); // อันตราย!;

2. ใช้ Alias สำหรับตารางที่มีชื่อยาว

use Kotchasan\Database;
$query = Kotchasan\Database::createQuery()
    ->select(['U.name', 'UP.bio'])
    ->from('user U')
    ->leftJoin('user_profile UP', 'U.id = UP.user_id');

3. ใช้ Method Chaining

use Kotchasan\Database;
$users = Kotchasan\Database::createQuery()
    ->select(['id', 'name', 'email'])
    ->from('user')
    ->where(['status', 'active'])
    ->orderBy('name')
    ->limit(10)
    ->fetchAll();

4. จัดการ Error

use Kotchasan\Database;
try {
    $result = Kotchasan\Database::createQuery()
        ->insert('user')
        ->values($userData)
        ->execute();
} catch (Kotchasan\DatabaseException $e) {
    // จัดการ error
    error_log($e->getMessage());
}

5. ใช้ Transaction สำหรับการเปลี่ยนแปลงหลายตาราง

use Kotchasan\Database;
$db = Kotchasan\Database::getConnection();
$db->beginTransaction();

try {
    // INSERT user
    $userId = Kotchasan\Database::createQuery()
        ->insert('user')
        ->values($userData)
        ->execute()
        ->lastInsertId();

    // INSERT profile
    Kotchasan\Database::createQuery()
        ->insert('user_profile')
        ->values(['user_id' => $userId] + $profileData)
        ->execute();

    $db->commit();
} catch (Exception $e) {
    $db->rollback();
    throw $e;
}

ตัวอย่างการใช้งานจริง

1. ระบบ User Management

use Kotchasan\Database;
class UserRepository
{
    public function findActiveUsers(int $limit = 10): array
    {
        return Kotchasan\Database::createQuery()
            ->select(['id', 'name', 'email', 'created_at'])
            ->from('user')
            ->where(['status', 'active'])
            ->where(['deleted_at', null])
            ->orderBy('created_at', 'DESC')
            ->limit($limit)
            ->fetchAll(true);
    }

    public function getUserWithProfile(int $userId): ?array
    {
        return Kotchasan\Database::createQuery()
            ->select(['U.*', 'UP.bio', 'UP.avatar'])
            ->from('user U')
            ->leftJoin('user_profile UP', 'U.id = UP.user_id')
            ->where(['U.id', $userId])
            ->first(true);
    }

    public function searchUsers(string $keyword): array
    {
        return Kotchasan\Database::createQuery()
            ->select(['id', 'name', 'email'])
            ->from('user')
            ->where(function($q) use ($keyword) {
                $q->where(['name', 'LIKE', "%$keyword%"])
                  ->orWhere(['email', 'LIKE', "%$keyword%"]);
            })
            ->where(['status', 'active'])
            ->orderBy('name')
            ->fetchAll(true);
    }
}

2. ระบบ Reporting

use Kotchasan\Database;
class ReportService
{
    public function getUserStats(): array
    {
        return Kotchasan\Database::createQuery()
            ->select([
                'status',
                'COUNT(*) as count',
                'AVG(DATEDIFF(NOW(), created_at)) as avg_days'
            ])
            ->from('user')
            ->groupBy('status')
            ->orderBy('count', 'DESC')
            ->fetchAll(true);
    }

    public function getMonthlyRegistrations(int $year): array
    {
        return Kotchasan\Database::createQuery()
            ->select([
                Sql::MONTH('created_at'),
                'COUNT(*) as registrations'
            ])
            ->from('user')
            ->where([Sql::YEAR('created_at'), $year])
            ->groupBy(Sql::MONTH('created_at'))
            ->orderBy(Sql::MONTH('created_at'))
            ->fetchAll(true);
    }
}

3. ระบบ E-commerce

use Kotchasan\Database;
class OrderRepository
{
    public function getOrdersWithItems(int $userId): array
    {
        $orderItems = Kotchasan\Database::createQuery()
            ->select([
                'OI.order_id',
                Sql::GROUP_CONCAT('P.name', null, ', ', true)
            ])
            ->from('order_item OI')
            ->join('product P', 'OI.product_id = P.id')
            ->groupBy('OI.order_id');

        return Kotchasan\Database::createQuery()
            ->select(['O.', [$orderItems, 'items']])
            ->from('order O')
            ->where(['O.user_id', $userId])
            ->orderBy('O.created_at', 'DESC')
            ->fetchAll(true);
    }

    public function getTopSellingProducts(int $limit = 10): array
    {
        return Kotchasan\Database::createQuery()
            ->select([
                'P.name',
                'SUM(OI.quantity) as total_sold',
                'SUM(OI.quantity  OI.price) as total_revenue'
            ])
            ->from('product P')
            ->join('order_item OI', 'P.id = OI.product_id')
            ->join('order O', 'OI.order_id = O.id')
            ->where(['O.status', 'completed'])
            ->groupBy('P.id')
            ->orderBy('total_sold', 'DESC')
            ->limit($limit)
            ->fetchAll(true);
    }
}

การแก้ไขปัญหาที่พบบ่อย

1. SQL Injection Prevention

QueryBuilder ป้องกัน SQL Injection โดยอัตโนมัติเมื่อใช้ parameter binding:

// ปลอดภัย - ใช้ parameter binding
$query->where(['name', $userInput]);

// อันตราย - Raw SQL
$query->where("name = '$userInput'");

2. Performance Optimization

// ใช้ Index ที่เหมาะสม
$query->where(['status', 'active']) // ถ้า status มี index
      ->where(['created_at', '>', $date]); // ถ้า created_at มี index

// ใช้ LIMIT เมื่อไม่ต้องการข้อมูลทั้งหมด
$query->limit(100);

// ใช้ Cache สำหรับข้อมูลที่ไม่เปลี่ยนแปลงบ่อย
$query->cacheOn(true, 3600);

3. Memory Management

// สำหรับข้อมูลจำนวนมาก ใช้ cursor
$result = $query->execute();
while ($row = $result->fetch()) {
    // ประมวลผลทีละแถว
    processRow($row);
}
$result->close();

InsertBuilder - การสร้างคำสั่ง INSERT

InsertBuilder เป็นคลาสสำหรับสร้างคำสั่ง INSERT ที่รองรับการ Insert ข้อมูลทีละ record หรือหลาย records พร้อมกัน (Batch Insert)

เมธอดหลักของ InsertBuilder

insert(string $table)

กำหนดตารางปลายทางสำหรับการ INSERT

use Kotchasan\Database;
$query = Kotchasan\Database::create()->insert('user');

values(array $data)

กำหนดข้อมูลที่จะ INSERT (สำหรับ record เดียว)

$query->values([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'status' => 'active',
    'created_at' => date('Y-m-d H:i:s')
]);

rows(array $rows)

กำหนดข้อมูลหลาย records สำหรับ Batch Insert

$query->rows([
    [
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'status' => 'active'
    ],
    [
        'name' => 'Jane Smith',
        'email' => 'jane@example.com',
        'status' => 'pending'
    ]
]);

ignore()

ใช้ INSERT IGNORE เพื่อข้าม record ที่ซ้ำ

$query->ignore()->values([
    'email' => 'existing@example.com',
    'name' => 'Duplicate User'
]);

ตัวอย่างการใช้งาน InsertBuilder

การ Insert ข้อมูลเดียว

use Kotchasan\Database;
$userId = Kotchasan\Database::create()
    ->insert('user')
    ->values([
        'name' => 'John Doe',
        'email' => 'john.doe@example.com',
        'password' => password_hash('mypassword', PASSWORD_DEFAULT),
        'status' => 'active',
        'created_at' => date('Y-m-d H:i:s')
    ])
    ->execute();

การ Insert หลาย records

use Kotchasan\Database;
$result = Kotchasan\Database::create()
    ->insert('user')
    ->rows([
        [
            'name' => 'Alice Johnson',
            'email' => 'alice@example.com',
            'status' => 'active'
        ],
        [
            'name' => 'Bob Smith',
            'email' => 'bob@example.com',
            'status' => 'pending'
        ]
    ])
    ->execute();

UpdateBuilder - การสร้างคำสั่ง UPDATE

UpdateBuilder เป็นคลาสสำหรับสร้างคำสั่ง UPDATE ที่ปลอดภัยและมีประสิทธิภาพ

เมธอดหลักของ UpdateBuilder

update(string $table)

กำหนดตารางที่จะ UPDATE

use Kotchasan\Database;
$query = Kotchasan\Database::create()->update('user');

set(array $data)

กำหนดข้อมูลที่จะอัปเดต

$query->set([
    'name' => 'Updated Name',
    'updated_at' => date('Y-m-d H:i:s')
]);

where($condition)

เพิ่มเงื่อนไข WHERE (จำเป็นสำหรับความปลอดภัย)

$query->where(['id', 123]);

ตัวอย่างการใช้งาน UpdateBuilder

การ Update ข้อมูลพื้นฐาน

use Kotchasan\Database;
$affected = Kotchasan\Database::create()
    ->update('user')
    ->set([
        'name' => 'John Updated',
        'email' => 'john.updated@example.com',
        'updated_at' => date('Y-m-d H:i:s')
    ])
    ->where(['id', 123])
    ->execute();

การ Update ด้วยการคำนวณ

use Kotchasan\Database;
use Kotchasan\Database\Sql;

$affected = Kotchasan\Database::create()
    ->update('user')
    ->set([
        'login_count' => Sql::raw('login_count + 1'),
        'last_login' => date('Y-m-d H:i:s')
    ])
    ->where(['id', 123])
    ->execute();

DeleteBuilder - การสร้างคำสั่ง DELETE

DeleteBuilder เป็นคลาสสำหรับสร้างคำสั่ง DELETE อย่างปลอดภัย

เมธอดหลักของ DeleteBuilder

delete(string $table)

กำหนดตารางที่จะ DELETE

use Kotchasan\Database;
$query = Kotchasan\Database::create()->delete('user');

where($condition)

เพิ่มเงื่อนไข WHERE (จำเป็นสำหรับความปลอดภัย)

$query->where(['id', 123]);

ตัวอย่างการใช้งาน DeleteBuilder

การลบข้อมูลเดียว

use Kotchasan\Database;
$deleted = Kotchasan\Database::create()
    ->delete('user')
    ->where(['id', 123])
    ->execute();

การลบข้อมูลตามเงื่อนไข

use Kotchasan\Database;
$deleted = Kotchasan\Database::create()
    ->delete('user')
    ->where(['status', 'inactive'])
    ->where(['updated_at', '<', date('Y-m-d', strtotime('-1 year'))])
    ->execute();

Advanced Features - ฟีเจอร์ขั้นสูง

การใช้ Transactions

use Kotchasan\Database;
try {
    Kotchasan\Database::beginTransaction();

    // สร้างผู้ใช้ใหม่
    $userId = Kotchasan\Database::create()
        ->insert('user')
        ->values(['name' => 'John', 'email' => 'john@example.com'])
        ->execute();

    // สร้าง profile
    Kotchasan\Database::create()
        ->insert('user_profile')
        ->values(['user_id' => $userId, 'phone' => '02-123-4567'])
        ->execute();

    Kotchasan\Database::commit();
} catch (Exception $e) {
    Kotchasan\Database::rollback();
    throw $e;
}

การใช้ Raw SQL

use Kotchasan\Database\Sql;

// Raw expressions ใน SELECT
$query->select([
    'id',
    'name',
    Sql::raw('COUNT(*) as total'),
    Sql::raw('AVG(score) as average_score')
]);

// Raw expressions ใน WHERE
$query->where(Sql::raw('FIND_IN_SET(?, tags)'), [5]);

// Raw expressions ใน ORDER BY
$query->orderBy(Sql::raw('FIELD(status, "active", "pending", "inactive")'));

การใช้ Subqueries

use Kotchasan\Database;
// Subquery ใน SELECT
$subquery = Kotchasan\Database::create()
    ->select('COUNT(*)')
    ->from('orders')
    ->where(['customer_id', '=', Sql::column('customers.id')]);

$customers = Kotchasan\Database::create()
    ->select(['customers.*', [$subquery, 'order_count']])
    ->from('customers')
    ->fetchAll();

// Subquery ใน WHERE
$activeUsers = Kotchasan\Database::create()
    ->select('id')
    ->from('users')
    ->where(['status', 'active']);

$orders = Kotchasan\Database::create()
    ->select('*')
    ->from('orders')
    ->where(['customer_id', 'IN', $activeUsers])
    ->fetchAll();

Best Practices - แนวทางปฏิบัติที่ดี

1. ความปลอดภัย

  • ใช้ Parameter Binding เสมอ แทนการต่อ string
  • ตรวจสอบ user input ก่อนส่งเข้า QueryBuilder
  • ใช้ whitelist สำหรับชื่อคอลัมน์และตาราง

2. ประสิทธิภาพ

  • ใช้ limit() เมื่อไม่ต้องการข้อมูลทั้งหมด
  • เลือกเฉพาะคอลัมน์ที่จำเป็น แทนการใช้ *
  • ใช้ index ที่เหมาะสมสำหรับเงื่อนไข WHERE

3. การจัดการข้อผิดพลาด

  • ใช้ try-catch สำหรับการดำเนินการที่สำคัญ
  • ใช้ Transaction สำหรับการดำเนินการหลายขั้นตอน
  • บันทึก error log เพื่อการ debug

4. การเขียนโค้ดที่อ่านง่าย

  • แบ่งบรรทัดสำหรับ method chain ที่ยาว
  • ใช้ตัวแปรสำหรับ query ที่ซับซ้อน
  • เพิ่ม comment อธิบายเงื่อนไขที่ซับซ้อน
use Kotchasan\Database;
// ตัวอย่าง code ที่อ่านง่าย
$userQuery = Kotchasan\Database::create()
    ->select([
        'U.id',
        'U.name',
        'U.email',
        'P.phone',
        'D.name as department'
    ])
    ->from('user U')
    ->leftJoin('profile P', 'U.id = P.user_id')
    ->leftJoin('department D', 'U.department_id = D.id')
    ->where(['U.status', 'active'])
    ->where(['U.created_at', '>=', '2023-01-01'])
    ->orderBy('U.name', 'ASC')
    ->limit(50);

$users = $userQuery->fetchAll();

QueryBuilder ใน Kotchasan Framework เป็นเครื่องมือที่ทรงพลังสำหรับการจัดการฐานข้อมูล ช่วยให้การเขียนโค้ดเป็นระเบียบ ปลอดภัย และง่ายต่อการบำรุงรักษา