Kotchasan Framework Documentation
FileCache - File-based Cache
FileCache - File-based Cache
ภาพรวม
FileCache เป็น Cache driver ที่เก็บข้อมูลในรูปแบบไฟล์บนระบบไฟล์ เป็น Cache driver ที่ไม่ต้องติดตั้งซอฟต์แวร์เพิ่มเติม และเหมาะสำหรับเว็บไซต์ขนาดเล็กถึงกลาง
Propertiesหลัก
- No Dependencies: ไม่ต้องติดตั้งซอฟต์แวร์เพิ่มเติม
- TTL Support: รองรับ Time To Live (TTL)
- Serialization: เก็บข้อมูลประเภทใดก็ได้ด้วย serialization
- Directory Management: จัดการโฟลเดอร์ cache อัตโนมัติ
- Thread Safe: ปลอดภัยสำหรับUsageแบบ concurrent
- Batch Operations: รองรับการทำงานกับหลาย keys พร้อมกัน
การติดตั้งและUsage
การสร้าง FileCache Instance
use Kotchasan\Cache\FileCache;
// สร้าง FileCache พื้นฐาน
$cache = new FileCache('/var/cache/myapp');
// ตรวจสอบสิทธิ์และสร้างโฟลเดอร์อัตโนมัติ
try {
$cache = new FileCache('/var/cache/secure');
} catch (ConfigurationException $e) {
echo "Cache configuration error: " . $e->getMessage();
}Usageพื้นฐาน
// เก็บข้อมูลใน cache
$cache->set('user:123', [
'id' => 123,
'name' => 'John Doe',
'email' => 'john@example.com'
], 3600); // TTL 1 ชั่วโมง
// ดึงข้อมูลจาก cache
$userData = $cache->get('user:123');
// ตรวจสอบว่ามี cache หรือไม่
if ($cache->has('user:123')) {
$userData = $cache->get('user:123');
} else {
// โหลดข้อมูลจากแหล่งอื่น
$userData = loadUserFromDatabase(123);
$cache->set('user:123', $userData, 3600);
}
// ลบ cache
$cache->delete('user:123');
// ล้าง cache ทั้งหมด
$cache->clear();Methodsหลักของ FileCache
__construct(string $cacheDir)
สร้าง FileCache instance และตั้งค่าโฟลเดอร์ cache
// โฟลเดอร์ที่มีอยู่แล้ว
$cache = new FileCache('/existing/cache/directory');
// โฟลเดอร์ที่ยังไม่มี (จะสร้างอัตโนมัติ)
$cache = new FileCache('/new/cache/directory');
// จะเกิด ConfigurationException ถ้าไม่สามารถสร้างโฟลเดอร์ได้set(string $key, $value, ?int $ttl = null): bool
เก็บข้อมูลใน cache
// เก็บข้อมูล string
$cache->set('message', 'Hello World', 300); // 5 นาที
// เก็บข้อมูล array
$cache->set('config', [
'debug' => true,
'version' => '1.0.0',
'features' => ['auth', 'api', 'cache']
], 3600);
// เก็บข้อมูล object
$user = new stdClass();
$user->id = 123;
$user->name = 'John';
$cache->set('user_object', $user, 1800);
// เก็บไม่มี TTL (ไม่หมดอายุ)
$cache->set('permanent_data', 'This will not expire');get(string $key, $default = null)
ดึงข้อมูลจาก cache
// ดึงข้อมูลพื้นฐาน
$value = $cache->get('message');
// ดึงข้อมูลพร้อม default value
$config = $cache->get('config', [
'debug' => false,
'version' => '1.0.0'
]);
// ตรวจสอบประเภทข้อมูล
$userData = $cache->get('user:123');
if (is_array($userData)) {
echo "User name: " . $userData['name'];
}has(string $key): bool
ตรวจสอบว่ามี cache key หรือไม่
if ($cache->has('user:123')) {
$user = $cache->get('user:123');
echo "Found user in cache";
} else {
echo "User not in cache";
}
// ใช้ร่วมกับ lazy loading
function getConfig($section) {
global $cache;
$key = "config:{$section}";
if (!$cache->has($key)) {
$config = loadConfigFromFile($section);
$cache->set($key, $config, 3600);
return $config;
}
return $cache->get($key);
}delete(string $key): bool
ลบ cache key
use Kotchasan\Database;
// ลบ cache เดียว
$deleted = $cache->delete('user:123');
if ($deleted) {
echo "Cache deleted successfully";
} else {
echo "Cache key not found";
}
// ลบ cache เมื่อข้อมูลเปลี่ยน
function updateUser($userId, $data) {
// อัปเดตฐานข้อมูล
Kotchasan\Database::create()
->update('users')
->set($data)
->where(['id', $userId])
->execute();
// ลบ cache ที่เกี่ยวข้อง
global $cache;
$cache->delete("user:{$userId}");
$cache->delete("user_profile:{$userId}");
}clear(): bool
ล้าง cache ทั้งหมด
// ล้าง cache ทั้งหมด
$cache->clear();
// ใช้ในการทำความสะอาดระบบ
function maintenanceCleanup() {
global $cache;
echo "Clearing all cache...";
if ($cache->clear()) {
echo "Cache cleared successfully";
} else {
echo "Failed to clear cache";
}
}Batch Operations
setMultiple(array $values, ?int $ttl = null): bool
เก็บข้อมูลหลาย keys พร้อมกัน
// เก็บข้อมูลหลาย users
$users = [
'user:123' => ['name' => 'John', 'email' => 'john@example.com'],
'user:124' => ['name' => 'Jane', 'email' => 'jane@example.com'],
'user:125' => ['name' => 'Bob', 'email' => 'bob@example.com']
];
$cache->setMultiple($users, 3600);
// เก็บ configuration หลายส่วน
$configs = [
'app:database' => ['host' => 'localhost', 'port' => 3306],
'app:redis' => ['host' => 'redis-server', 'port' => 6379],
'app:email' => ['smtp' => 'smtp.gmail.com', 'port' => 587]
];
$cache->setMultiple($configs, 86400); // 24 ชั่วโมง;getMultiple(array $keys, $default = null): array
ดึงข้อมูลหลาย keys พร้อมกัน
// ดึงข้อมูล users หลายคน
$userIds = ['user:123', 'user:124', 'user:125'];
$users = $cache->getMultiple($userIds);
foreach ($users as $key => $user) {
if ($user !== null) {
echo "User {$key}: " . $user['name'] . "\n";
}
}
// ดึงข้อมูลพร้อม default values
$configKeys = ['app:database', 'app:redis', 'app:email'];
$configs = $cache->getMultiple($configKeys, []);
// ตรวจสอบข้อมูลที่ได้
foreach ($configs as $key => $config) {
if (empty($config)) {
echo "Config {$key} not found in cache\n";
}
}deleteMultiple(array $keys): bool
ลบหลาย keys พร้อมกัน
// ลบ cache users หลายคน
$userKeys = ['user:123', 'user:124', 'user:125'];
$cache->deleteMultiple($userKeys);
// ลบ cache ที่เกี่ยวข้องกับ feature
$featureKeys = [
'feature_flags:auth',
'feature_flags:api',
'feature_flags:notifications'
];
$cache->deleteMultiple($featureKeys);ExampleUsageในโปรเจกต์จริง
1. User Profile Cache
use Kotchasan\Database;
class UserProfileCache {
private $cache;
public function __construct() {
$this->cache = new FileCache('/var/cache/user_profiles');
}
public function getProfile($userId) {
$cacheKey = "profile:{$userId}";
$profile = $this->cache->get($cacheKey);
if ($profile === null) {
$profile = $this->loadProfileFromDatabase($userId);
if ($profile) {
$this->cache->set($cacheKey, $profile, 1800); // 30 นาที
}
}
return $profile;
}
public function updateProfile($userId, $data) {
// อัปเดตฐานข้อมูล
$this->updateProfileInDatabase($userId, $data);
// ลบ cache
$this->cache->delete("profile:{$userId}");
// โหลดข้อมูลใหม่และ cache
return $this->getProfile($userId);
}
public function preloadProfiles($userIds) {
$cacheKeys = array_map(function($id) {
return "profile:{$id}";
}, $userIds);
$cachedProfiles = $this->cache->getMultiple($cacheKeys);
$missingIds = [];
foreach ($userIds as $userId) {
$key = "profile:{$userId}";
if ($cachedProfiles[$key] === null) {
$missingIds[] = $userId;
}
}
if (!empty($missingIds)) {
$profiles = $this->loadMultipleProfilesFromDatabase($missingIds);
$cacheData = [];
foreach ($profiles as $profile) {
$cacheData["profile:{$profile['id']}"] = $profile;
}
$this->cache->setMultiple($cacheData, 1800);
}
}
private function loadProfileFromDatabase($userId) {
return Kotchasan\Database::create()
->select(['id', 'name', 'email', 'avatar', 'settings'])
->from('user_profiles')
->where(['user_id', $userId])
->first();
}
private function loadMultipleProfilesFromDatabase($userIds) {
return Kotchasan\Database::create()
->select(['id', 'name', 'email', 'avatar', 'settings'])
->from('user_profiles')
->where(['user_id', $userIds])
->fetchAll();
}
}2. Configuration Cache
class ConfigCache {
private $cache;
private $configPath;
public function __construct($configPath = '/etc/myapp') {
$this->cache = new FileCache('/var/cache/config');
$this->configPath = $configPath;
}
public function get($section, $key = null) {
$cacheKey = "config:{$section}";
$config = $this->cache->get($cacheKey);
if ($config === null) {
$configFile = $this->configPath . "/{$section}.php";
if (file_exists($configFile)) {
$config = include $configFile;
$this->cache->set($cacheKey, $config, 3600); // 1 ชั่วโมง
} else {
$config = [];
}
}
if ($key !== null) {
return $config[$key] ?? null;
}
return $config;
}
public function refresh($section = null) {
if ($section) {
$this->cache->delete("config:{$section}");
} else {
// ลบ config cache ทั้งหมด
$this->clearConfigCache();
}
}
public function warmup() {
$configFiles = glob($this->configPath . '/*.php');
$configs = [];
foreach ($configFiles as $file) {
$section = basename($file, '.php');
$config = include $file;
$configs["config:{$section}"] = $config;
}
$this->cache->setMultiple($configs, 3600);
}
private function clearConfigCache() {
// ในUsageจริงอาจต้องใช้ pattern matching
// หรือเก็บรายการ config sections ไว้
$sections = ['database', 'redis', 'email', 'app'];
$keys = array_map(function($section) {
return "config:{$section}";
}, $sections);
$this->cache->deleteMultiple($keys);
}
}
// Usage
$config = new ConfigCache();
// ดึง config section
$dbConfig = $config->get('database');
// ดึง config key เฉพาะ
$dbHost = $config->get('database', 'host');
// Refresh config
$config->refresh('database');
// Warmup cache
$config->warmup();
*/3. Page Cache
class PageCache {
private $cache;
public function __construct() {
$this->cache = new FileCache('/var/cache/pages');
}
public function get($url, $params = []) {
$cacheKey = $this->generateCacheKey($url, $params);
return $this->cache->get($cacheKey);
}
$ttl = 360; // 0) {
$cacheKey = $this->generateCacheKey($url, $params);
return $this->cache->set($cacheKey, [
'content' => $content,
'cached_at' => time(),
'url' => $url,
'params' => $params
], $ttl);
}
public function invalidate($url, $params = []) {
$cacheKey = $this->generateCacheKey($url, $params);
return $this->cache->delete($cacheKey);
}
public function invalidatePattern($pattern) {
// ในUsageจริงอาจต้องเก็บ metadata ของ cache keys
// หรือใช้ directory structure เพื่อง่ายต่อการลบ
// ตัวอย่างการลบ cache ทั้งหมดที่เกี่ยวข้องกับ user
if (strpos($pattern, 'user:') === 0) {
$userId = substr($pattern, 5);
$keysToDelete = [
"page:user/{$userId}",
"page:user/{$userId}/profile",
"page:user/{$userId}/settings"
];
$this->cache->deleteMultiple($keysToDelete);
}
}
private function generateCacheKey($url, $params) {
$key = 'page:' . $url;
if (!empty($params)) {
ksort($params);
$key .= ':' . md5(serialize($params));
}
return $key;
}
}
// Middleware สำหรับ cache pages
function pageCacheMiddleware($request, $response) {
$pageCache = new PageCache();
$url = $request->getUri()->getPath();
$params = $request->getQueryParams();
// ตรวจสอบ cache
$cachedPage = $pageCache->get($url, $params);
if ($cachedPage !== null) {
$response->getBody()->write($cachedPage['content']);
return $response->withHeader('X-Cache', 'HIT');
}
// ประมวลผล request
$response = $next($request, $response);
// เก็บ response ใน cache
$content = (string) $response->getBody();
$pageCache->set($url, $content, $params, 1800); // 30 นาที
return $response->withHeader('X-Cache', 'MISS');
}Performance และ Best Practices
1. Cache Key Naming
// ใช้ namespace pattern
$userKey = "user:{$userId}";
$productKey = "product:{$productId}";
$categoryKey = "category:{$categoryId}:products";
// รวม parameters ใน key
$searchKey = "search:" . md5(serialize([
'query' => $query,
'filters' => $filters,
'sort' => $sort,
'page' => $page
]));2. Cache Expiration Strategy
// TTL แยกตามประเภทข้อมูล
$cache->set('user_profile:123', $profile, 1800); // 30 นาที
$cache->set('product_list', $products, 900); // 15 นาที
$cache->set('site_config', $config, 86400); // 1 วัน
$cache->set('session_data', $session, 7200); // 2 ชั่วโมง;3. Error Handling
$ttl = 360; // 0) {
try {
if ($cache->has($key)) {
return $cache->get($key);
}
$data = $loader();
$cache->set($key, $data, $ttl);
return $data;
} catch (Exception $e) {
error_log("Cache error for key {$key}: " . $e->getMessage());
// คืนค่าข้อมูลโดยไม่ใช้ cache
return $loader();
}
}4. Cache Monitoring
class FileCacheMonitor {
private $cache;
private $stats = [
'hits' => 0,
'misses' => 0,
'sets' => 0,
'deletes' => 0
];
public function __construct(FileCache $cache) {
$this->cache = $cache;
}
public function get($key, $default = null) {
if ($this->cache->has($key)) {
$this->stats['hits']++;
return $this->cache->get($key, $default);
} else {
$this->stats['misses']++;
return $default;
}
}
public function set($key, $value, $ttl = null) {
$this->stats['sets']++;
return $this->cache->set($key, $value, $ttl);
}
public function delete($key) {
$this->stats['deletes']++;
return $this->cache->delete($key);
}
public function getStats() {
$total = $this->stats['hits'] + $this->stats['misses'];
return array_merge($this->stats, [
'total_requests' => $total,
'hit_ratio' => $total > 0 ? ($this->stats['hits'] / $total) * 100 : 0
]);
}
}FileCache เป็น Cache driver ที่เหมาะสำหรับUsageทั่วไป ไม่ต้องพึ่งพาระบบภายนอก และสามารถให้ประสิทธิภาพที่ดีสำหรับเว็บไซต์ขนาดเล็กถึงกลาง