Kotchasan Framework Documentation
QueryBuilder - ตัวสร้างคำสั่ง SQL
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
สารบัญ
- การติดตั้งและการใช้งานเบื้องต้น
- SelectBuilder - การสร้างคำสั่ง SELECT
- InsertBuilder - การสร้างคำสั่ง INSERT
- UpdateBuilder - การสร้างคำสั่ง UPDATE
- DeleteBuilder - การสร้างคำสั่ง DELETE
- Advanced Features - ฟีเจอร์ขั้นสูง
- 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 เป็นเครื่องมือที่ทรงพลังสำหรับการจัดการฐานข้อมูล ช่วยให้การเขียนโค้ดเป็นระเบียบ ปลอดภัย และง่ายต่อการบำรุงรักษา