کش در PHP
محصول اورجینال INZIP
دانلود پوسته وردپرس باریستا؛ قالب کافیشاپ، رُستری قهوه و فروشگاه قهوه دوزبانه با منوی رومیزی، رزرو آنلاین میز با کد پیامکی و ووکامرس. طراحی اختصاصی inzip.ir
تحویل آنی
آپدیت رایگان
بدون قفل لایسنس
پشتیبانی واقعی
٪۲۶
تخفیف ویژه
۱,۰۳۰,۰۰۰ تومان
کش کردن و بهینهسازی عملکرد در PHP
کش (Cache) یکی از مهمترین تکنیکهای بهینهسازی عملکرد است. با استفاده صحیح از کش، میتوان سرعت اپلیکیشن را دهها برابر افزایش داد.
انواع کش در PHP
انواع کش
OPcache
کد کامپایل
شده PHP
Data Cache
Redis
Memcached
Page Cache
HTML
کامل صفحه
Browser Cache
HTTP
Headers
OPcache (مهمترین بهینهسازی)
OPcache اسکریپتهای PHP کامپایل شده را در حافظه نگه میدارد:
# php.ini
[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.fast_shutdown=1
# بررسی در PHP
var_dump(opcache_get_status());
کش ساده با File
<?php
class FileCache {
private string $cacheDir;
public function __construct(string $cacheDir = 'cache/') {
$this->cacheDir = $cacheDir;
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
}
public function get(string $key): mixed {
$file = $this->getFilePath($key);
if (!file_exists($file)) {
return null;
}
$content = file_get_contents($file);
$data = unserialize($content);
if ($data['expires'] < time()) {
unlink($file);
return null;
}
return $data['value'];
}
public function set(string $key, mixed $value, int $ttl = 3600): void {
$data = [
'value' => $value,
'expires' => time() + $ttl,
'created' => time()
];
file_put_contents($this->getFilePath($key), serialize($data), LOCK_EX);
}
public function delete(string $key): void {
$file = $this->getFilePath($key);
if (file_exists($file)) unlink($file);
}
public function flush(): void {
$files = glob($this->cacheDir . '*');
foreach ($files as $file) {
if (is_file($file)) unlink($file);
}
}
private function getFilePath(string $key): string {
return $this->cacheDir . md5($key) . '.cache';
}
}
// استفاده
$cache = new FileCache();
$data = $cache->get('users');
if ($data === null) {
$data = $db->query('SELECT * FROM users')->fetchAll();
$cache->set('users', $data, 600); // 10 دقیقه
}
?>
کش با Redis
<?php
// composer require predis/predis
use Predis\Client;
class RedisCache {
private Client $redis;
public function __construct() {
$this->redis = new Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'password' => null
]);
}
public function get(string $key): mixed {
$value = $this->redis->get($key);
return $value ? unserialize($value) : null;
}
public function set(string $key, mixed $value, int $ttl = 3600): void {
$this->redis->setex($key, $ttl, serialize($value));
}
public function remember(string $key, int $ttl, callable $callback): mixed {
$value = $this->get($key);
if ($value !== null) return $value;
$value = $callback();
$this->set($key, $value, $ttl);
return $value;
}
public function delete(string $key): void {
$this->redis->del([$key]);
}
public function has(string $key): bool {
return $this->redis->exists($key) > 0;
}
public function flush(): void {
$this->redis->flushdb();
}
// Cache Tags (Redis Sets)
public function tag(string $tag): TaggedCache {
return new TaggedCache($this->redis, $tag);
}
}
// استفاده ساده
$cache = new RedisCache();
$users = $cache->remember('all_users', 600, function() use ($db) {
return $db->query('SELECT * FROM users')->fetchAll();
});
?>
کش با Memcached
<?php
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);
$key = 'product_123';
$data = $memcached->get($key);
if ($data === false) {
$data = $db->query(...);
$memcached->set($key, $data, 600);
}
$memcached->delete($key);
?>
Pattern: Cache Aside
<?php
function getUserPosts(int $userId): array {
$cacheKey = "user:{$userId}:posts";
$cache = new RedisCache();
$posts = $cache->get($cacheKey);
if ($posts !== null) {
return $posts; // cache hit
}
// cache miss - از دیتابیس بخوان
$posts = $db->prepare('SELECT * FROM posts WHERE user_id = ?');
$posts->execute([$userId]);
$posts = $posts->fetchAll();
// در کش ذخیره کن
$cache->set($cacheKey, $posts, 300);
return $posts;
}
// هنگام بهروزرسانی، کش را پاک کن
function updateUserPost(int $postId): void {
// بهروزرسانی دیتابیس
$db->prepare('UPDATE posts SET ... WHERE id = ?')->execute([$postId]);
// پاک کردن کش مرتبط
$cache = new RedisCache();
$cache->tag('user_posts')->flush();
}
?>
کش Query با APCu
<?php
// APCu برای سرور محلی، سریعتر از Redis
function getConfig(string $key): mixed {
$cacheKey = "config:{$key}";
$cached = apcu_fetch($cacheKey, $success);
if ($success) return $cached;
$value = $db->query('SELECT value FROM settings WHERE key = ?', [$key]);
apcu_store($cacheKey, $value, 3600);
return $value;
}
// حذف همه
apcu_clear_cache();
?>
کش HTTP و Browser
<?php
// Cache-Control Headers
header('Cache-Control: public, max-age=3600');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
// ETag
$etag = md5($content);
header("ETag: $etag");
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
$_SERVER['HTTP_IF_NONE_MATCH'] === $etag) {
http_response_code(304);
exit;
}
// کش صفحه HTML کامل
function cacheFullPage(int $ttl = 300): void {
$url = $_SERVER['REQUEST_URI'];
$cacheFile = "cache/pages/" . md5($url) . '.html';
if (file_exists($cacheFile) &&
filemtime($cacheFile) > time() - $ttl) {
readfile($cacheFile);
exit;
}
ob_start();
// ... محتوای صفحه
$content = ob_get_clean();
if (!is_dir('cache/pages')) mkdir('cache/pages', 0755, true);
file_put_contents($cacheFile, $content);
echo $content;
}
?>
بهینهسازی Composer Autoloader
# در production
composer dump-autoload -o --classmap-authoritative
# بدون dev dependencies
composer install --no-dev --optimize-autoloader
بهینهسازی دیتابیس
<?php
// استفاده از JOIN به جای چند Query
$users = $db->query('
SELECT u.*, p.title as last_post_title
FROM users u
LEFT JOIN posts p ON p.user_id = u.id
WHERE u.active = 1
GROUP BY u.id
')->fetchAll();
// Eager Loading
$posts = $db->query('SELECT * FROM posts LIMIT 50')->fetchAll();
$userIds = array_unique(array_column($posts, 'user_id'));
$users = $db->query(
'SELECT * FROM users WHERE id IN (' .
implode(',', array_fill(0, count($userIds), '?')) . ')'
)->execute($userIds)->fetchAll();
// به جای N+1 Query
foreach ($posts as &$post) {
$post['user'] = $users[$post['user_id']] ?? null;
}
?>
نکات مهم
Cache Invalidation: سختترین مشکل!
TTL مناسب: بسته به نوع داده
Cache Key معنادار: شامل پارامترها
Cache Stampede: برای دادههای پرطرفدار
پاکسازی دورهای: جلوگیری از رشد بیرویه
نتیجهگیری
کش کردن یکی از مؤثرترین راههای بهبود عملکرد است. با انتخاب استراتژی مناسب و پیادهسازی صحیح، میتوانید سرعت اپلیکیشن را چندین برابر افزایش دهید.
٪۴۱
دوره اختصاصی INZIP
آموزش حرفه ای HTML از صفر در ۱۶ ویدیو: سند، متن، لینک، تصویر، جدول، فرم، معناییسازی، دسترسپذیری و سئو، تا پروژهٔ کامل صفحهٔ فروشگاه محصول.
تماشای آنلاین + دانلود
دسترسی آنی و همیشگی
بهروزرسانی رایگان
کیفیت Full HD
۹۹۰,۰۰۰ تومان
۵۹۰,۰۰۰ تومان
سود شما ۴۰۰,۰۰۰ تومان
مشاهده سریال