ساخت Cache فایل با php
با سلام , امروزه یکی از مهمترین قابلیت ها هر فریم ورک که کش هست , کش میتونه رویه درایو های مخصوصی قرار بگیره مثل Database , Redis , file , … داخل این آموزش میخواهیم یک کلاس برای کش کردن فایل بسازیم
کش باعث میشه سرعت اجرا بالا بره وهمچنین ما از کانکشن مکرر به پایگاه داده و هر دستور اضافه , غیر ضروری خوداری کنیم
برای شروع به ساخت کلاس کش ما باید مسئله ای رو تعریف کنیم که میخواهیم به کجا برسیم !
صورت مسئله : کلاسی میخواهم که بتونم یه فایل کش درست کنم یا از فایل کش چیزی رو بردارم و همچنین چک کنم فایل کش من موجود هست یا خیر این فایل بتواند در زمان خاصی از سرور من حذف شود .
خب شروع میکنیم به کد زنی تو بخش اول مسئله ما باید توانایی درج روی فایل رو به کلاس بدیم پس :
class Cache{
//** پوشه ذخیره سازی **//
protected static $path = "cache" ;
//** زمان انقضا بر اساس دقیقه **//
protected static $expire = 1 ;
//** الفبا **//
const ALPHBA = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
//** جداکننده **//
const SEPARATOR = "_" ;
//** درخواست ساخت فایل کش **//
public static function put(string $name ,string $value ,int $expire = 0)
{
$name = self::generateName($name,$expire) ;
$pathWithFileName = self::path( $name ) ;
file_put_contents( $pathWithFileName , $value ) ;
}
//** ساخت توکن تصادفی **//
private static function generateName($name ,$expire, $size = 10 ){
$len = mb_strlen( self::ALPHBA ) ;
$chars = "" ;
for ($i = 0 ; $i < $size ; $i++ ) $chars .= self::ALPHBA[ random_int(0,$len-1) ] ; $expire_at = $expire > 0 ? $expire : self::$expire ;
$expire_at = strtotime("+{$expire_at}") ;
return $name.self::SEPARATOR.$expire_at.self::SEPARATOR.$chars ;
}
private static function path($name){
$path = __DIR__ .DIRECTORY_SEPARATOR.self::$path ;
if (! file_exists($path) )
mkdir($path) ;
return $path . DIRECTORY_SEPARATOR . $name ;
}
}
در کلاس بالا ما چند متغییر و ثابت داریم :
path : پوشه ای که قرار است فایل های کش ما در ان ذخیره شود
expire : زمان اکسپایر (انقضا) فایل بر اساس دقیقه
ALPHBA : شامل حروف و اعداد APLHA NUMERIC
SEPARATOR : جداکننده
متد استاتیک generateName : این متد کارش ساختن نام بر اساس ورودی هستش نامی که میسازه چند قسمت اصلی دارد مثل :
نام + جداکننده + زمان اکسپایر + جداکننده + رشته salt
کار اصلی این متد ساخت نام فایل است زمانی که ما نام فایل رو میسازیم باید تاریخ انقضا رو به صورت تایم استمپ در نظر بگیریم مهمترین کار این است زیرا ما باید برای فایل کش تاریخی برای حذف پیدا کنیم نمیتوانیم فقط به زمان modify بسنده کنیم
متد استاتیک path : کار اصلی این متد برگردوندن یک استریتگ است شامل نام فایل و فولدر ذخیره سازی دقت کنید ما فولدری که فایل های کش ذخیره میشود را فولدر جاری اسکریپت در نظر گرفتیم شما میتوانید این متد رو دست بزنید و فولدی که دوست داشتید رو اعمال کنید .
متد استاتیک put : این متد کار ساخت فایل رو بر عهده دارد وقتی شما دستور زیر رو تایپ میکنید برای شما در دایرکتوری cache فایل کش شما را میسازد .
Cache::put( string nameCache , string valueCache , integer expireMinutes ) ;
// مثال
Cache::put("name" , "amin" , 1 ) ;
در مثال بالا ما میگوییم اسم کش ما رو name قرار بده و مقدار رو amin و زمان اکسپایر شدن ۱ دقیقه بعد باشد .
ما برای بقیه پروژه باید دو متد دیگه هم بنویسیم یکی متدی که اطلاعات رو از فایل کش بگیره و دیگری اینکه موجود بودن فایل کش رو بررسی کنه :
//** فایل کش رو پیدا کن و بخون **//
public static function get($name , $default = false )
{
$path = self::has($name,true) ;
if ( $path )
return file_get_contents($path) ;
return $default ;
}
//** اگر فایل کش وجود داشت **//
public function has($name , $withPath = false )
{
$files = glob(self::path() . "*");
if (!empty($files)) {
foreach ( $files as $file ){
$baseName = basename($file) ;
$baseName = explode( self::SEPARATOR , $baseName );
if ( isset($baseName[0]) && $baseName[0] === $name )
return $withPath ? $file : true ;
}
}
return false ;
}
متد استاتیک has : در متد دوم که بالا نوشتیم ما ابتدا تمام فایل های دایرکتوری رو میخونیم و مسیرشو داخل files ذخیره میکنیم بعد داخل حلقه basename مسیر رو بررسی میکنیم و به وسیله تابع explode استرینگ رو به وسیله separator (جداکننده) تبدیل به ارایه میکنیم همون طور که گفته شد داخل اولین عضو ارایه ما نام کش قرار گرفته پس باید بررسی کنیم ببینیم نام کش با آرگومان تابع ما برابری دارد یا خیر
متد استاتیک get : در این متد ما وجود بودن فایل رو ابتدا بررسی میکنیم در صورت موجود بودن فایل رو میخونیم در صورت ناموجود بودن آرگومان دوم رو اجرا میکنیم .
براساس متد has ما میتوانیم یه تغییر جزئی به تابع put بدهیم و اینطوری بنویسیمش :
//** درخواست ساخت فایل کش **//
public static function put(string $name ,string $value ,int $expire = 0)
{
if (! self::has($name) )
{
$name = self::generateName($name,$expire) ;
$path = self::path() ;
$pathFile = $path . $name ;
file_put_contents( $pathFile , $value ) ;
return true ;
}
return false ;
}
اول بررسی میکنیم ببینم فایلی با این نام وجود داره که دوباره همون نام رو نسازیم و بعدا به مشکل نخوریم .
و در آخر ما باید اکسپایر شدن یک فایل رو بررسی کنیم همونطور که میدونید کد های php خود به خود داخل سرور اجرا نمیشن ! حتما باید به آدرس فایل درخواستی داده بشه تا اجرا بشن یا اینکه داخل CronJob (کرون جاب) یا Task Scheduler (اسکژول تَسک) فایل رو ادد کنیم و یک زمان اجرا در هر زمان خاصی بهش بدیم .
public function expire()
{
$files = glob(self::path() . "*");
if (!empty($files)) {
foreach ($files as $file) {
$baseName = basename($file) ;
$baseName = explode( self::SEPARATOR , $baseName );
$now = time() ;
if ( isset($baseName[1]) && $now >= intval($baseName[1]) )
unlink($file) ;
}
}
return ;
}
کد بالا بررسی میکنیم ! خیلی شبیه کد متد has هستش ولی ما داخل این کد بعد از explode کردن دومین عضو ارایه رو بررسی میکنیم و میبینیم که آیا زمان از زمان حال بیشتر شده ! در این صورت فایل رو با تابع unlink حذف میکنیم .
این کلاس بهتره تو یه فریم ورک با چارچوب mvc پیاده بشه برای حذف کردن فایل های کش ما دیگه از cronJob , … استفاده نکنیم به سادگی این کلاس رو در فایل index.php یعنی فایل مستر خودمون فراخونی کنیم که با هر درخواست خودش کاراشو انجام بده . ما میتونید فایل ضمیمه این جلسه رو دانلود کنید