تابع serialize() در PHP
تابع serialize() در PHP دادههای پیچیده مانند آرایهها و اشیاء را به یک رشتهٔ قابل ذخیره یا انتقال تبدیل میکند. این رشته قالب مخصوص PHP دارد و با تابع مقابل، یعنی unserialize()، قابل بازگردانی به مقدار اولیه است. کاربردهای رایج شامل ذخیره در پایگاهداده، کش، فایل و انتقال بین سرویسها است.
چرا و چه وقت از serialize استفاده کنیم؟
- ذخیرهٔ ساختار دادهٔ پیچیده در یک ستون متن در دیتابیس.
- کَشکردن (caching) آرایهها و اشیاء در فایل یا مموری.
- ذخیرهٔ نشستها (session) که به صورت پیشفرض از سریالایز استفاده میکنند.
- انتقال داده بین پروسسها یا APIهای درون برنامهای که فقط رشته دریافت میکنند.
قالب خروجی serialize
قالب سریالایز پیاچپی به صورت متن است و اجزای مختلف را با شناسهٔ نوع و طول نشان میدهد. مثالهایی از قالبها:
- s:length:”string”; — رشته
- i:value; — عدد صحیح
- d:value; — عدد اعشاری
- b:0; یا b:1; — بولین
- a:length:{…} — آرایه
- O:length:”ClassName”:members:{…} — شیء
مثال ساده: آرایه و بازگردانی
$arr = ['name' => 'Ali', 'age' => 30, 'tags' => ['php', 'serialize']];
$serialized = serialize($arr);
$unserialized = unserialize($serialized);
var_dump($serialized, $unserialized);در این مثال ابتدا آرایهای را سریالایز میکنیم که خروجی آن رشتهای مطابق قالب PHP خواهد بود. سپس با unserialize مقدار اصلی را بازمیسازیم. توجه داشته باشید که unserialize به کلاسها و تعریفهای نوع هنگام بازسازی اشیاء نیاز دارد.
کار با اشیاء و متدهای جادویی
برای اشیاء، PHP متدهای ویژهای را صدا میزند:
- __sleep() — قبل از سریالایز برای مشخص کردن چه پروپرتیهایی ذخیره شوند.
- __wakeup() — بعد از unserialize برای بازسازی منابع مانند اتصال دیتابیس.
- __serialize() و __unserialize() — از PHP 7.4 جایگزین روش قدیمیتر Serializable شدهاند و کنترل دقیقتری میدهند.
class User {
private $name;
private $conn; // resource
public function __construct($name) {
$this->name = $name;
$this->conn = null;
}
public function __serialize(): array {
return ['name' => $this->name];
}
public function __unserialize(array $data): void {
$this->name = $data['name'];
// میتوان اتصال دیتابیس را در اینجا دوباره برقرار کرد
$this->conn = null;
}
}در این کد، __serialize اطلاعات قابل ذخیره را بازمیگرداند و __unserialize هنگام بازسازی، داده را دریافت میکند. این روش امنتر و خواناتر از Serializable است.
مسائل امنیتی: خطرات unserialize
unserialize میتواند در مقابل Object Injection آسیبپذیر باشد؛ حملهای که با ارسال دادهٔ سریالایزدِ مخرب، کد دلخواه را از طریق متدهای جادویی مانند __wakeup یا متدهای کلاسها اجرا میکند. برای کاهش ریسک:
- هیچگاه دادهٔ غیرقابلاعتماد را مستقیم به unserialize ندهید.
- از گزینهٔ allowed_classes در unserialize استفاده کنید: unserialize($data, [‘allowed_classes’ => false]) برای جلوگیری از بازسازی اشیاء.
- در صورتی که نیاز به بازسازی اشیاء دارید، فقط کلاسهای مورد اعتماد را اجازه دهید.
$safe = unserialize($input, ['allowed_classes' => false]);با این پارامتر، اشیاء سریالایز شده تبدیل به آرایه یا خطا نخواهند شد و فقط ساختارهای اسکالر و آرایهای بازسازی میشوند. این یکی از سادهترین روشهای افزایش امنیت است.
مقایسه با json_encode و دیگر گزینهها
| ویژگی | serialize() | json_encode() |
|---|---|---|
| قابلیت ذخیره اشیاء | بله (با اطلاعات کلاس) | نه (فقط دادهٔ ساختاری) |
| قابل حمل بین زبانها | خیر (فرمت PHP خاص) | بله |
| حجم خروجی | معمولاً بیشتر | معمولاً کمتر و فشردهتر |
| امنیت | نیاز به احتیاط بیشتر | امنتر برای دادهٔ غیرقابلاعتماد |
برای کارایی بهتر و کاهش حجم گاهی از افزونههایی مثل igbinary استفاده میشود که فرمت باینری فشردهتری نسبت به serialize تولید میکند.
نکات فنی و بهترین شیوهها
- اگر کلاسها هنگام unserialize در دسترس نباشند، PHP خطا میدهد یا اشیاء را به کلاس __PHP_Incomplete_Class تبدیل میکند.
- برای تشخیص شکست unserialize از مقایسه خاص استفاده کنید، زیرا تابع ممکن است مقدار boolean false را واقعاً بازگرداند: بررسی کنید که ورودی مربوطه دقیقاً با رشتهٔ ‘b:0;’ مطابقت نداشته باشد یا از بررسی نوع استفاده نمایید.
- برای دادههای بینزبانی یا APIها از json_encode/json_decode استفاده کنید مگر آنکه نیاز صریح به بازسازی اشیاء PHP داشته باشید.
- در برنامههای حساس، همیشه allowed_classes را مشخص کنید یا از فرمتهای امنتر بهره ببرید.
مثال: استفادهٔ ایمن در عمل
// دریافت داده از منبع خارجی (مثلاً header یا POST)
$input = $_POST['payload'] ?? '';
$data = null;
if ($input !== '') {
$data = @unserialize($input, ['allowed_classes' => false]);
if ($data === false && $input !== 'b:0;') {
// دادهٔ نامعتبر یا حمله — لاگ کرده و رد کنید
error_log('Invalid serialized payload');
$data = null;
}
}در این نمونه ابتدا unserialize را با allowed_classes غیرفعال صدا میزنیم تا اشیاء بازسازی نشوند. سپس با چک دقیق بررسی میکنیم که false بهخاطر خطا نیست (چون b:0; میتواند مقدار false واقعی را تولید کند).
جمعبندی
تابع serialize() ابزار قدرتمندی برای ذخیرهسازی و انتقال ساختارهای پیچیده در PHP است، اما به دلیل فرمت خاص و خطرات امنیتی مرتبط باید با احتیاط و آگاهی استفاده شود. در مواردی که ارتباط بین زبانها یا امنیت مهم است، json_encode گزینهٔ مناسبتری خواهد بود؛ و در کاربردهای داخلی که نیاز به بازسازی اشیاء دارید، از allowed_classes و متدهای جدید __serialize/__unserialize استفاده کنید. افزونههای فشردهساز مانند igbinary نیز برای صرفهجویی در حافظه و زمان کاربردیاند.
آیا این مطلب برای شما مفید بود ؟



