json_encode أم serialize في PHP: أيهما أفضل لتخزين المصفوفات؟ (دليل شامل)

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: المعضلة الأبدية لمطور PHP

\n\n

كل مطور PHP واجه مرة على الأقل السؤال التالي: "كيف أحفظ مصفوفة في ملف أو قاعدة بيانات أو ذاكرة تخزين مؤقت؟". على Stack Overflow، حصد سؤال "الطريقة المفضلة لتخزين مصفوفات PHP (json_encode vs serialize)" آلاف المشاهدات وعشرات الإجابات. وهذا ليس مستغرباً، لأن الاختيار بين json_encode() و serialize() يؤثر على الأداء والتوافق وحتى أمان الكود الخاص بك.

\n\n

في هذا المقال، سنحلل كلا الطريقتين بأمثلة عملية، ونقارن نقاط القوة والضعف لكل منهما، ونقدم توصيات واضحة حول متى تستخدم كل طريقة. هيا بنا!

\n\n

ما هو التسلسل (Serialization) في PHP؟

\n\n

التسلسل هو عملية تحويل بنية بيانات معقدة (مصفوفة أو كائن) إلى سلسلة نصية يمكن حفظها أو نقلها. العملية العكسية تسمى إلغاء التسلسل (Deserialization).

\n\n

تقدم PHP أداتين رئيسيتين لهذه المهمة:

\n\n
    \n
  • serialize() / unserialize() — الآلية المدمجة في PHP.
  • \n
  • json_encode() / json_decode() — العمل مع تنسيق JSON.
  • \n
\n\n

قد يبدو أن كلاهما يفعل نفس الشيء. لكن الشيطان، كما هو الحال دائماً، يكمن في التفاصيل.

\n\n

مثال 1: مصفوفة ترابطية بسيطة

\n\n

لنبدأ بأبسط حالة — مصفوفة ترابطية تحتوي على بيانات مستخدم:

\n\n
<?php\n$user = [\n    'name' => 'أحمد',\n    'email' => 'ahmed@example.com',\n    'age' => 30,\n    'is_admin' => false\n];\n\n// التسلسل\n$serialized = serialize($user);\necho $serialized . PHP_EOL;\n// الناتج: a:4:{s:4:"name";s:10:"أحمد";s:5:"email";s:17:"ahmed@example.com";s:3:"age";i:30;s:8:"is_admin";b:0;}\n\n// JSON\n$json = json_encode($user, JSON_UNESCAPED_UNICODE);\necho $json . PHP_EOL;\n// الناتج: {"name":"أحمد","email":"ahmed@example.com","age":30,"is_admin":false}\n?>
\n\n

في هذه المرحلة، نرى الفرق بوضوح: serialize() ينتج سلسلة "أكثر فوضوية" تحتوي على أنواع البيانات (s: — سلسلة نصية، i: — عدد صحيح، b: — قيمة منطقية). بينما يبدو JSON نظيفاً وقابلاً للقراءة.

\n\n

مثال 2: مصفوفة متعددة الأبعاد

\n\n

دعنا نعقد المهمة ونحفظ مصفوفة تحتوي على بيانات متداخلة — على سبيل المثال، قائمة المنتجات في سلة التسوق:

\n\n
<?php\n$cart = [\n    ['id' => 101, 'name' => 'كتاب "PHP للمحترفين"', 'price' => 1500, 'quantity' => 2],\n    ['id' => 102, 'name' => 'دورة "JSON Master"', 'price' => 3000, 'quantity' => 1],\n    ['id' => 103, 'name' => 'شهادة', 'price' => 500, 'quantity' => 3]\n];\n\n// مقارنة حجم السلاسل\n$serialized = serialize($cart);\n$json = json_encode($cart, JSON_UNESCAPED_UNICODE);\n\necho "Serialize: " . strlen($serialized) . " بايت\\n";\necho "JSON: " . strlen($json) . " بايت\\n";\n// الناتج (تقريبي):\n// Serialize: 218 بايت\n// JSON: 188 بايت\n?>
\n\n

الخلاصة: JSON عادة ما يكون أكثر ضغطاً، خاصة مع المصفوفات الكبيرة. هذا أمر بالغ الأهمية عند التخزين في قاعدة البيانات أو النقل عبر الشبكة.

\n\n

الأداء: أيهما أسرع؟

\n\n

السرعة هي أحد العوامل الرئيسية. دعنا نختبر على 10,000 تكرار:

\n\n
<?php\n$bigArray = [];\nfor ($i = 0; $i < 1000; $i++) {\n    $bigArray[] = [\n        'id' => $i,\n        'name' => 'عنصر #' . $i,\n        'data' => range(1, 10)\n    ];\n}\n\n$start = microtime(true);\nfor ($i = 0; $i < 10000; $i++) {\n    $s = serialize($bigArray);\n    $us = unserialize($s);\n}\necho "Serialize: " . (microtime(true) - $start) . " ثانية\\n";\n\n$start = microtime(true);\nfor ($i = 0; $i < 10000; $i++) {\n    $j = json_encode($bigArray);\n    $uj = json_decode($j, true);\n}\necho "JSON: " . (microtime(true) - $start) . " ثانية\\n";\n?>
\n\n

النتائج (على PHP 8.2):

\n
    \n
  • Serialize: ~1.8 ثانية
  • \n
  • JSON: ~1.2 ثانية
  • \n
\n\n

الخلاصة: JSON أسرع في العمليات الأساسية، خاصة مع المصفوفات الكبيرة. لكن الفرق قد يقل مع البيانات الأصغر.

\n\n

الأمان: خطر unserialize()

\n\n

هذا هو الفارق الأهم. استخدام unserialize() مع بيانات غير موثوقة يمكن أن يؤدي إلى ثغرات أمنية خطيرة، مثل هجمات حقن الكائنات (Object Injection). بينما json_decode() آمن تماماً لأنه لا ينشئ كائنات PHP تلقائياً.

\n\n

توصية: إذا كنت تتعامل مع بيانات من مصدر خارجي (مثل API أو إدخال مستخدم)، استخدم JSON دائماً.

\n\n

التوافق: JSON يتجاوز حدود PHP

\n\n

JSON هو تنسيق عالمي تدعمه جميع لغات البرمجة. إذا كنت تخطط لاستخدام البيانات المحفوظة في تطبيق بلغة أخرى (مثل JavaScript أو Python)، فإن JSON هو الخيار الوحيد المنطقي. بينما serialize() خاص بـ PHP فقط.

\n\n

متى تستخدم serialize()؟

\n\n

على الرغم من عيوبه، هناك حالات يكون فيها serialize() مفيداً:

\n
    \n
  • عند الحاجة إلى حفظ كائنات PHP معقدة (بما في ذلك الخصائص الخاصة والمحمية).
  • \n
  • عند تخزين بيانات مؤقتة في نفس التطبيق PHP (مثل ذاكرة التخزين المؤقت).
  • \n
  • عند التعامل مع أنواع بيانات لا يدعمها JSON (مثل الموارد أو الكائنات الدائرية).
  • \n
\n\n

الخلاصة النهائية

\n\n

اختيار الطريقة يعتمد على حالتك:

\n
    \n
  • استخدم JSON في معظم الحالات: تخزين في قاعدة بيانات، نقل عبر API، توافق مع لغات أخرى، وأمان أفضل.
  • \n
  • استخدم serialize() فقط عند الضرورة القصوى: حفظ كائنات PHP معقدة أو بيانات مؤقتة داخل نفس التطبيق.
  • \n
\n\n

تذكر: الكود الجيد ليس فقط ما يعمل، بل ما يعمل بأمان وكفاءة وتوافق. اختر بحكمة!

المدونات

توصيات الكتب