Kotchasan Framework Documentation

Kotchasan Framework Documentation

Kotchasan\Cache\QueryCache

TH 05 Feb 2026 07:40

Kotchasan\Cache\QueryCache

QueryCache เป็น cache wrapper เฉพาะสำหรับ database query caching โดยจะสร้าง cache keys จาก SQL queries และ parameters โดยอัตโนมัติ

สารบัญ

  1. ภาพรวม
  2. การติดตั้งและใช้งาน
  3. เมธอดหลัก
  4. ตัวอย่างการใช้งาน
  5. Best Practices

ภาพรวม

QueryCache มีคุณสมบัติดังนี้:

  • Automatic Key Generation: สร้าง cache key จาก SQL + parameters
  • Query Builder Integration: ทำงานร่วมกับ QueryBuilder ได้โดยตรง
  • Enable/Disable: เปิด/ปิด caching ได้ตลอดเวลา
  • Statistics: ติดตาม hits, misses, writes
  • Table Invalidation: ล้าง cache เมื่อตารางถูกแก้ไข

เมื่อไหร่ควรใช้:

  • ต้องการ cache ผลลัพธ์ของ database queries
  • Queries ที่ซับซ้อนและใช้เวลาประมวลผล
  • ข้อมูลที่ไม่เปลี่ยนแปลงบ่อย

การติดตั้งและใช้งาน

ความต้องการ

  • PHP 7.4 หรือสูงกว่า
  • Kotchasan Framework
  • Cache implementation (FileCache, RedisCache, หรือ MemoryCache)

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

use Kotchasan\Cache\QueryCache;
use Kotchasan\Cache\FileCache;
use Kotchasan\Database;

// สร้าง underlying cache
$fileCache = new FileCache(['path' => ROOT_PATH . 'datas/cache/']);

// สร้าง QueryCache
$queryCache = new QueryCache($fileCache, 3600);

// ใช้กับ Database
Database::setCache($fileCache, 3600);

// Queries จะถูก cache อัตโนมัติ
$db = Database::create();
$users = $db->select('*')
    ->from('users')
    ->where('status', '=', 'active')
    ->cache(true)  // เปิด cache สำหรับ query นี้
    ->execute();

เมธอดหลัก

__construct()

สร้าง QueryCache instance

Signature:

public function __construct(CacheInterface $cache, int $defaultTtl = 3600)

Parameters:

  • $cache - Cache implementation (FileCache, RedisCache, etc.)
  • $defaultTtl - TTL เริ่มต้น (วินาที)

get()

ดึง cached query result

Signature:

public function get(QueryBuilderInterface $query)

Parameters:

  • $query - QueryBuilder instance

Returns: Cached result หรือ null ถ้าไม่พบ

set()

Cache query result

Signature:

public function set(QueryBuilderInterface $query, $result, ?int $ttl = null): bool

Parameters:

  • $query - QueryBuilder instance
  • $result - ผลลัพธ์ที่จะ cache
  • $ttl - TTL เป็นวินาที (optional)

generateKey()

สร้าง cache key จาก query

Signature:

protected function generateKey(QueryBuilderInterface $query): string

getByKey() / setByKey()

ใช้ raw SQL แทน QueryBuilder

Signatures:

public function getByKey(string $sql, array $params = [])
public function setByKey(string $sql, array $params, $result, ?int $ttl = null): bool

invalidate()

ลบ cached query

Signature:

public function invalidate(QueryBuilderInterface $query): bool

invalidateTable()

ล้าง cache ทั้งหมดของตาราง

Signature:

public function invalidateTable(string $table): bool

enable() / disable() / isEnabled()

เปิด/ปิด caching

Signatures:

public function enable(): self
public function disable(): self
public function isEnabled(): bool

getStats()

ดึงสถิติ

Signature:

public function getStats(): array

Returns:

[
    'hits' => 500,
    'misses' => 100,
    'writes' => 300,
    'enabled' => true,
    'default_ttl' => 3600,
    'backend' => 'Kotchasan\\Cache\\FileCache',
    'backend_stats' => [...] // สถิติของ underlying cache
]

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

1. การ Cache Query พื้นฐาน

use Kotchasan\Cache\QueryCache;
use Kotchasan\Cache\FileCache;
use Kotchasan\Database;

// Setup
$fileCache = new FileCache(['path' => ROOT_PATH . 'datas/cache/']);
$queryCache = new QueryCache($fileCache, 3600);

$db = Database::create();

// สร้าง query
$query = $db->select('*')
    ->from('products')
    ->where('category', '=', 'electronics')
    ->orderBy('price');

// ตรวจสอบ cache ก่อน
$products = $queryCache->get($query);
if ($products === null) {
    // ไม่มี cache, execute query
    $products = $query->execute();

    // Cache ผลลัพธ์
    $queryCache->set($query, $products, 600);
}

// ใช้ข้อมูล
foreach ($products as $product) {
    echo $product->name . "\n";
}

2. การ Invalidate Cache เมื่อข้อมูลเปลี่ยน

use Kotchasan\Cache\QueryCache;
use Kotchasan\Cache\RedisCache;
use Kotchasan\Database;

class ProductRepository
{
    private QueryCache $queryCache;
    private Database $db;

    public function __construct()
    {
        $redisCache = new RedisCache('localhost', 6379);
        $this->queryCache = new QueryCache($redisCache, 600);
        $this->db = Database::create();
    }

    public function findByCategory(string $category): array
    {
        $sql = "SELECT * FROM products WHERE category = ?";
        $params = [$category];

        // ลอง cache ก่อน
        $result = $this->queryCache->getByKey($sql, $params);
        if ($result !== null) {
            return $result;
        }

        // Query จาก database
        $result = $this->db->select('*')
            ->from('products')
            ->where('category', '=', $category)
            ->execute();

        // Cache
        $this->queryCache->setByKey($sql, $params, $result);

        return $result;
    }

    public function update(int $id, array $data): bool
    {
        $result = $this->db->update('products')
            ->set($data)
            ->where('id', '=', $id)
            ->execute();

        if ($result) {
            // ล้าง cache ที่เกี่ยวข้อง
            $this->queryCache->invalidateTable('products');
        }

        return $result;
    }
}

3. การเปิด/ปิด Cache ตามสถานการณ์

use Kotchasan\Cache\QueryCache;
use Kotchasan\Cache\MemoryCache;

$queryCache = new QueryCache(new MemoryCache(), 600);

// ปิด cache ระหว่าง development หรือ debugging
if (defined('DEBUG') && DEBUG) {
    $queryCache->disable();
}

// หรือปิดชั่วคราวสำหรับ queries ที่ต้องการข้อมูลล่าสุด
$queryCache->disable();
$realTimeData = $db->select('*')
    ->from('live_stats')
    ->execute();
$queryCache->enable();

4. การดูสถิติ Cache

$db = Database::create();

// Execute queries...
for ($i = 0; $i < 100; $i++) {
    $users = $db->select('*')
        ->from('users')
        ->where('id', '=', $i % 10)
        ->cache(true, 60)
        ->execute();
}

// ดูสถิติ
$queryCache = Database::getQueryCache();
$stats = $queryCache->getStats();

echo "Cache Performance:\n";
echo "- Hits: {$stats['hits']}\n";
echo "- Misses: {$stats['misses']}\n";
echo "- Hit Rate: " . round($stats['hits'] / ($stats['hits'] + $stats['misses']) * 100, 2) . "%\n";

5. การใช้กับ Kotchasan\Database โดยตรง

use Kotchasan\Database;
use Kotchasan\Cache\CacheFactory;

// กำหนดค่า cache ให้ Database
Database::configureCache([
    'driver' => 'file',
    'path' => ROOT_PATH . 'datas/cache/'
], 3600);

$db = Database::create();

// Query พร้อม cache
$users = $db->select('*')
    ->from('users')
    ->where('status', '=', 'active')
    ->cache(true, 600)  // cache 10 นาที
    ->execute();

// Query ที่สอง (ถ้า parameters เหมือนกัน จะได้จาก cache)
$users = $db->select('*')
    ->from('users')
    ->where('status', '=', 'active')
    ->cache(true, 600)
    ->execute();  // จาก cache!

Best Practices

1. ใช้ TTL ที่เหมาะสมกับข้อมูล

// ข้อมูลที่ไม่ค่อยเปลี่ยน - TTL ยาว
$queryCache->set($categoryQuery, $categories, 86400); // 24 ชั่วโมง

// ข้อมูลที่เปลี่ยนบ่อย - TTL สั้น
$queryCache->set($orderQuery, $orders, 60); // 1 นาที

// ข้อมูล real-time - ไม่ cache
$queryCache->disable();

2. Invalidate Cache อย่างถูกต้อง

// เมื่อ INSERT/UPDATE/DELETE ควร invalidate cache ที่เกี่ยวข้อง
function updateUser($id, $data)
{
    $db->update('users')->set($data)->where('id', '=', $id)->execute();

    // Invalidate cache
    $queryCache->invalidateTable('users');
}

3. ใช้ Cache Backend ที่เหมาะสม

// Development: MemoryCache
$cache = new MemoryCache();

// Single server: FileCache
$cache = new FileCache(['path' => '/tmp/cache/']);

// Multiple servers: RedisCache
$cache = new RedisCache('redis.example.com', 6379);

ข้อควรระวัง

⚠️ Warning:

  • อย่า cache queries ที่มีข้อมูลที่เปลี่ยนบ่อย
  • อย่าลืม invalidate cache เมื่อข้อมูลถูกแก้ไข
  • ระวัง stale data

💡 Tip: ใช้ short TTL สำหรับข้อมูลที่เปลี่ยนบ่อย และ long TTL สำหรับ static data

คลาสที่เกี่ยวข้อง

  • CacheFactory - สร้าง cache instances
  • [FileCache] - Cache แบบไฟล์
  • MemoryCache - Memory Cache
  • RedisCache - Redis Cache
  • Database - คลาสหลักสำหรับฐานข้อมูล