أساسيات PHP
العمل مع JSON
العمل مع JSON في PHP
JSON (JavaScript Object Notation) هو تنسيق تبادل بيانات نصي خفيف الوزن يسهل على البشر قراءته وكتابته، ويسهل على الآلات تحليله وتوليده. إنه المعيار الفعلي لواجهات برمجة تطبيقات الويب وتبادل البيانات.
ملاحظة: JSON مستقل عن اللغة ولكنه يستخدم اصطلاحات مألوفة لمبرمجي عائلة لغات C، بما في ذلك PHP. فهم JSON ضروري لتطوير الويب الحديث.
أساسيات JSON
يدعم JSON أنواع البيانات التالية:
- نص: "hello"
- رقم: 42, 3.14
- منطقي: true, false
- فارغ: null
- مصفوفة: [1, 2, 3]
- كائن: {"key": "value"}
{
"name": "John Doe",
"age": 30,
"isActive": true,
"email": null,
"hobbies": ["reading", "coding", "gaming"],
"address": {
"city": "New York",
"zip": "10001"
}
}
ترميز PHP إلى JSON (json_encode)
تحويل مصفوفات وكائنات PHP إلى نصوص JSON:
<?php
// مصفوفة بسيطة إلى JSON
$colors = ["red", "green", "blue"];
$json = json_encode($colors);
echo $json; // ["red","green","blue"]
// مصفوفة ترابطية إلى كائن JSON
$person = [
"name" => "John Doe",
"age" => 30,
"email" => "john@example.com"
];
$json = json_encode($person);
echo $json;
// {"name":"John Doe","age":30,"email":"john@example.com"}
// مصفوفات متداخلة
$data = [
"users" => [
["id" => 1, "name" => "Alice"],
["id" => 2, "name" => "Bob"]
],
"total" => 2
];
$json = json_encode($data);
echo $json;
?>
خيارات json_encode()
<?php
$data = [
"name" => "John",
"city" => "New York",
"hobbies" => ["reading", "coding"]
];
// طباعة جميلة (تنسيق قابل للقراءة)
echo json_encode($data, JSON_PRETTY_PRINT);
/*
{
"name": "John",
"city": "New York",
"hobbies": [
"reading",
"coding"
]
}
*/
// الحفاظ على أحرف اليونيكود
$arabic = ["greeting" => "مرحبا"];
echo json_encode($arabic); // {"greeting":"\u0645\u0631\u062d\u0628\u0627"}
echo json_encode($arabic, JSON_UNESCAPED_UNICODE); // {"greeting":"مرحبا"}
// عدم تحويل الشرطات المائلة
$url = ["website" => "https://example.com"];
echo json_encode($url, JSON_UNESCAPED_SLASHES);
// {"website":"https://example.com"}
// فرض تدوين الكائن للمصفوفات الفارغة
$empty = [];
echo json_encode($empty); // []
echo json_encode($empty, JSON_FORCE_OBJECT); // {}
// دمج خيارات متعددة
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>
نصيحة: استخدم
JSON_PRETTY_PRINT لتصحيح الأخطاء و JSON_UNESCAPED_UNICODE عند العمل مع الأحرف الدولية.
فك ترميز JSON إلى PHP (json_decode)
تحويل نصوص JSON إلى مصفوفات أو كائنات PHP:
<?php
$json = '{"name":"John","age":30,"city":"NYC"}';
// فك الترميز إلى مصفوفة ترابطية (افتراضياً: كائن)
$data = json_decode($json, true);
print_r($data);
// Array ( [name] => John [age] => 30 [city] => NYC )
echo $data["name"]; // John
// فك الترميز إلى كائن
$obj = json_decode($json);
print_r($obj);
// stdClass Object ( [name] => John [age] => 30 [city] => NYC )
echo $obj->name; // John
// JSON متداخل
$json = '{"user":{"name":"Alice","email":"alice@example.com"},"posts":3}';
$data = json_decode($json, true);
echo $data["user"]["name"]; // Alice
?>
خيارات json_decode()
<?php
$json = '{"name":"John","age":30}';
// تحديد العمق (مستوى التداخل الأقصى)
$data = json_decode($json, true, 512);
// فك الترميز مع الأعلام
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
// معالجة الأعداد الصحيحة الكبيرة كنصوص (منع فقدان الدقة)
$json = '{"id":9223372036854775807}'; // رقم كبير
$data = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
echo $data["id"]; // "9223372036854775807" (نص)
?>
معالجة الأخطاء
تحقق دائماً من الأخطاء عند العمل مع JSON:
<?php
// أخطاء الترميز
$data = ["text" => "\xB1\x31"]; // UTF-8 غير صالح
$json = json_encode($data);
if ($json === false) {
echo "خطأ في ترميز JSON: " . json_last_error_msg();
// الناتج: خطأ في ترميز JSON: أحرف UTF-8 مشوهة
}
// أخطاء فك الترميز
$json = '{"name":"John",}'; // JSON غير صالح (فاصلة زائدة)
$data = json_decode($json, true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
echo "خطأ في فك ترميز JSON: " . json_last_error_msg();
// الناتج: خطأ في فك ترميز JSON: خطأ في الصياغة
}
// استخدام json_last_error()
switch (json_last_error()) {
case JSON_ERROR_NONE:
echo "لا يوجد خطأ";
break;
case JSON_ERROR_DEPTH:
echo "تجاوز الحد الأقصى لعمق المكدس";
break;
case JSON_ERROR_SYNTAX:
echo "خطأ في الصياغة، JSON مشوه";
break;
case JSON_ERROR_UTF8:
echo "أحرف UTF-8 مشوهة";
break;
default:
echo "خطأ غير معروف";
}
?>
تحذير: تحقق دائماً من صحة بيانات JSON قبل فك الترميز.
json_decode() ترجع null لكل من الإدخال الفارغ و JSON غير الصالح، لذا تحقق دائماً من json_last_error().
أمثلة عملية
العمل مع استجابات API
<?php
// محاكاة استجابة API
$apiResponse = '
{
"status": "success",
"data": {
"users": [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
]
},
"meta": {
"total": 2,
"page": 1
}
}
';
// تحليل الاستجابة
$response = json_decode($apiResponse, true);
if ($response === null) {
die("استجابة JSON غير صالحة");
}
// الوصول إلى البيانات
if ($response["status"] === "success") {
$users = $response["data"]["users"];
foreach ($users as $user) {
echo "{$user['name']} ({$user['email']})<br>";
}
echo "الإجمالي: {$response['meta']['total']}<br>";
}
?>
إنشاء استجابات API
<?php
// تعيين نوع المحتوى المناسب
header("Content-Type: application/json");
// استجابة النجاح
function jsonResponse($data, $status = 200) {
http_response_code($status);
echo json_encode([
"success" => true,
"data" => $data
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
// استجابة الخطأ
function jsonError($message, $status = 400) {
http_response_code($status);
echo json_encode([
"success" => false,
"error" => $message
], JSON_PRETTY_PRINT);
}
// الاستخدام
$users = [
["id" => 1, "name" => "Alice"],
["id" => 2, "name" => "Bob"]
];
jsonResponse($users, 200);
// أو للأخطاء
// jsonError("المستخدم غير موجود", 404);
?>
قراءة وكتابة ملفات JSON
<?php
// كتابة JSON إلى ملف
$data = [
"users" => [
["name" => "Alice", "age" => 25],
["name" => "Bob", "age" => 30]
],
"updated" => date("Y-m-d H:i:s")
];
$json = json_encode($data, JSON_PRETTY_PRINT);
file_put_contents("data.json", $json);
// قراءة JSON من ملف
$json = file_get_contents("data.json");
$data = json_decode($json, true);
if ($data === null) {
die("خطأ في قراءة ملف JSON");
}
print_r($data);
// التحديث والحفظ
$data["users"][] = ["name" => "Charlie", "age" => 28];
$data["updated"] = date("Y-m-d H:i:s");
file_put_contents("data.json", json_encode($data, JSON_PRETTY_PRINT));
?>
JSON وكائنات PHP
<?php
class User {
public $name;
public $email;
private $password; // لن يتم تضمينها في JSON
public function __construct($name, $email, $password) {
$this->name = $name;
$this->email = $email;
$this->password = $password;
}
}
// ترميز الكائن إلى JSON
$user = new User("John", "john@example.com", "secret123");
$json = json_encode($user);
echo $json; // {"name":"John","email":"john@example.com"}
// فك ترميز JSON إلى فئة محددة (PHP 7.0+)
$json = '{"name":"Alice","email":"alice@example.com"}';
$user = json_decode($json); // stdClass
// تمثيل JSON مخصص
class Product implements JsonSerializable {
private $id;
private $name;
private $price;
public function __construct($id, $name, $price) {
$this->id = $id;
$this->name = $name;
$this->price = $price;
}
public function jsonSerialize(): mixed {
return [
"id" => $this->id,
"name" => $this->name,
"price" => number_format($this->price, 2),
"currency" => "USD"
];
}
}
$product = new Product(1, "Laptop", 999.99);
echo json_encode($product);
// {"id":1,"name":"Laptop","price":"999.99","currency":"USD"}
?>
نصيحة: نفذ واجهة
JsonSerializable للتحكم بالضبط في كيفية تحويل كائناتك إلى JSON.
التحقق من صحة JSON
<?php
function isValidJson($string) {
json_decode($string);
return json_last_error() === JSON_ERROR_NONE;
}
// التحقق من JSON
$json = '{"name":"John","age":30}';
if (isValidJson($json)) {
echo "JSON صالح";
} else {
echo "JSON غير صالح";
}
// التحقق من البنية
function validateJsonStructure($json, $requiredKeys) {
$data = json_decode($json, true);
if ($data === null) {
return ["error" => "JSON غير صالح"];
}
$errors = [];
foreach ($requiredKeys as $key) {
if (!isset($data[$key])) {
$errors[] = "مفتاح مطلوب مفقود: $key";
}
}
return empty($errors) ? true : $errors;
}
// الاستخدام
$json = '{"name":"John","email":"john@example.com"}';
$result = validateJsonStructure($json, ["name", "email", "age"]);
if ($result === true) {
echo "البنية صالحة";
} else {
print_r($result); // ["مفتاح مطلوب مفقود: age"]
}
?>
تقنيات JSON المتقدمة
بث ملفات JSON الكبيرة
<?php
// للملفات JSON الكبيرة، استخدم البث لتجنب مشاكل الذاكرة
function streamJsonArray($filename, $callback) {
$handle = fopen($filename, "r");
if (!$handle) return false;
$buffer = "";
$inArray = false;
$bracketCount = 0;
while (($char = fgetc($handle)) !== false) {
if ($char === "[") {
$inArray = true;
continue;
}
if ($inArray) {
if ($char === "{") $bracketCount++;
if ($char === "}") $bracketCount--;
$buffer .= $char;
if ($bracketCount === 0 && trim($buffer)) {
$item = json_decode(trim($buffer, ","), true);
if ($item) $callback($item);
$buffer = "";
}
}
}
fclose($handle);
}
// الاستخدام: معالجة العناصر واحداً تلو الآخر
streamJsonArray("large-data.json", function($item) {
echo $item["name"] . "<br>";
});
?>
التحقق من مخطط JSON
<?php
// مدقق مخطط JSON بسيط
function validateJsonSchema($data, $schema) {
$errors = [];
foreach ($schema as $field => $rules) {
if ($rules["required"] && !isset($data[$field])) {
$errors[] = "$field مطلوب";
continue;
}
if (!isset($data[$field])) continue;
$value = $data[$field];
// التحقق من النوع
if (isset($rules["type"])) {
$actualType = gettype($value);
if ($actualType !== $rules["type"]) {
$errors[] = "$field يجب أن يكون {$rules['type']}";
}
}
// التحقق من التنسيق
if (isset($rules["format"])) {
switch ($rules["format"]) {
case "email":
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$errors[] = "$field يجب أن يكون بريداً إلكترونياً صالحاً";
}
break;
case "url":
if (!filter_var($value, FILTER_VALIDATE_URL)) {
$errors[] = "$field يجب أن يكون عنوان URL صالحاً";
}
break;
}
}
}
return empty($errors) ? true : $errors;
}
// الاستخدام
$data = [
"name" => "John",
"email" => "invalid-email",
"age" => "30"
];
$schema = [
"name" => ["required" => true, "type" => "string"],
"email" => ["required" => true, "type" => "string", "format" => "email"],
"age" => ["required" => true, "type" => "integer"]
];
$result = validateJsonSchema($data, $schema);
print_r($result);
?>
تمرين:
- أنشئ مصفوفة PHP تمثل منشور مدونة وحولها إلى JSON
- اقرأ ملف JSON يحتوي على منتجات واعرضها في جدول HTML
- أنشئ نقطة نهاية API بسيطة ترجع بيانات المستخدم بتنسيق JSON
- اكتب دالة تتحقق من صحة JSON مقابل مخطط وترجع أخطاء مفصلة
- أنشئ دالة تحول مصفوفات PHP المتداخلة إلى JSON بتدوين النقاط والعكس
حالات الاستخدام الشائعة
- اتصالات API: إرسال واستقبال البيانات من REST APIs
- ملفات التكوين: تخزين إعدادات التطبيق بتنسيق JSON
- تخزين البيانات: استخدام ملفات JSON كقواعد بيانات خفيفة الوزن
- استجابات AJAX: إرجاع بيانات منظمة إلى JavaScript
- التسجيل: تخزين إدخالات السجل المنظمة
- التخزين المؤقت: تسلسل هياكل البيانات المعقدة للتخزين المؤقت
أفضل الممارسات
- تحقق دائماً من صحة JSON قبل فك الترميز
- استخدم
json_last_error()للتحقق من أخطاء الترميز/فك الترميز - عيّن رأس
Content-Type: application/jsonالمناسب لاستجابات API - استخدم
JSON_PRETTY_PRINTللمخرجات القابلة للقراءة البشرية - استخدم
JSON_UNESCAPED_UNICODEللأحرف الدولية - نفذ
JsonSerializableللتسلسل المخصص للكائنات - كن حذراً مع ملفات JSON الكبيرة - فكر في البث
- تحويل مدخلات المستخدم دائماً قبل الترميز لمنع XSS
تحذير:
- يجب أن تكون مفاتيح JSON نصوصاً (وليست أعداداً صحيحة) للكائنات
- يمكن أن تُفقد دقة الفاصلة العائمة في ترميز JSON
nullوfalseوالنص الفارغ""في PHP مختلفة في JSON- قد تفقد الأعداد الصحيحة الكبيرة الدقة - استخدم
JSON_BIGINT_AS_STRING - JSON لا يدعم التعليقات - أزلها قبل التحليل
الملخص
في هذا الدرس، تعلمت:
- ما هو JSON وأنواع بياناته
- كيفية ترميز مصفوفات/كائنات PHP إلى JSON باستخدام
json_encode() - كيفية فك ترميز JSON إلى PHP باستخدام
json_decode() - خيارات ترميز/فك ترميز JSON ومعالجة الأخطاء
- العمل مع استجابات API وإنشاء نقاط نهاية API
- قراءة وكتابة ملفات JSON
- تحويل كائنات PHP إلى JSON والعكس
- التحقق من صحة بنية ومخططات JSON
- تقنيات متقدمة مثل البث والتسلسل المخصص
JSON أساسي لتطوير الويب الحديث. أتقنه جيداً - ستستخدمه باستمرار عند بناء APIs والعمل مع JavaScript والتكامل مع خدمات الطرف الثالث!