حل أخطاء PHP – دليل شامل 🚀

any inconvenience caused.

حل أخطاء PHP – دليل شامل 🚀

سأقدم لك حلولاً شاملة لأخطاء PHP مع توضيح الأسباب والحلول لكل حالة:


📌 1. خطأ 500 Internal Server Error

✅ السبب الأكثر شيوعاً:

php

// ❌ خطأ في بناء الجملة (Syntax Error)
<?php
if ($x = 5)  // نسيان القوس المغلق
    echo "Hello";
    echo "World";  // هذا السطر خارج الشرط
?>

🔍 الأسباب المحتملة والحلول:

أ) خطأ في بناء الجملة (Parse Error)

php

// ❌ الكود الخاطئ
<?php
$name = "Ahmed
echo $name;  // خطأ: سلسلة غير مغلقة
?>

php

// ✅ الحل الصحيح
<?php
$name = "Ahmed";
echo $name;
?>

ب) خطأ في تضمين الملفات

php

// ❌ الكود الخاطئ
<?php
include("config.php");  // الملف غير موجود
require("database.php"); // الملف غير موجود → خطأ قاتل
?>

php

// ✅ الحل الصحيح
<?php
// التحقق من وجود الملف قبل التضمين
if (file_exists("config.php")) {
    include("config.php");
} else {
    die("الملف config.php غير موجود");
}

// استخدام require_once لمنع التضمين المكرر
require_once("database.php");
?>

ج) مشاكل في ملف .htaccess

apache

# ❌ .htaccess خاطئ
RewriteEngine On
RewriteRule ^products/(.*)$ product.php?id=$1  # نسيان [L]

apache

# ✅ .htaccess صحيح
RewriteEngine On
RewriteRule ^products/(.*)$ product.php?id=$1 [L,QSA]

📌 2. أخطاء الاتصال بقاعدة البيانات

✅ خطأ: Connection failed: Access denied for user

php

// ❌ الكود الخاطئ
<?php
$host = "localhost";
$user = "root";
$pass = "";  // كلمة المرور فارغة لكن قاعدة البيانات تطلب كلمة مرور
$db = "my_database";

$conn = new mysqli($host, $user, $pass, $db);
// خطأ: Access denied for user 'root'@'localhost'
?>

php

// ✅ الحل الصحيح
<?php
$host = "localhost";
$user = "root";
$pass = "your_actual_password";  // إضافة كلمة المرور الصحيحة
$db = "my_database";

// إضافة معالجة الأخطاء
try {
    $conn = new mysqli($host, $user, $pass, $db);
    
    if ($conn->connect_error) {
        throw new Exception("فشل الاتصال: " . $conn->connect_error);
    }
    
    echo "تم الاتصال بنجاح";
} catch (Exception $e) {
    // تسجيل الخطأ في ملف السجلات بدلاً من عرضه للمستخدم
    error_log($e->getMessage());
    echo "حدث خطأ في الاتصال، يرجى المحاولة لاحقاً";
}
?>

📌 3. أخطاء المتغيرات غير المعرفة

✅ خطأ: Notice: Undefined variable

php

// ❌ الكود الخاطئ
<?php
function calculateTotal($price) {
    $tax = 0.15;
    // المتغير $discount غير معرف
    $total = $price + ($price * $tax) - $discount;  // تحذير!
    return $total;
}

echo calculateTotal(100);
?>

php

// ✅ الحل الصحيح - الطريقة الأولى (تعريف المتغير)
<?php
function calculateTotal($price, $discount = 0) {  // إضافة قيمة افتراضية
    $tax = 0.15;
    $total = $price + ($price * $tax) - $discount;
    return $total;
}

echo calculateTotal(100, 10);  // 105
?>

php

// ✅ الحل الصحيح - الطريقة الثانية (التحقق من وجود المتغير)
<?php
function calculateTotal($price) {
    $tax = 0.15;
    $discount = isset($discount) ? $discount : 0;  // التحقق
    $total = $price + ($price * $tax) - $discount;
    return $total;
}
?>

📌 4. أخطاء المصفوفات (Array Errors)

✅ خطأ: Undefined array key

php

// ❌ الكود الخاطئ
<?php
$user = [
    'name' => 'Ahmed',
    'email' => 'ahmed@email.com'
];

echo $user['age'];  // خطأ: المفتاح age غير موجود
?>

php

// ✅ الحل الصحيح - طريقة 1
<?php
$user = [
    'name' => 'Ahmed',
    'email' => 'ahmed@email.com'
];

// التحقق من وجود المفتاح
if (isset($user['age'])) {
    echo $user['age'];
} else {
    echo "العمر غير محدد";
}
?>

php

// ✅ الحل الصحيح - طريقة 2 (PHP 7+)
<?php
$user = [
    'name' => 'Ahmed',
    'email' => 'ahmed@email.com'
];

// استخدام null coalescing operator
$age = $user['age'] ?? "غير محدد";
echo $age;  // "غير محدد"
?>

📌 5. أخطاء الجلسات (Session Errors)

✅ خطأ: Cannot send session cookie - headers already sent

php

// ❌ الكود الخاطئ
<?php
echo "مرحباً";  // إرسال محتوى قبل بدء الجلسة
session_start();  // خطأ! تم إرسال الهيدرات بالفعل
$_SESSION['user'] = 'Ahmed';
?>

php

// ✅ الحل الصحيح - الطريقة الأولى
<?php
// بدء الجلسة في بداية الملف
session_start();
echo "مرحباً";
$_SESSION['user'] = 'Ahmed';
?>

php

// ✅ الحل الصحيح - الطريقة الثانية (اختبار احترافي)
<?php
// استخدام Output Buffering
ob_start();  // بدء التخزين المؤقت

session_start();
echo "مرحباً";
$_SESSION['user'] = 'Ahmed';

ob_end_flush();  // إرسال المخرجات بعد الجلسة
?>

📌 6. أخطاء الملفات (File Upload Errors)

✅ خطأ: File upload error - UPLOAD_ERR_INI_SIZE

php

// ❌ الكود الخاطئ
<?php
if ($_FILES['image']['error'] == 0) {
    $tmp_name = $_FILES['image']['tmp_name'];
    move_uploaded_file($tmp_name, "uploads/" . $_FILES['image']['name']);
}
?>

php

// ✅ الحل الصحيح - معالجة شاملة
<?php
// إعدادات في php.ini
ini_set('upload_max_filesize', '20M');
ini_set('post_max_size', '20M');
ini_set('max_execution_time', 300);

// التحقق من رفع الملف
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
    $file = $_FILES['image'];
    $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
    $max_size = 5 * 1024 * 1024;  // 5MB
    
    // التحقق من النوع
    if (!in_array($file['type'], $allowed_types)) {
        die("نوع الملف غير مسموح");
    }
    
    // التحقق من الحجم
    if ($file['size'] > $max_size) {
        die("حجم الملف كبير جداً");
    }
    
    // إنشاء اسم فريد للملف
    $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
    $new_name = time() . '_' . uniqid() . '.' . $ext;
    $destination = "uploads/" . $new_name;
    
    if (move_uploaded_file($file['tmp_name'], $destination)) {
        echo "تم رفع الملف بنجاح: " . $new_name;
    } else {
        echo "فشل رفع الملف";
    }
} else {
    // التعامل مع أخطاء الرفع
    switch ($_FILES['image']['error']) {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            echo "الملف كبير جداً";
            break;
        case UPLOAD_ERR_PARTIAL:
            echo "تم رفع الملف بشكل ناقص";
            break;
        case UPLOAD_ERR_NO_FILE:
            echo "لم يتم اختيار ملف";
            break;
        default:
            echo "حدث خطأ غير معروف";
    }
}
?>

📌 7. أخطاء الـ Class/Object

✅ خطأ: Call to undefined method

php

// ❌ الكود الخاطئ
<?php
class User {
    private $name;
    
    public function __construct($name) {
        $this->name = $name;
    }
}

$user = new User("Ahmed");
echo $user->getName();  // خطأ! الطريقة غير موجودة
?>

php

// ✅ الحل الصحيح
<?php
class User {
    private $name;
    
    public function __construct($name) {
        $this->name = $name;
    }
    
    // إضافة الطريقة المفقودة
    public function getName() {
        return $this->name;
    }
    
    // إضافة метод __call للتعامل مع الطرق غير الموجودة
    public function __call($method, $arguments) {
        if ($method === 'get' . ucfirst($this->name)) {
            return $this->name;
        }
        throw new Exception("الطريقة $method غير موجودة");
    }
}

$user = new User("Ahmed");
echo $user->getName();  // "Ahmed"
?>

📌 8. أخطاء SQL Injection (أمن المعلومات)

❌ الكود غير الآمن:

php

<?php
$id = $_GET['id'];  // بيانات من المستخدم
$query = "SELECT * FROM users WHERE id = $id";  // ثغرة أمنية!
$result = mysqli_query($conn, $query);
?>

✅ الحلول الآمنة:

الطريقة 1: Prepared Statements (MySQLi)

php

<?php
$id = $_GET['id'];

$stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);  // "i" = integer
$stmt->execute();
$result = $stmt->get_result();
?>

الطريقة 2: Prepared Statements (PDO)

php

<?php
$id = $_GET['id'];

try {
    $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
    $stmt->execute(['id' => $id]);
    $result = $stmt->fetchAll();
} catch (PDOException $e) {
    error_log($e->getMessage());
    echo "حدث خطأ في قاعدة البيانات";
}
?>

📌 9. أخطاء XSS (Cross-Site Scripting)

❌ الكود غير الآمن:

php

<?php
$user_input = $_GET['message'];
echo "رسالتك: " . $user_input;  // خطير!
?>

✅ الحلول الآمنة:

php

<?php
$user_input = $_GET['message'];

// استخدام htmlspecialchars
echo "رسالتك: " . htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');

// أو استخدام strip_tags (إزالة الـ HTML كلياً)
echo "رسالتك: " . strip_tags($user_input);

// أو استخدام filter_var
echo "رسالتك: " . filter_var($user_input, FILTER_SANITIZE_STRING);
?>

📌 10. أخطاء الأداء

❌ كود بطيء:

php

<?php
// استعلام داخل حلقة - مشكلة N+1
$users = $db->query("SELECT * FROM users");
while ($user = $users->fetch_assoc()) {
    $orders = $db->query("SELECT * FROM orders WHERE user_id = " . $user['id']);
    // معالجة الطلبات
}
?>

✅ الحل المحسّن:

php

<?php
// استخدام JOIN لاستعلام واحد
$sql = "
    SELECT u.*, o.* 
    FROM users u 
    LEFT JOIN orders o ON u.id = o.user_id
";
$results = $db->query($sql);

// أو استخدام caching
$cache_key = 'users_with_orders';
$data = $cache->get($cache_key);

if (!$data) {
    $data = $db->query($sql)->fetchAll();
    $cache->set($cache_key, $data, 3600);  // تخزين لمدة ساعة
}
?>

📌 11. أخطاء التكوين (php.ini)

✅ مشاكل شائعة:

ini

; ❌ إعدادات غير مناسبة
memory_limit = 8M
upload_max_filesize = 2M
max_execution_time = 30
display_errors = On  ; عرض الأخطاء في الإنتاج
error_reporting = E_ALL

ini

; ✅ إعدادات محسّنة للإنتاج
memory_limit = 256M
upload_max_filesize = 20M
post_max_size = 20M
max_execution_time = 300
display_errors = Off  ; إخفاء الأخطاء في الإنتاج
log_errors = On
error_log = /var/log/php_errors.log
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

; ✅ إعدادات التطوير
; display_errors = On
; error_reporting = E_ALL

🛠️ أدوات تصحيح الأخطاء في PHP

php

<?php
// 1. دالة مخصصة للـ Debugging
function debug($var, $die = false) {
    echo "<pre style='background:#f4f4f4;padding:10px;border:1px solid #ddd;'>";
    echo "<strong>Debug:</strong><br>";
    var_dump($var);
    echo "</pre>";
    if ($die) die();
}

// 2. تسجيل الأخطاء في ملف
function logError($message, $file = 'error.log') {
    $log = date('Y-m-d H:i:s') . " - " . $message . "\n";
    file_put_contents($file, $log, FILE_APPEND);
}

// 3. معالج أخطاء مخصص
set_error_handler(function($errno, $errstr, $errfile, $errline) {
    $message = "خطأ [$errno] $errstr في $errfile السطر $errline";
    logError($message);
    
    if (ini_get('display_errors')) {
        echo "<b>خطأ:</b> $errstr في <b>$errfile</b> السطر $errline";
    }
});

// 4. معالج استثناءات مخصص
set_exception_handler(function($exception) {
    $message = "استثناء: " . $exception->getMessage();
    $message .= " في " . $exception->getFile();
    $message .= " السطر " . $exception->getLine();
    logError($message);
    
    if (ini_get('display_errors')) {
        echo "<b>استثناء:</b> " . $exception->getMessage();
    }
});
?>

📝 ملخص سريع لحل الأخطاء:

الخطأالحل السريع
500 Internal Server Errorتحقق من الأخطاء في ملف error_log، تأكد من صلاحيات الملفات
Parse Errorتأكد من إغلاق جميع الأقواس والفواصل والعلامات
Undefined Variableاستخدم isset() أو ?? (null coalescing)
Undefined Indexاستخدم array_key_exists() أو isset()
Headers Already Sentاستخدم ob_start() أو تأكد من عدم وجود مخرجات قبل session_start()
Connection Errorsتحقق من بيانات الاتصال، استخدم try-catch
File Upload Errorsتحقق من الإعدادات في php.ini، استخدم أنواع الملفات المسموحة
SQL Injectionاستخدم Prepared Statements
XSSاستخدم htmlspecialchars() أو strip_tags()

🎯 هل لديك خطأ محدد تواجهه الآن؟

ارسل لي:

  1. الكود المسبب للخطأ
  2. رسالة الخطأ كاملة
  3. بيئة التشغيل (إصدار PHP، نظام التشغيل)

وسأعطيك حلًا مخصصًا فوراً! 🚀

📚 من حلول أخطاء PHP – دليل شامل ومتقدم 🚀

سأقدم لك من الأخطاء الشائعة والحلول المتقدمة مع أمثلة عملية:


📌 12. أخطاء التعامل مع التواريخ والوقت

✅ خطأ: Warning: date(): It is not safe to rely on the system's timezone settings

php

// ❌ الكود الخاطئ
<?php
echo date('Y-m-d H:i:s');  // تحذير: المنطقة الزمنية غير محددة
?>

php

// ✅ الحل الصحيح - الطريقة الأولى
<?php
// تعيين المنطقة الزمنية في بداية الملف
date_default_timezone_set('Asia/Riyadh');  // أو 'Asia/Dubai'
echo date('Y-m-d H:i:s');

// أو استخدام UTC
date_default_timezone_set('UTC');
echo date('Y-m-d H:i:s');
?>

php

// ✅ الحل الصحيح - الطريقة الثانية (استخدام DateTime)
<?php
$datetime = new DateTime('now', new DateTimeZone('Asia/Riyadh'));
echo $datetime->format('Y-m-d H:i:s');

// تحويل بين المناطق الزمنية
$utc_time = new DateTime('now', new DateTimeZone('UTC'));
$riyadh_time = $utc_time->setTimezone(new DateTimeZone('Asia/Riyadh'));
echo $riyadh_time->format('Y-m-d H:i:s');
?>

✅ مشاكل حساب التواريخ

php

// ❌ حساب خاطئ للتواريخ
<?php
$date1 = "2024-01-01";
$date2 = "2024-01-31";
$diff = strtotime($date2) - strtotime($date1);
$days = $diff / (60 * 60 * 24);  // قد يعطي نتائج غير دقيقة مع التوقيت الصيفي
?>

php

// ✅ الحل الصحيح باستخدام DateTime
<?php
$date1 = new DateTime('2024-01-01');
$date2 = new DateTime('2024-01-31');
$interval = $date1->diff($date2);

echo "الفرق: " . $interval->days . " أيام";
echo "الفرق: " . $interval->m . " شهور";
echo "الفرق: " . $interval->y . " سنوات";

// إضافة/طرح تواريخ
$future = (new DateTime())->modify('+30 days');
$past = (new DateTime())->modify('-2 months');
?>

📌 13. أخطاء JSON

✅ خطأ: json_decode(): expects parameter 1 to be string, object given

php

// ❌ الكود الخاطئ
<?php
$data = ['name' => 'Ahmed', 'age' => 30];
$json = json_decode($data);  // خطأ! يجب أن تكون string
?>

php

// ✅ الحل الصحيح
<?php
$data = ['name' => 'Ahmed', 'age' => 30];

// تحويل المصفوفة إلى JSON أولاً
$json_string = json_encode($data);
$decoded = json_decode($json_string, true);  // true -> مصفوفة

// التحقق من صحة JSON
if (json_last_error() === JSON_ERROR_NONE) {
    print_r($decoded);
} else {
    echo "خطأ في JSON: " . json_last_error_msg();
}
?>

✅ معالجة JSON بشكل احترافي

php

<?php
class JsonHandler {
    private static $errors = [
        JSON_ERROR_NONE => 'لا يوجد خطأ',
        JSON_ERROR_DEPTH => 'الحد الأقصى للعمق تم تجاوزه',
        JSON_ERROR_STATE_MISMATCH => 'عدم تطابق في الحالة',
        JSON_ERROR_CTRL_CHAR => 'حرف تحكم غير متوقع',
        JSON_ERROR_SYNTAX => 'خطأ في بناء الجملة',
        JSON_ERROR_UTF8 => 'ترميز UTF-8 غير صحيح',
        JSON_ERROR_RECURSION => 'تكرار لا نهائي',
        JSON_ERROR_INF_OR_NAN => 'قيمة INF أو NAN غير مسموحة',
        JSON_ERROR_UNSUPPORTED_TYPE => 'نوع غير مدعوم'
    ];
    
    public static function encode($data, $options = 0) {
        $json = json_encode($data, $options);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            $error = self::$errors[json_last_error()] ?? 'خطأ غير معروف';
            throw new Exception("فشل ترميز JSON: $error");
        }
        
        return $json;
    }
    
    public static function decode($json, $assoc = true) {
        $data = json_decode($json, $assoc);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            $error = self::$errors[json_last_error()] ?? 'خطأ غير معروف';
            throw new Exception("فشل فك ترميز JSON: $error");
        }
        
        return $data;
    }
    
    public static function validate($json) {
        json_decode($json);
        return json_last_error() === JSON_ERROR_NONE;
    }
}

// استخدام الكلاس
try {
    $data = ['name' => 'Ahmed', 'age' => 30];
    $json = JsonHandler::encode($data, JSON_PRETTY_PRINT);
    echo $json;
    
    $decoded = JsonHandler::decode($json);
    print_r($decoded);
    
    // التحقق من الصلاحية
    if (JsonHandler::validate('{"name":"Ahmed"}')) {
        echo "JSON صحيح";
    }
} catch (Exception $e) {
    echo "خطأ: " . $e->getMessage();
}
?>

📌 14. أخطاء الـ API والـ HTTP Requests

✅ خطأ: file_get_contents(): Failed to open stream

php

// ❌ الكود الخاطئ
<?php
$response = file_get_contents('https://api.example.com/data');
echo $response;
?>

php

// ✅ الحل الصحيح - الطريقة الأولى (cURL)
<?php
function apiRequest($url, $method = 'GET', $data = null, $headers = []) {
    $ch = curl_init();
    
    // إعدادات cURL
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  // للإنتاج استخدم true
    
    // إعداد الـ headers
    if (!empty($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    
    // إعداد الـ method والبيانات
    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        if ($data) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
    } elseif ($method === 'PUT') {
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        if ($data) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
    } elseif ($method === 'DELETE') {
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
    }
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    
    curl_close($ch);
    
    if ($error) {
        throw new Exception("cURL Error: $error");
    }
    
    if ($httpCode >= 400) {
        throw new Exception("HTTP Error: $httpCode - $response");
    }
    
    return json_decode($response, true);
}

// استخدام الدالة
try {
    $result = apiRequest('https://api.example.com/users', 'GET', null, [
        'Authorization: Bearer your_token',
        'Content-Type: application/json'
    ]);
    print_r($result);
} catch (Exception $e) {
    error_log($e->getMessage());
    echo "فشل الاتصال بالـ API";
}
?>

php

// ✅ الحل الصحيح - الطريقة الثانية (Guzzle HTTP Client)
<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class ApiClient {
    private $client;
    
    public function __construct($baseUrl, $timeout = 30) {
        $this->client = new Client([
            'base_uri' => $baseUrl,
            'timeout' => $timeout,
            'headers' => [
                'Accept' => 'application/json',
                'Content-Type' => 'application/json'
            ]
        ]);
    }
    
    public function get($endpoint, $params = []) {
        try {
            $response = $this->client->get($endpoint, [
                'query' => $params
            ]);
            return json_decode($response->getBody(), true);
        } catch (GuzzleException $e) {
            $this->handleError($e);
        }
    }
    
    public function post($endpoint, $data = []) {
        try {
            $response = $this->client->post($endpoint, [
                'json' => $data
            ]);
            return json_decode($response->getBody(), true);
        } catch (GuzzleException $e) {
            $this->handleError($e);
        }
    }
    
    private function handleError($e) {
        $statusCode = $e->getCode();
        $message = $e->getMessage();
        
        // معالجة أنواع مختلفة من الأخطاء
        if ($e->hasResponse()) {
            $body = $e->getResponse()->getBody()->getContents();
            error_log("API Error: $statusCode - $body");
        }
        
        throw new Exception("فشل طلب الـ API: $message");
    }
}

// استخدام الكلاس
$api = new ApiClient('https://api.example.com');
try {
    $users = $api->get('/users', ['page' => 1, 'limit' => 10]);
    print_r($users);
    
    $newUser = $api->post('/users', [
        'name' => 'Ahmed',
        'email' => 'ahmed@email.com'
    ]);
} catch (Exception $e) {
    echo "حدث خطأ: " . $e->getMessage();
}
?>

📌 15. أخطاء التشفير والتوقيع

✅ خطأ: hash_equals(): Expected known_string to be a string

php

// ❌ الكود الخاطئ - مقارنة غير آمنة
<?php
$password = '123456';
$hash = '$2y$10$encrypted_hash_here';

if ($password == $hash) {  // غير آمن! لا تستخدم == مع التشفير
    echo "كلمة المرور صحيحة";
}
?>

php

// ✅ الحل الصحيح - التشفير الآمن
<?php
class PasswordHandler {
    // تشفير كلمة المرور
    public static function hash($password) {
        $options = [
            'cost' => 12,  // يوصى بـ 10-12
            'salt' => random_bytes(22)  // ملح عشوائي
        ];
        return password_hash($password, PASSWORD_BCRYPT, $options);
    }
    
    // التحقق من كلمة المرور
    public static function verify($password, $hash) {
        if (!is_string($password) || !is_string($hash)) {
            throw new InvalidArgumentException('يجب أن تكون المدخلات نصية');
        }
        return password_verify($password, $hash);
    }
    
    // التحقق من قوة كلمة المرور
    public static function isStrong($password) {
        return strlen($password) >= 8 &&
               preg_match('/[A-Z]/', $password) &&
               preg_match('/[a-z]/', $password) &&
               preg_match('/[0-9]/', $password) &&
               preg_match('/[^A-Za-z0-9]/', $password);
    }
    
    // توليد كلمة مرور عشوائية قوية
    public static function generate($length = 12) {
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';
        $password = '';
        for ($i = 0; $i < $length; $i++) {
            $password .= $chars[random_int(0, strlen($chars) - 1)];
        }
        return $password;
    }
}

// استخدام الكلاس
try {
    // تشفير كلمة المرور
    $password = 'MySecurePass123!';
    $hash = PasswordHandler::hash($password);
    echo "التشفير: $hash\n";
    
    // التحقق من كلمة المرور
    if (PasswordHandler::verify('MySecurePass123!', $hash)) {
        echo "كلمة المرور صحيحة ✅\n";
    } else {
        echo "كلمة المرور خاطئة ❌\n";
    }
    
    // التحقق من قوة كلمة المرور
    if (PasswordHandler::isStrong($password)) {
        echo "كلمة المرور قوية 💪\n";
    }
    
    // توليد كلمة مرور جديدة
    $newPass = PasswordHandler::generate(16);
    echo "كلمة مرور جديدة: $newPass\n";
    
} catch (Exception $e) {
    echo "خطأ: " . $e->getMessage();
}
?>

✅ تشفير البيانات (Encryption)

php

<?php
class EncryptionHandler {
    private static $method = 'AES-256-CBC';
    private static $key;
    
    public static function init($key = null) {
        if ($key === null) {
            $key = $_ENV['ENCRYPTION_KEY'] ?? getenv('ENCRYPTION_KEY');
        }
        
        if (!$key) {
            // توليد مفتاح جديد (احفظه في مكان آمن)
            $key = bin2hex(openssl_random_pseudo_bytes(32));
            throw new Exception("قم بحفظ هذا المفتاح: $key");
        }
        
        // التأكد من طول المفتاح المناسب
        self::$key = hash('sha256', $key, true);
    }
    
    public static function encrypt($data) {
        if (empty(self::$key)) {
            self::init();
        }
        
        $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(self::$method));
        $encrypted = openssl_encrypt($data, self::$method, self::$key, 0, $iv);
        
        // دمج الـ IV مع البيانات المشفرة
        return base64_encode($iv . $encrypted);
    }
    
    public static function decrypt($encryptedData) {
        if (empty(self::$key)) {
            self::init();
        }
        
        $data = base64_decode($encryptedData);
        $ivLength = openssl_cipher_iv_length(self::$method);
        $iv = substr($data, 0, $ivLength);
        $encrypted = substr($data, $ivLength);
        
        return openssl_decrypt($encrypted, self::$method, self::$key, 0, $iv);
    }
}

// استخدام التشفير
try {
    EncryptionHandler::init('your-secret-key-here');
    
    $original = 'بيانات حساسة جداً';
    $encrypted = EncryptionHandler::encrypt($original);
    echo "مشفر: $encrypted\n";
    
    $decrypted = EncryptionHandler::decrypt($encrypted);
    echo "مفكوك: $decrypted\n";
    
} catch (Exception $e) {
    echo "خطأ تشفير: " . $e->getMessage();
}
?>

📌 16. أخطاء إدارة الذاكرة

✅ خطأ: Allowed memory size exhausted

php

// ❌ الكود الخاطئ - استهلاك كبير للذاكرة
<?php
// قراءة ملف كبير كامل في الذاكرة
$file = file_get_contents('huge_file.csv');
$data = explode("\n", $file);  // تخزين كل البيانات في الذاكرة
?>

php

// ✅ الحل الصحيح - استخدام Streams
<?php
function processLargeFile($filename, $callback) {
    $handle = fopen($filename, 'r');
    if (!$handle) {
        throw new Exception("لا يمكن فتح الملف: $filename");
    }
    
    $rowCount = 0;
    while (($row = fgetcsv($handle)) !== false) {
        $rowCount++;
        // معالجة كل صف على حدة
        $callback($row, $rowCount);
        
        // تحرير الذاكرة بشكل دوري
        if ($rowCount % 1000 == 0) {
            gc_collect_cycles();  // جمع القمامة
            memory_get_usage();   // يمكن تسجيل استخدام الذاكرة
        }
    }
    
    fclose($handle);
    return $rowCount;
}

// استخدام الدالة
$totalRows = processLargeFile('huge_file.csv', function($row, $index) {
    // معالجة كل صف
    if ($index % 1000 == 0) {
        echo "معالجة الصف $index...\n";
    }
});

echo "تم معالجة $totalRows صفوف\n";
?>

✅ إدارة الذاكرة المتقدمة

php

<?php
class MemoryManager {
    private static $memoryLimit = null;
    private static $peakMemory = 0;
    
    public static function setMemoryLimit($limit) {
        self::$memoryLimit = $limit;
        ini_set('memory_limit', $limit);
    }
    
    public static function getMemoryUsage() {
        return [
            'current' => memory_get_usage(true),
            'peak' => memory_get_peak_usage(true),
            'real_usage' => memory_get_usage(false)
        ];
    }
    
    public static function optimize() {
        // تحرير الذاكرة
        gc_collect_cycles();
        
        // إعادة تعيين الـ memory limit إذا لزم الأمر
        if (memory_get_usage(true) > self::$peakMemory) {
            self::$peakMemory = memory_get_usage(true);
        }
    }
    
    public static function memoryToString($bytes) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $i = 0;
        while ($bytes >= 1024 && $i < count($units) - 1) {
            $bytes /= 1024;
            $i++;
        }
        return round($bytes, 2) . ' ' . $units[$i];
    }
    
    public static function logMemoryUsage($label = '') {
        $usage = self::getMemoryUsage();
        $log = sprintf(
            "%s - Current: %s, Peak: %s, Limit: %s\n",
            $label,
            self::memoryToString($usage['current']),
            self::memoryToString($usage['peak']),
            ini_get('memory_limit')
        );
        error_log($log);
        return $log;
    }
    
    public static function monitor($callback) {
        $startTime = microtime(true);
        $startMemory = memory_get_usage(true);
        
        try {
            $result = $callback();
        } finally {
            $endTime = microtime(true);
            $endMemory = memory_get_usage(true);
            
            $timeMs = round(($endTime - $startTime) * 1000, 2);
            $memoryDiff = $endMemory - $startMemory;
            
            $log = sprintf(
                "Execution: %sms, Memory: %s (Δ%s)",
                $timeMs,
                self::memoryToString($endMemory),
                self::memoryToString($memoryDiff)
            );
            error_log($log);
        }
        
        return $result;
    }
}

// استخدام مدير الذاكرة
MemoryManager::setMemoryLimit('512M');

// تتبع استخدام الذاكرة
MemoryManager::logMemoryUsage('بداية التنفيذ');

// مراقبة أداء عملية
$result = MemoryManager::monitor(function() {
    // عملية ثقيلة
    $array = [];
    for ($i = 0; $i < 100000; $i++) {
        $array[] = "Item $i";
        if ($i % 10000 == 0) {
            MemoryManager::optimize();
        }
    }
    return count($array);
});

echo "النتيجة: $result\n";
MemoryManager::logMemoryUsage('نهاية التنفيذ');
?>

📌 17. أخطاء التزامن (Concurrency)

✅ مشكلة Race Condition

php

// ❌ الكود الخاطئ
<?php
function updateCounter() {
    $file = 'counter.txt';
    $count = (int) file_get_contents($file);
    $count++;
    file_put_contents($file, $count);  // قد يفقد تحديثات متزامنة
}
?>

php

// ✅ الحل الصحيح - استخدام الأقفال (File Locking)
<?php
function updateCounterSafe() {
    $file = 'counter.txt';
    $fp = fopen($file, 'c+');
    
    if (flock($fp, LOCK_EX)) {  // قفل حصري
        $count = (int) fread($fp, filesize($file));
        $count++;
        fseek($fp, 0);
        ftruncate($fp, 0);
        fwrite($fp, (string) $count);
        fflush($fp);
        flock($fp, LOCK_UN);  // فتح القفل
    } else {
        throw new Exception("لا يمكن الحصول على القفل");
    }
    
    fclose($fp);
    return $count;
}
?>

✅ استخدام قاعدة البيانات للعمليات الذرية

php

<?php
class AtomicCounter {
    private $pdo;
    
    public function __construct($pdo) {
        $this->pdo = $pdo;
        $this->createTable();
    }
    
    private function createTable() {
        $this->pdo->exec("
            CREATE TABLE IF NOT EXISTS counters (
                id VARCHAR(50) PRIMARY KEY,
                value INT DEFAULT 0,
                version INT DEFAULT 0
            )
        ");
    }
    
    public function increment($id, $amount = 1) {
        // عملية ذرية باستخدام قاعدة البيانات
        $stmt = $this->pdo->prepare("
            UPDATE counters 
            SET value = value + :amount, version = version + 1
            WHERE id = :id
        ");
        
        return $stmt->execute([
            ':id' => $id,
            ':amount' => $amount
        ]);
    }
    
    public function getValue($id) {
        $stmt = $this->pdo->prepare("SELECT value FROM counters WHERE id = :id");
        $stmt->execute([':id' => $id]);
        return (int) $stmt->fetchColumn();
    }
    
    // عملية آمنة مع التحقق من الإصدار (Optimistic Locking)
    public function updateWithVersion($id, $newValue) {
        $this->pdo->beginTransaction();
        
        try {
            // قراءة القيمة الحالية مع الإصدار
            $stmt = $this->pdo->prepare("
                SELECT value, version FROM counters WHERE id = :id FOR UPDATE
            ");
            $stmt->execute([':id' => $id]);
            $current = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$current) {
                throw new Exception("المفتاح غير موجود");
            }
            
            // تحديث القيمة
            $stmt = $this->pdo->prepare("
                UPDATE counters 
                SET value = :value, version = version + 1
                WHERE id = :id AND version = :version
            ");
            
            $result = $stmt->execute([
                ':id' => $id,
                ':value' => $newValue,
                ':version' => $current['version']
            ]);
            
            if ($stmt->rowCount() === 0) {
                throw new Exception("تم تعديل البيانات أثناء المعالجة");
            }
            
            $this->pdo->commit();
            return true;
            
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }
}

// استخدام الكلاس
try {
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    $counter = new AtomicCounter($pdo);
    
    // زيادة آمنة
    $counter->increment('visits', 1);
    $counter->increment('visits', 1);
    $counter->increment('visits', 1);
    
    echo "الزيارات: " . $counter->getValue('visits') . "\n";
    
    // تحديث مع التحقق من الإصدار
    $counter->updateWithVersion('visits', 100);
    
} catch (Exception $e) {
    echo "خطأ: " . $e->getMessage();
}
?>

📌 18. أخطاء معالجة الملفات الكبيرة

✅ قراءة ملفات CSV كبيرة

php

<?php
class LargeFileProcessor {
    private $filePath;
    private $batchSize = 1000;
    private $callbacks = [];
    
    public function __construct($filePath) {
        if (!file_exists($filePath)) {
            throw new Exception("الملف غير موجود: $filePath");
        }
        $this->filePath = $filePath;
    }
    
    public function setBatchSize($size) {
        $this->batchSize = $size;
        return $this;
    }
    
    public function onRow($callback) {
        $this->callbacks['row'][] = $callback;
        return $this;
    }
    
    public function onBatch($callback) {
        $this->callbacks['batch'][] = $callback;
        return $this;
    }
    
    public function onComplete($callback) {
        $this->callbacks['complete'][] = $callback;
        return $this;
    }
    
    public function processCSV($delimiter = ',', $hasHeader = true) {
        $handle = fopen($this->filePath, 'r');
        if (!$handle) {
            throw new Exception("لا يمكن فتح الملف");
        }
        
        $headers = [];
        $batch = [];
        $rowCount = 0;
        $batchCount = 0;
        
        // قراءة الـ header إذا وجد
        if ($hasHeader) {
            $headers = fgetcsv($handle, 0, $delimiter);
        }
        
        while (($row = fgetcsv($handle, 0, $delimiter)) !== false) {
            $rowCount++;
            
            // دمج البيانات مع الـ headers
            if ($hasHeader && count($headers) === count($row)) {
                $row = array_combine($headers, $row);
            }
            
            // تنفيذ callbacks لكل صف
            foreach ($this->callbacks['row'] ?? [] as $callback) {
                $callback($row, $rowCount);
            }
            
            $batch[] = $row;
            
            // معالجة الدفعة
            if (count($batch) >= $this->batchSize) {
                $batchCount++;
                foreach ($this->callbacks['batch'] ?? [] as $callback) {
                    $callback($batch, $batchCount);
                }
                $batch = [];
                
                // تحرير الذاكرة
                gc_collect_cycles();
            }
        }
        
        // معالجة الدفعة الأخيرة
        if (!empty($batch)) {
            $batchCount++;
            foreach ($this->callbacks['batch'] ?? [] as $callback) {
                $callback($batch, $batchCount);
            }
        }
        
        fclose($handle);
        
        // تنفيذ callbacks الاكتمال
        foreach ($this->callbacks['complete'] ?? [] as $callback) {
            $callback($rowCount, $batchCount);
        }
        
        return $rowCount;
    }
}

// استخدام المعالج
$processor = new LargeFileProcessor('data.csv');
$processor->setBatchSize(5000)
    ->onRow(function($row, $index) {
        // معالجة كل صف
        if ($index % 10000 == 0) {
            echo "معالجة الصف $index...\n";
        }
    })
    ->onBatch(function($batch, $batchNumber) {
        // معالجة الدفعة (مثل حفظ في قاعدة البيانات)
        echo "معالجة الدفعة $batchNumber (تم معالجة " . count($batch) . " صف)\n";
        
        // مثال: حفظ في قاعدة البيانات
        // $db->insertBatch($batch);
    })
    ->onComplete(function($totalRows, $totalBatches) {
        echo "تم الانتهاء! تم معالجة $totalRows صف في $totalBatches دفعة\n";
    });

$processor->processCSV(',', true);
?>

📌 19. أخطاء تحسين استعلامات قاعدة البيانات

✅ مشكلة استعلامات N+1

php

// ❌ الكود الخاطئ - مشكلة N+1
<?php
// استعلام واحد للمستخدمين
$users = $db->query("SELECT * FROM users LIMIT 10");

foreach ($users as $user) {
    // استعلام إضافي لكل مستخدم - هذه هي المشكلة!
    $orders = $db->query("SELECT * FROM orders WHERE user_id = {$user['id']}");
    // معالجة الطلبات...
}
?>

php

// ✅ الحل الصحيح - استخدام JOIN
<?php
// استعلام واحد مع JOIN
$sql = "
    SELECT u.*, o.id as order_id, o.total, o.status
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.status = 'active'
    ORDER BY u.id, o.created_at DESC
";

$results = $db->query($sql);

// تجميع البيانات
$users = [];
while ($row = $results->fetch_assoc()) {
    $userId = $row['id'];
    if (!isset($users[$userId])) {
        $users[$userId] = [
            'id' => $row['id'],
            'name' => $row['name'],
            'email' => $row['email'],
            'orders' => []
        ];
    }
    
    if ($row['order_id']) {
        $users[$userId]['orders'][] = [
            'id' => $row['order_id'],
            'total' => $row['total'],
            'status' => $row['status']
        ];
    }
}
?>

✅ استخدام الفهارس (Indexes)

sql

-- ❌ استعلام بطيء بدون فهرسة
SELECT * FROM orders WHERE user_id = 123 AND created_at > '2024-01-01';

-- ✅ إضافة فهارس مناسبة
CREATE INDEX idx_orders_user_created ON orders (user_id, created_at);
CREATE INDEX idx_orders_status ON orders (status);

-- ✅ استعلام محسّن
SELECT * FROM orders 
WHERE user_id = 123 AND created_at > '2024-01-01'
ORDER BY created_at DESC
LIMIT 10;

✅ استخدام التخزين المؤقت (Caching)

php

<?php
class QueryCache {
    private $cache = [];
    private $cacheTime = 3600;  // ساعة واحدة
    private $enabled = true;
    
    public function __construct($enabled = true) {
        $this->enabled = $enabled;
        if ($this->enabled) {
            // استخدام APC, Redis, أو Memcached
            if (extension_loaded('apcu')) {
                $this->cache = new APCuCache();
            } elseif (extension_loaded('redis')) {
                $this->cache = new RedisCache();
            } else {
                $this->cache = new ArrayCache();
            }
        }
    }
    
    public function get($query, $params = []) {
        if (!$this->enabled) {
            return null;
        }
        
        $key = $this->generateKey($query, $params);
        return $this->cache->get($key);
    }
    
    public function set($query, $params, $result) {
        if (!$this->enabled) {
            return false;
        }
        
        $key = $this->generateKey($query, $params);
        return $this->cache->set($key, $result, $this->cacheTime);
    }
    
    public function invalidate($query = null) {
        if ($query) {
            // حذف مفتاح محدد
            $key = $this->generateKey($query, []);
            $this->cache->delete($key);
        } else {
            // حذف كل الكاش
            $this->cache->clear();
        }
    }
    
    private function generateKey($query, $params) {
        return 'query_' . md5($query . serialize($params));
    }
}

class DBWithCache {
    private $db;
    private $cache;
    
    public function __construct($db, $cache) {
        $this->db = $db;
        $this->cache = $cache;
    }
    
    public function query($sql, $params = [], $useCache = true) {
        if (!$useCache) {
            return $this->executeQuery($sql, $params);
        }
        
        // محاولة القراءة من الكاش
        $cached = $this->cache->get($sql, $params);
        if ($cached !== null) {
            return $cached;
        }
        
        // تنفيذ الاستعلام
        $result = $this->executeQuery($sql, $params);
        
        // تخزين النتيجة في الكاش
        $this->cache->set($sql, $params, $result);
        
        return $result;
    }
    
    private function executeQuery($sql, $params) {
        // تنفيذ الاستعلام هنا
        // ...
    }
}
?>

📌 20. أخطاء تعدد المهام (Multitasking)

✅ استخدام Parallel Processing في PHP

php

<?php
// ✅ استخدام pcntl_fork للعمليات المتوازية
class ParallelProcessor {
    private $tasks = [];
    private $maxProcesses = 4;
    
    public function addTask($callback, $data) {
        $this->tasks[] = [
            'callback' => $callback,
            'data' => $data,
            'pid' => null,
            'result' => null
        ];
        return $this;
    }
    
    public function setMaxProcesses($count) {
        $this->maxProcesses = $count;
        return $this;
    }
    
    public function execute() {
        if (!function_exists('pcntl_fork')) {
            throw new Exception("pcntl_fork غير مدعوم في هذا النظام");
        }
        
        $running = [];
        $results = [];
        
        foreach ($this->tasks as $index => $task) {
            // انتظار إذا وصلنا للحد الأقصى
            while (count($running) >= $this->maxProcesses) {
                $pid = pcntl_wait($status, WNOHANG);
                if ($pid > 0) {
                    // إزالة العملية المنتهية
                    unset($running[$pid]);
                }
                usleep(100000);  // 0.1 ثانية
            }
            
            $pid = pcntl_fork();
            
            if ($pid == -1) {
                throw new Exception("فشل إنشاء عملية جديدة");
            } elseif ($pid == 0) {
                // العملية الفرعية
                $result = $task['callback']($task['data']);
                exit($result);
            } else {
                // العملية الرئيسية
                $this->tasks[$index]['pid'] = $pid;
                $running[$pid] = $index;
            }
        }
        
        // انتظار اكتمال جميع العمليات
        while (count($running) > 0) {
            $pid = pcntl_wait($status);
            if ($pid > 0) {
                $index = $running[$pid];
                $this->tasks[$index]['result'] = pcntl_wexitstatus($status);
                unset($running[$pid]);
            }
        }
        
        // جمع النتائج
        foreach ($this->tasks as $task) {
            $results[] = $task['result'];
        }
        
        return $results;
    }
}

// استخدام المعالج المتوازي
$processor = new ParallelProcessor();

$tasks = [
    ['name' => 'Task 1', 'data' => range(1, 100)],
    ['name' => 'Task 2', 'data' => range(1, 200)],
    ['name' => 'Task 3', 'data' => range(1, 300)],
    ['name' => 'Task 4', 'data' => range(1, 400)],
    ['name' => 'Task 5', 'data' => range(1, 500)]
];

foreach ($tasks as $task) {
    $processor->addTask(
        function($data) {
            // معالجة البيانات
            $sum = array_sum($data);
            usleep(500000);  // محاكاة عمل ثقيل
            return $sum;
        },
        $task['data']
    );
}

$processor->setMaxProcesses(3);
$results = $processor->execute();

echo "النتائج: " . implode(', ', $results) . "\n";
?>

📌 21. أخطاء Logging و Monitoring

✅ نظام تسجيل الأخطاء المتقدم

php

<?php
class AdvancedLogger {
    const LEVEL_DEBUG = 0;
    const LEVEL_INFO = 1;
    const LEVEL_WARNING = 2;
    const LEVEL_ERROR = 3;
    const LEVEL_CRITICAL = 4;
    
    private $logFile;
    private $logLevel = self::LEVEL_INFO;
    private $maxSize = 10485760;  // 10MB
    private $maxFiles = 5;
    private $context = [];
    private $handlers = [];
    
    public function __construct($logFile = 'app.log') {
        $this->logFile = $logFile;
        $this->ensureLogDirectory();
    }
    
    public function setLevel($level) {
        $this->logLevel = $level;
        return $this;
    }
    
    public function addContext($key, $value) {
        $this->context[$key] = $value;
        return $this;
    }
    
    public function addHandler($handler) {
        $this->handlers[] = $handler;
        return $this;
    }
    
    public function debug($message, $data = null) {
        $this->log(self::LEVEL_DEBUG, $message, $data);
    }
    
    public function info($message, $data = null) {
        $this->log(self::LEVEL_INFO, $message, $data);
    }
    
    public function warning($message, $data = null) {
        $this->log(self::LEVEL_WARNING, $message, $data);
    }
    
    public function error($message, $data = null) {
        $this->log(self::LEVEL_ERROR, $message, $data);
    }
    
    public function critical($message, $data = null) {
        $this->log(self::LEVEL_CRITICAL, $message, $data);
    }
    
    public function log($level, $message, $data = null) {
        if ($level < $this->logLevel) {
            return;
        }
        
        $logEntry = $this->formatLogEntry($level, $message, $data);
        
        // كتابة في ملف السجلات
        $this->writeLog($logEntry);
        
        // تنفيذ معالجات إضافية
        foreach ($this->handlers as $handler) {
            $handler($logEntry, $level, $message, $data);
        }
    }
    
    private function formatLogEntry($level, $message, $data) {
        $levelNames = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'];
        $timestamp = date('Y-m-d H:i:s.u');
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'CLI';
        $method = $_SERVER['REQUEST_METHOD'] ?? 'CLI';
        $uri = $_SERVER['REQUEST_URI'] ?? 'CLI';
        
        $entry = [
            'timestamp' => $timestamp,
            'level' => $levelNames[$level],
            'message' => $message,
            'ip' => $ip,
            'method' => $method,
            'uri' => $uri,
            'context' => $this->context
        ];
        
        if ($data !== null) {
            $entry['data'] = $data;
        }
        
        return json_encode($entry) . "\n";
    }
    
    private function writeLog($entry) {
        // تدوير الملفات إذا لزم الأمر
        $this->rotateLogs();
        
        file_put_contents($this->logFile, $entry, FILE_APPEND | LOCK_EX);
    }
    
    private function rotateLogs() {
        if (!file_exists($this->logFile)) {
            return;
        }
        
        if (filesize($this->logFile) < $this->maxSize) {
            return;
        }
        
        // حذف أقدم ملف
        $lastFile = $this->logFile . '.' . $this->maxFiles;
        if (file_exists($lastFile)) {
            unlink($lastFile);
        }
        
        // إعادة تسمية الملفات
        for ($i = $this->maxFiles - 1; $i > 0; $i--) {
            $old = $this->logFile . '.' . $i;
            $new = $this->logFile . '.' . ($i + 1);
            if (file_exists($old)) {
                rename($old, $new);
            }
        }
        
        // نقل الملف الحالي
        rename($this->logFile, $this->logFile . '.1');
    }
    
    private function ensureLogDirectory() {
        $dir = dirname($this->logFile);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
    }
    
    // البحث في السجلات
    public function search($search, $limit = 100) {
        $results = [];
        $handle = fopen($this->logFile, 'r');
        
        if (!$handle) {
            return $results;
        }
        
        while (($line = fgets($handle)) !== false && count($results) < $limit) {
            $entry = json_decode($line, true);
            if ($entry && strpos($line, $search) !== false) {
                $results[] = $entry;
            }
        }
        
        fclose($handle);
        return $results;
    }
}

// استخدام نظام التسجيل
$logger = new AdvancedLogger('logs/application.log');
$logger->setLevel(AdvancedLogger::LEVEL_DEBUG)
       ->addContext('app', 'MyApp')
       ->addContext('version', '1.0.0')
       ->addHandler(function($entry, $level, $message, $data) {
           // إرسال الأخطاء الحرجة إلى البريد الإلكتروني
           if ($level >= AdvancedLogger::LEVEL_CRITICAL) {
               // mail('admin@example.com', 'خطأ حرج', $entry);
           }
       });

// تسجيل الأحداث
$logger->info('تطبيق بدأ');
$logger->debug('معالجة الطلب', ['user_id' => 123]);
$logger->warning('بطء في الاستعلام', ['query' => 'SELECT * FROM users', 'time' => 2.5]);

try {
    // بعض الكود
    throw new Exception('خطأ تجريبي');
} catch (Exception $e) {
    $logger->error('خطأ في التطبيق', [
        'exception' => [
            'message' => $e->getMessage(),
            'file' => $e->getFile(),
            'line' => $e->getLine(),
            'trace' => $e->getTraceAsString()
        ]
    ]);
}

$logger->critical('خطأ فادح!', ['critical_data' => '...']);

// البحث في السجلات
$errors = $logger->search('ERROR');
echo "عدد الأخطاء: " . count($errors) . "\n";
?>

📌 22. أخطاء التعامل مع الصور والملفات

✅ معالجة الصور (تحويل، ضغط، تغيير الحجم)

php

<?php
class ImageProcessor {
    private $sourcePath;
    private $image;
    private $type;
    private $width;
    private $height;
    
    public function __construct($sourcePath) {
        if (!file_exists($sourcePath)) {
            throw new Exception("الملف غير موجود: $sourcePath");
        }
        
        $this->sourcePath = $sourcePath;
        $this->loadImage();
    }
    
    private function loadImage() {
        list($this->width, $this->height, $this->type) = getimagesize($this->sourcePath);
        
        switch ($this->type) {
            case IMAGETYPE_JPEG:
                $this->image = imagecreatefromjpeg($this->sourcePath);
                break;
            case IMAGETYPE_PNG:
                $this->image = imagecreatefrompng($this->sourcePath);
                break;
            case IMAGETYPE_GIF:
                $this->image = imagecreatefromgif($this->sourcePath);
                break;
            default:
                throw new Exception("نوع الصورة غير مدعوم");
        }
        
        if (!$this->image) {
            throw new Exception("فشل تحميل الصورة");
        }
    }
    
    public function resize($newWidth, $newHeight, $keepAspect = true) {
        if ($keepAspect) {
            $ratio = $this->width / $this->height;
            if ($newWidth / $newHeight > $ratio) {
                $newWidth = $newHeight * $ratio;
            } else {
                $newHeight = $newWidth / $ratio;
            }
        }
        
        $newImage = imagecreatetruecolor($newWidth, $newHeight);
        
        // الحفاظ على الشفافية للصور PNG و GIF
        if ($this->type == IMAGETYPE_PNG || $this->type == IMAGETYPE_GIF) {
            imagecolortransparent($newImage, imagecolorallocatealpha($newImage, 0, 0, 0, 127));
            imagealphablending($newImage, false);
            imagesavealpha($newImage, true);
        }
        
        imagecopyresampled(
            $newImage, $this->image,
            0, 0, 0, 0,
            $newWidth, $newHeight,
            $this->width, $this->height
        );
        
        $this->image = $newImage;
        $this->width = $newWidth;
        $this->height = $newHeight;
        
        return $this;
    }
    
    public function crop($x, $y, $width, $height) {
        $newImage = imagecrop($this->image, [
            'x' => $x,
            'y' => $y,
            'width' => $width,
            'height' => $height
        ]);
        
        if ($newImage) {
            $this->image = $newImage;
            $this->width = $width;
            $this->height = $height;
        }
        
        return $this;
    }
    
    public function addWatermark($watermarkPath, $position = 'bottom-right', $opacity = 50) {
        $watermark = new self($watermarkPath);
        
        // ضبط حجم العلامة المائية
        $wmWidth = $this->width * 0.2;
        $wmHeight = $watermark->height * ($wmWidth / $watermark->width);
        $watermark->resize($wmWidth, $wmHeight, true);
        
        // تحديد الموقع
        $x = $this->width - $watermark->width - 10;
        $y = $this->height - $watermark->height - 10;
        
        switch ($position) {
            case 'top-left':
                $x = 10; $y = 10;
                break;
            case 'top-right':
                $x = $this->width - $watermark->width - 10; $y = 10;
                break;
            case 'bottom-left':
                $x = 10; $y = $this->height - $watermark->height - 10;
                break;
            case 'center':
                $x = ($this->width - $watermark->width) / 2;
                $y = ($this->height - $watermark->height) / 2;
                break;
        }
        
        // دمج العلامة المائية مع الشفافية
        imagecopymerge(
            $this->image,
            $watermark->image,
            $x, $y, 0, 0,
            $watermark->width,
            $watermark->height,
            $opacity
        );
        
        return $this;
    }
    
    public function compress($quality = 80) {
        // ضغط الصورة دون تغيير الأبعاد
        return $this;
    }
    
    public function save($outputPath, $quality = 80) {
        $dir = dirname($outputPath);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        
        switch ($this->type) {
            case IMAGETYPE_JPEG:
                imagejpeg($this->image, $outputPath, $quality);
                break;
            case IMAGETYPE_PNG:
                // PNG: التحويل من quality (0-100) إلى compression (0-9)
                $compression = 9 - round($quality / 11.11);
                imagepng($this->image, $outputPath, $compression);
                break;
            case IMAGETYPE_GIF:
                imagegif($this->image, $outputPath);
                break;
            default:
                throw new Exception("نوع الصورة غير مدعوم للحفظ");
        }
        
        return $this;
    }
    
    public function getInfo() {
        return [
            'width' => $this->width,
            'height' => $this->height,
            'type' => image_type_to_extension($this->type, false),
            'size' => filesize($this->sourcePath)
        ];
    }
    
    public function __destruct() {
        if ($this->image) {
            imagedestroy($this->image);
        }
    }
}

// استخدام معالج الصور
try {
    $image = new ImageProcessor('source.jpg');
    
    // الحصول على معلومات الصورة
    print_r($image->getInfo());
    
    // تغيير الحجم مع الحفاظ على النسبة
    $image->resize(800, 600, true)
          ->addWatermark('logo.png', 'bottom-right', 30)
          ->save('output/resized_with_watermark.jpg', 85);
    
    echo "تم معالجة الصورة بنجاح ✅\n";
    
} catch (Exception $e) {
    echo "خطأ في معالجة الصورة: " . $e->getMessage();
}
?>

🚀 نصائح إضافية لتحسين كود PHP

✅ استخدام الكود الأنظف (Clean Code)

php

<?php
// ❌ كود سيء
function do($d, $u) {
    $r = [];
    foreach($d as $k => $v) {
        if($v['status'] == 'active' && $v['user_id'] == $u) {
            $r[] = $v;
        }
    }
    return $r;
}

// ✅ كود نظيف
class UserDataFilter {
    private $data;
    
    public function __construct(array $data) {
        $this->data = $data;
    }
    
    public function filterByUserId(int $userId): array {
        return array_filter($this->data, function($item) use ($userId) {
            return $this->isUserActive($item) && $this->belongsToUser($item, $userId);
        });
    }
    
    private function isUserActive(array $item): bool {
        return isset($item['status']) && $item['status'] === 'active';
    }
    
    private function belongsToUser(array $item, int $userId): bool {
        return isset($item['user_id']) && $item['user_id'] === $userId;
    }
}
?>

✅ استخدام PHPStan أو Psalm لتحليل الكود

bash

# تثبيت PHPStan
composer require --dev phpstan/phpstan

# تحليل الكود
vendor/bin/phpstan analyse src/ --level=max

# تثبيت Psalm
composer require --dev vimeo/psalm

# تحليل الكود
vendor/bin/psalm --init
vendor/bin/psalm

✅ استخدام Xdebug للـ Debugging

ini

; php.ini
[xdebug]
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_port=9003
xdebug.client_host=127.0.0.1
xdebug.log=/var/log/xdebug.log
xdebug.idekey=PHPSTORM

📊 جدول مقارنة: أدوات حل الأخطاء

الأداةالاستخدامالمزاياالعيوب
XdebugDebugging متقدم• نقاط توقف
• تتبع المكدس
• تحليل الأداء
• بطيء
• يحتاج تكوين
PHPStanتحليل ثابت• يكتشف الأخطاء مسبقاً
• مستوى تحليل قابل للتعديل
• يحتاج تعلم
• قد يعطي نتائج إيجابية خاطئة
Psalmتحليل ثابت• أسرع من PHPStan
• تثبيت سهل
• أقل شهرة
• دقة أقل في بعض الحالات
Error Logsمراقبة مستمرة• بسيط
• لا يؤثر على الأداء
• لا يكتشف الأخطاء فوراً
• يحتاج مراجعة يدوية
Sentryمراقبة الأخطاء• تنبيهات فورية
• تقارير مفصلة
• تحليل الاتجاهات
• مدفوع
• يحتاج اتصال بالإنترنت

🎯 هل تحتاج حل لمشكلة محددة؟

أرسل لي:

  1. الكود الكامل
  2. رسالة الخطأ مع الـ Stack Trace
  3. إصدار PHP والبيئة

سأعطيك حلاً مفصلاً ومخصصاً! 🚀

التفاصيل الكاملة، وسأقدم لك حلاً مخصصاً خطوة بخطوة! 🚀

مرحباً! من خلال خبرتي في حل مشكلات PHP، سأقوم بتحليل خطأ 500 Internal Server Error الخاص بك بشكل شامل وحلّه خطوة بخطوة.

📌 تحليل الخطأ

الخطأ الذي ظهر لك هو:

text

Oops! An Error Occurred
The server returned a "500 Internal Server Error".

هذا خطأ عام في الخادم، وهو شائع جداً في تطبيقات PHP و Laravel تحديداً.

🔍 الأسباب الأكثر احتمالاً في بيئة Laravel

بناءً على تجربتي، أسباب هذا الخطأ في Laravel غالباً ما تكون:

  1. مشكلة في ملف .env (تكوين قاعدة البيانات أو المفاتيح)
  2. صلاحيات المجلدات (storage و bootstrap/cache)
  3. خطأ في الكود (خاصة في routes أو controllers)
  4. مشكلة في قاعدة البيانات (اتصال فاشل)
  5. نقص في الذاكرة أو وقت التنفيذ

🛠 الحلول التفصيلية (خطوة بخطوة)

✅ الحل الأول: تفعير عرض الأخطاء في Laravel

افتح ملف .env وغير:

env

APP_DEBUG=true
APP_ENV=local

ثم تأكد من وجود هذا الكود في ملف config/app.php:

php

'debug' => env('APP_DEBUG', true),

✅ الحل الثاني: فحص سجل الأخطاء (الأهم!)

شغّل هذا الأمر في الطرفية لرؤية الخطأ الفعلي:

bash

tail -f storage/logs/laravel.log

أو ابحث في مجلد storage/logs/ عن ملف laravel.log واقرأ آخر الأخطاء.

مثال على خطأ شائع في السجل:

text

SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES)

هذا يعني أن بيانات الاتصال بقاعدة البيانات خاطئة.

✅ الحل الثالث: إصلاح صلاحيات المجلدات (الحل الأكثر شيوعاً!)

نفذ الأوامر التالية في مجلد المشروع:

bash

# للـ Linux/Mac
chmod -R 775 storage
chmod -R 775 bootstrap/cache
chmod -R 775 vendor

# أو
sudo chmod -R 777 storage
sudo chmod -R 777 bootstrap/cache

للـ Windows: اذهب إلى خصائص المجلدات وأعطي صلاحيات كاملة للمستخدم IIS_IUSRS أو Everyone.

✅ الحل الرابع: إعادة تعيين الكاش والتكوين

نفذ الأوامر التالية بالترتيب:

bash

# حذف الكاش
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

# إعادة بناء الكاش
php artisan config:cache
php artisan route:cache
php artisan view:cache

# أو بشكل شامل
php artisan optimize

✅ الحل الخامس: التحقق من قاعدة البيانات

تأكد من صحة بيانات الاتصال في ملف .env:

env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_username
DB_PASSWORD=your_password

ثم جرب الاتصال:

bash

php artisan db:show

إذا فشل، تأكد من تشغيل خدمة MySQL أو استخدم SQLite:

env

DB_CONNECTION=sqlite
# ثم أنشئ ملف database/database.sqlite

✅ الحل السادس: زيادة حدود PHP

أضف في ملف .htaccess (إن وجد):

apache

php_value memory_limit 256M
php_value max_execution_time 300

أو في ملف php.ini:

ini

memory_limit = 256M
max_execution_time = 300

✅ الحل السابع: فحص ملفات التوجيه (routes)

تأكد من صحة ملفات routes/web.php و routes/api.php. مثال على خطأ شائع:

php

// ❌ خطأ: نسيان إرجاع Response
Route::get('/test', function () {
    // مفقود return
});

// ✅ صحيح
Route::get('/test', function () {
    return view('welcome');
});

✅ الحل الثامن: إعادة تثبيت الاعتماديات

في بعض الأحيان، تتلف حزمة معينة:

bash

# حذف مجلد vendor
rm -rf vendor

# إعادة تثبيت الاعتماديات
composer install

# أو مع محاولة التحديث
composer update

✅ الحل التاسع: استخدام Tinker للكشف السريع

جرب تشغيل هذا الأمر:

bash

php artisan tinker

ثم اختبر أي كود، مثل:

php

>>> config('app.env');
>>> DB::connection()->getPdo();

إذا ظهر خطأ هنا، فالمشكلة في البيئة أو قاعدة البيانات.

📋 قائمة المراجعة السريعة للـ Laravel

الخطوةالأمر/الإجراءالنتيجة المتوقعة
1php artisan config:clearمسح الكاش
2php artisan cache:clearمسح الكاش
3chmod -R 775 storage bootstrap/cacheصلاحيات صحيحة
4composer dump-autoloadإعادة تحميل الكلاسات
5php artisan optimizeتحسين الأداء
6التحقق من .envبيانات صحيحة
7php artisan serveتشغيل السيرفر المحلي
8فتح http://localhost:8000رؤية التطبيق

🔧 حل متقدم: تشغيل السيرفر مع عرض الأخطاء

إذا لم تنجح أي من الحلول السابقة، جرب تشغيل السيرفر بهذه الطريقة لرؤية الخطأ مباشرة:

bash

php -S localhost:8000 -t public

ثم اذهب إلى المتصفح وافتح http://localhost:8000، وستظهر لك رسالة الخطأ الفعلية.

💡 نصائح إضافية للمستقبل

  1. استخدم Git للتحكم في الإصدارات، واحتفظ بنسخة احتياطية قبل أي تغيير.
  2. لا تهمل ملف laravel.log، فهو أفضل صديق لك في حل الأخطاء.
  3. اختبر التطبيق محلياً قبل رفعه إلى الخادم.
  4. استخدم dd() لتصحيح الأخطاء:

php

dd($variable); // سيوقف التنفيذ ويعرض قيمة المتغير

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

  1. أولاً: فعّل APP_DEBUG=true في .env
  2. ثانياً: اقرأ ملف storage/logs/laravel.log
  3. ثالثاً: صلح المشكلة التي تظهر في السجل
  4. رابعاً: نظف الكاش (php artisan config:clear)
  5. خامساً: أعد تشغيل السيرفر

إذا أرسلت لي محتوى ملف laravel.log، سأعطيك حلاً دقيقاً 100% لمشكلتك المحددة! 🚀

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

📚 الجزء الثاني: أخطاء Laravel المتقدمة وحلولها

🔥 1. خطأ: Target class [Controller] does not exist.

❌ الكود المسبب:

php

// routes/web.php
Route::get('/user', 'UserController@show'); // الطريقة القديمة

✅ الحلول:

الحل 1: استخدام الـ Namespace الكامل

php

use App\Http\Controllers\UserController;

Route::get('/user', [UserController::class, 'show']);

الحل 2: استخدام الـ String مع الـ Namespace

php

Route::get('/user', 'App\Http\Controllers\UserController@show');

الحل 3: التأكد من وجود الكلاس

bash

# تحقق من وجود الملف
ls app/Http/Controllers/UserController.php

# أنشئ الـ Controller إذا لم يكن موجوداً
php artisan make:controller UserController

🔥 2. خطأ: SQLSTATE[42S02]: Base table or view not found

❌ الكود المسبب:

php

// Model
class User extends Model
{
    protected $table = 'userss'; // خطأ إملائي
}

✅ الحلول:

الحل 1: تحديد اسم الجدول بشكل صحيح

php

class User extends Model
{
    protected $table = 'users'; // الاسم الصحيح
}

الحل 2: استخدام التسمية الافتراضية (Plural)

php

// Laravel يتوقع جدول 'users' تلقائياً
class User extends Model
{
    // لا حاجة لتحديد $table
}

الحل 3: إنشاء الجدول إذا كان مفقوداً

bash

# إنشاء ميجريشن
php artisan make:migration create_users_table

# تشغيل الميجريشن
php artisan migrate

🔥 3. خطأ: Maximum execution time of 60 seconds exceeded

❌ الكود المسبب:

php

// عملية طويلة جداً
foreach (range(1, 1000000) as $i) {
    // معالجة ثقيلة
    processHeavyTask($i);
}

✅ الحلول المتقدمة:

الحل 1: زيادة وقت التنفيذ مؤقتاً

php

// في بداية الكود
set_time_limit(300); // 5 دقائق

// أو في ملف .htaccess
php_value max_execution_time 300

الحل 2: استخدام الـ Queue (الأفضل)

php

// إنشاء Job
php artisan make:job ProcessLargeData

// في الـ Job
class ProcessLargeData implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
    public function handle()
    {
        // معالجة البيانات هنا
        foreach (range(1, 1000000) as $i) {
            // معالجة
        }
    }
}

// تشغيل الـ Job
ProcessLargeData::dispatch();

الحل 3: تقسيم المهمة (Chunking)

php

// معالجة البيانات على دفعات
User::chunk(100, function ($users) {
    foreach ($users as $user) {
        // معالجة كل مستخدم
    }
});

🔥 4. خطأ: The stream or file "/path/to/storage/logs/laravel.log" could not be opened: failed to open stream: Permission denied

✅ الحلول الأمنية:

الحل 1: تعيين الصلاحيات الصحيحة (الموصى به)

bash

# للـ Linux/Mac
sudo chown -R $USER:www-data storage
sudo chown -R $USER:www-data bootstrap/cache
chmod -R 775 storage
chmod -R 775 bootstrap/cache

# أو إذا كنت تستخدم Nginx
sudo chown -R www-data:www-data storage
sudo chown -R www-data:www-data bootstrap/cache

الحل 2: استخدام ACL (Access Control Lists)

bash

# منح صلاحيات للمستخدم الحالي
sudo setfacl -R -m u:www-data:rwx storage
sudo setfacl -R -m u:www-data:rwx bootstrap/cache
sudo setfacl -R -m u:$USER:rwx storage
sudo setfacl -R -m u:$USER:rwx bootstrap/cache

الحل 3: تغيير مالك المجلدات في بيئة التطوير

bash

# فقط للتطوير المحلي!
sudo chmod -R 777 storage
sudo chmod -R 777 bootstrap/cache

🔥 5. خطأ: No application encryption key has been specified

✅ الحل:

bash

# إنشاء مفتاح التشفير
php artisan key:generate

# التحقق من وجود المفتاح في .env
APP_KEY=base64:your_generated_key_here

🔥 6. خطأ: Call to undefined method Illuminate\Database\Query\Builder::whereHas()

❌ الكود المسبب:

php

// استخدام whereHas على Query Builder (خطأ)
$users = DB::table('users')
    ->whereHas('posts', function ($query) {
        $query->where('active', 1);
    })
    ->get();

✅ الحلول:

الحل 1: استخدام Eloquent

php

$users = User::whereHas('posts', function ($query) {
    $query->where('active', 1);
})->get();

الحل 2: استخدام JOIN في Query Builder

php

$users = DB::table('users')
    ->join('posts', 'users.id', '=', 'posts.user_id')
    ->where('posts.active', 1)
    ->select('users.*')
    ->distinct()
    ->get();

الحل 3: استخدام whereExists

php

$users = DB::table('users')
    ->whereExists(function ($query) {
        $query->select(DB::raw(1))
            ->from('posts')
            ->whereColumn('posts.user_id', 'users.id')
            ->where('posts.active', 1);
    })
    ->get();

🔥 7. خطأ: Method Illuminate\Http\Request::input does not exist

❌ الكود المسبب:

php

// استخدام input() على Request بطريقة خاطئة
$request->input(); // بدون معامل

✅ الحلول:

الحل 1: استخدام input() مع معامل

php

$name = $request->input('name');
$all = $request->all(); // لجلب جميع البيانات

الحل 2: استخدام الـ Helper functions

php

$name = request('name');
$all = request()->all();

الحل 3: استخدام الـ Dependency Injection

php

public function store(Request $request)
{
    $validated = $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|email',
    ]);
    
    // أو
    $name = $request->input('name');
}

🔥 8. خطأ: Class 'App\Models\User' not found

✅ الحلول:

الحل 1: التحقق من الـ Namespace

php

// تأكد من وجود هذا السطر في بداية الملف
namespace App\Models;

class User extends Authenticatable
{
    // ...
}

الحل 2: إعادة تحميل الـ Autoloader

bash

composer dump-autoload

الحل 3: التحقق من اسم الملف

bash

# تأكد من أن اسم الملف مطابق لاسم الكلاس
# User.php (وليس user.php)
ls app/Models/User.php

🛠 أدوات متقدمة لتشخيص الأخطاء

1. Laravel Debugbar

التثبيت:

bash

composer require barryvdh/laravel-debugbar --dev

الاستخدام:
يعرض شريط أدوات في أسفل الصفحة يحتوي على:

  • وقت التنفيذ
  • استعلامات قاعدة البيانات
  • الذاكرة المستخدمة
  • الـ Routes
  • المتغيرات

2. Telescope (لتتبع الأداء)

التثبيت:

bash

composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

الاستخدام:

bash

php artisan telescope

يعرض:

  • الطلبات الواردة
  • الاستثناءات
  • الاستعلامات البطيئة
  • الـ Jobs

3. Ray (للتصحيح المتقدم)

التثبيت:

bash

composer require spatie/laravel-ray --dev

الاستخدام:

php

ray($variable)->green(); // عرض متغير بلون معين
ray()->showQueries(); // عرض استعلامات DB
ray()->caller(); // عرض موقع الاستدعاء

4. Log Viewer (لعرض السجلات)

التثبيت:

bash

composer require opcodesio/log-viewer --dev

الاستخدام:

bash

php artisan log-viewer:publish

ثم افتح /log-viewer في المتصفح.


🔐 أخطاء أمنية شائعة في Laravel

1. Mass Assignment Vulnerability

❌ الكود غير الآمن:

php

// في Controller
public function update(Request $request, $id)
{
    $user = User::find($id);
    $user->update($request->all()); // خطير!
}

✅ الحلول:

الحل 1: استخدام الـ $fillable

php

class User extends Model
{
    protected $fillable = ['name', 'email', 'password'];
}

الحل 2: استخدام الـ $guarded

php

class User extends Model
{
    protected $guarded = ['id', 'is_admin'];
}

الحل 3: استخدام Request مع validation

php

public function update(Request $request, $id)
{
    $validated = $request->validate([
        'name' => 'required|string',
        'email' => 'required|email',
    ]);
    
    $user = User::find($id);
    $user->update($validated);
}

2. SQL Injection Prevention

❌ الكود غير الآمن:

php

// استخدام الـ Query Builder بدون prepared statements
$users = DB::select("SELECT * FROM users WHERE name = '$name'");

✅ الحلول الآمنة:

الحل 1: استخدام Query Builder

php

$users = DB::table('users')
    ->where('name', $name)
    ->get();

الحل 2: استخدام Eloquent

php

$users = User::where('name', $name)->get();

الحل 3: استخدام prepared statements يدوياً

php

$users = DB::select('SELECT * FROM users WHERE name = ?', [$name]);

📊 جدول مقارنة: حلول الأخطاء حسب نوع المشكلة

المشكلةالحل السريعالحل المتقدمالأدوات المطلوبة
الأذوناتchmod -R 775 storageACL + تعيين المالك الصحيحTerminal
الكاشphp artisan config:clearphp artisan optimizeArtisan
قاعدة البياناتالتحقق من .envاستخدام DB::reconnect()MySQL/PostgreSQL
الذاكرةزيادة memory_limitاستخدام Chunking أو Queuephp.ini
الوقتزيادة max_execution_timeاستخدام Queuephp.ini
التوجيهphp artisan route:clearاستخدام Route CachingArtisan

🎯 خطة تشخيص متكاملة لأي خطأ في Laravel

الخطوة 1: تفعيل التصحيح

bash

# في ملف .env
APP_DEBUG=true
APP_ENV=local

# في config/app.php
'debug' => env('APP_DEBUG', true),

الخطوة 2: قراءة سجل الأخطاء

bash

# عرض آخر 50 سطراً
tail -n 50 storage/logs/laravel.log

# متابعة السجل مباشرة
tail -f storage/logs/laravel.log

الخطوة 3: تنظيف الكاش

bash

php artisan config:clear
php artisan cache:clear
php artisan view:clear
php artisan route:clear

الخطوة 4: إعادة تحميل الـ Autoloader

bash

composer dump-autoload

الخطوة 5: التحقق من قاعدة البيانات

bash

# اختبار الاتصال
php artisan db:show

# تشغيل الميجريشن
php artisan migrate --pretend # لمعرفة ما سيحدث
php artisan migrate # للتشغيل الفعلي

الخطوة 6: تشغيل السيرفر المحلي

bash

php artisan serve --host=0.0.0.0 --port=8000

💡 نصائح ذهبية لمطوري Laravel

1. استخدم dd() و dump() بحكمة

php

// عرض متغير وإيقاف التنفيذ
dd($variable);

// عرض متغير والاستمرار
dump($variable);

// عرض استعلامات قاعدة البيانات
DB::enableQueryLog();
// ... تنفيذ استعلامات ...
dd(DB::getQueryLog());

2. استخدم الـ Exception Handling المخصص

php

// app/Exceptions/Handler.php
public function render($request, Exception $exception)
{
    if ($exception instanceof ModelNotFoundException) {
        return response()->json([
            'error' => 'Resource not found'
        ], 404);
    }
    
    return parent::render($request, $exception);
}

3. استخدم الـ Global Scopes للتصفية التلقائية

php

class ActiveScope implements GlobalScope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->where('is_active', true);
    }
}

class User extends Model
{
    protected static function booted()
    {
        static::addGlobalScope(new ActiveScope);
    }
}

4. استخدم الـ Observers لمراقبة التغييرات

bash

php artisan make:observer UserObserver --model=User

php

class UserObserver
{
    public function created(User $user)
    {
        Log::info('User created: ' . $user->email);
    }
    
    public function updated(User $user)
    {
        Log::info('User updated: ' . $user->email);
    }
}

5. استخدم الـ API Resources لتنسيق الـ Responses

bash

php artisan make:resource UserResource

php

class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at->toDateTimeString(),
        ];
    }
}

📦 حلول لأخطاء الـ Packages

مشكلة: Class 'Package\Class' not found

✅ الحلول:

bash

# 1. تثبيت الـ package
composer require vendor/package-name

# 2. إعادة تحميل الـ autoloader
composer dump-autoload

# 3. نشر التهيئة (إذا لزم الأمر)
php artisan vendor:publish --provider="Vendor\Package\PackageServiceProvider"

# 4. تشغيل الميجريشن (إذا لزم الأمر)
php artisan migrate

مشكلة: Package version conflict

✅ الحلول:

bash

# 1. معرفة الإصدارات المتاحة
composer show vendor/package-name --all

# 2. تثبيت إصدار محدد
composer require vendor/package-name:^1.0

# 3. تحديث جميع الـ packages
composer update

# 4. حل التعارضات يدوياً في composer.json
{
    "require": {
        "vendor/package1": "^1.0",
        "vendor/package2": "^2.0"
    }
}

🚀 أدوات مفيدة خارجية

1. Laravel Shift (لتحديث الإصدارات)

bash

# تحديث من Laravel 8 إلى 9 مثلاً
# استخدم موقع shift.laravel.com

2. Laravel Dump Server (لعرض الـ Dumps)

bash

composer require --dev symfony/var-dumper

# تشغيل السيرفر
php artisan dump-server

# الآن يمكنك استخدام dd() و dump() وستظهر هنا

3. Laravel IDE Helper (للـ Auto-completion)

bash

composer require --dev barryvdh/laravel-ide-helper

php artisan ide-helper:generate
php artisan ide-helper:models

📝 قائمة التحقق النهائية عند مواجهة أي خطأ

  • □ هل APP_DEBUG مضبوط على true؟
  • □ هل اطلعت على ملف storage/logs/laravel.log؟
  • □ هل البيانات في ملف .env صحيحة؟
  • □ هل صلاحيات المجلدات صحيحة (storage و bootstrap/cache
  • □ هل قمت بتنظيف الكاش؟
  • □ هل composer dump-autoload يعمل بشكل صحيح؟
  • □ هل قاعدة البيانات تعمل وتستطيع الاتصال بها؟
  • □ هل المتغيرات المطلوبة موجودة؟
  • □ هل نسيت return في الـ Controllers؟
  • □ هل الـ Routes معرفة بشكل صحيح؟
  • □ هل الـ Models تستخدم الـ Namespace الصحيح؟

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

تذكر دائماً في Laravel:

  1. الـ Logs هي صديقك الأول – اقرأها دائماً أولاً
  2. Artisan هو أداة قوية – استخدم الأوامر بانتظام
  3. الـ Community كبيرة – ابحث عن مشكلتك، غالباً حُلت مسبقاً
  4. التوثيق الرسمي هو المرجع – اقرأه دائماً
  5. اختبر على محلي قبل الرفع إلى الإنتاج

هل لديك خطأ محدد لم تحله بعد؟

أرسل لي:

  • محتوى ملف laravel.log
  • الكود المسبب للخطأ
  • إصدار Laravel و PHP
  • البيئة (Windows/Linux/Mac)

وسأعطيك حلاً مخصصاً 100%! 🚀

This response is AI-generated, for reference only.

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

🚀 الجزء الثالث: أخطاء متقدمة جداً وحلولها

🔥 9. خطأ: PHP Fatal error: Uncaught ReflectionException: Class config does not exist

❌ الكود المسبب:

php

// محاولة الوصول إلى config قبل تحميله
$value = config('app.timezone'); // قبل تهيئة Laravel

✅ الحلول المتقدمة:

الحل 1: استخدام الـ Helper بعد التهيئة

php

// في bootstrap/app.php أو في Service Provider
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

// الآن يمكن استخدام config
$timezone = config('app.timezone');

الحل 2: تحميل التكوين يدوياً

php

// إذا كنت في سكربت خارجي
$config = require __DIR__.'/../config/app.php';
$timezone = $config['timezone'];

الحل 3: استخدام الـ Application Container

php

$app = require __DIR__.'/../bootstrap/app.php';
$timezone = $app['config']->get('app.timezone');

🔥 10. خطأ: PDOException: SQLSTATE[08006] [7] could not connect to server: Connection refused

✅ الحلول المتقدمة:

الحل 1: التحقق من خدمة قاعدة البيانات

bash

# Linux
sudo systemctl status postgresql
sudo systemctl start postgresql

# Mac
brew services list
brew services start postgresql

# Windows
net start postgresql-13

الحل 2: استخدام الـ Connection Retry Logic

php

// في config/database.php
'retry' => [
    'max_attempts' => 5,
    'backoff' => 100, // milliseconds
],

// أو في الكود
$retries = 5;
while ($retries > 0) {
    try {
        $connection = DB::connection();
        break;
    } catch (PDOException $e) {
        $retries--;
        if ($retries === 0) throw $e;
        sleep(1);
    }
}

الحل 3: استخدام الـ Connection Pool

php

// config/database.php
'connections' => [
    'pgsql' => [
        'driver' => 'pgsql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '5432'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'charset' => 'utf8',
        'prefix' => '',
        'schema' => 'public',
        'sslmode' => 'prefer',
        'options' => [
            PDO::ATTR_PERSISTENT => true, // Persistent connection
        ],
    ],
],

🔥 11. خطأ: ErrorException: Trying to get property of non-object

❌ الكود المسبب:

php

// العلاقة غير محملة
$user = User::find(1);
echo $user->profile->bio; // خطأ إذا كان profile == null

✅ الحلول المتقدمة:

الحل 1: استخدام Optional Helper (Laravel 8+)

php

echo optional($user->profile)->bio ?? 'No bio';

الحل 2: استخدام Null Coalescing Operator

php

echo $user->profile?->bio ?? 'No bio'; // PHP 8+

الحل 3: استخدام Eager Loading مع Default

php

$user = User::with(['profile' => function($query) {
    $query->select(['user_id', 'bio']);
}])->find(1);

echo $user->profile->bio ?? 'No bio';

الحل 4: استخدام Accessor

php

class User extends Model
{
    public function getBioAttribute()
    {
        return $this->profile?->bio ?? 'No bio available';
    }
}

// الاستخدام
echo $user->bio;

🔥 12. خطأ: League\Flysystem\UnableToWriteFile: Unable to write file at location: permission denied

✅ الحلول المتقدمة:

الحل 1: استخدام الـ Storage Facade مع Driver مناسب

php

// config/filesystems.php
'disks' => [
    'local' => [
        'driver' => 'local',
        'root' => storage_path('app'),
        'throw' => true, // إلقاء استثناء عند الفشل
        'permissions' => [
            'file' => [
                'public' => 0644,
                'private' => 0600,
            ],
            'dir' => [
                'public' => 0755,
                'private' => 0700,
            ],
        ],
    ],
],

الحل 2: استخدام الـ try-catch مع Retry

php

use League\Flysystem\UnableToWriteFile;

try {
    Storage::disk('local')->put('file.txt', $content);
} catch (UnableToWriteFile $e) {
    // محاولة إنشاء المجلد
    Storage::disk('local')->makeDirectory('folder');
    
    // المحاولة مرة أخرى
    Storage::disk('local')->put('file.txt', $content);
}

الحل 3: استخدام الـ Temporary Disk

php

// كتابة في مجلد مؤقت
$tempFile = tempnam(sys_get_temp_dir(), 'laravel_');
file_put_contents($tempFile, $content);

// نقل الملف لاحقاً
Storage::disk('local')->put('final.txt', file_get_contents($tempFile));
unlink($tempFile);

🔥 13. خطأ: Illuminate\Contracts\Container\BindingResolutionException: Target class [view] does not exist

✅ الحلول:

الحل 1: استخدام الـ Facade

php

use Illuminate\Support\Facades\View;

return View::make('welcome', ['name' => 'Laravel']);

الحل 2: استخدام الـ Helper Function

php

return view('welcome', ['name' => 'Laravel']);

الحل 3: استخدام الـ Service Provider للتسجيل

php

// في AppServiceProvider
public function register()
{
    $this->app->bind('view', function ($app) {
        return new \Illuminate\View\Factory(
            $app['view.engine.resolver'],
            $app['view.finder'],
            $app['events']
        );
    });
}

🔥 14. خطأ: LogicException: Please provide a valid cache path

✅ الحلول:

الحل 1: إنشاء المجلدات المفقودة

bash

# إنشاء مجلدات الـ Cache
mkdir -p storage/framework/cache
mkdir -p storage/framework/sessions
mkdir -p storage/framework/views
mkdir -p storage/framework/testing

الحل 2: تعيين صلاحيات صحيحة

bash

chmod -R 775 storage/framework
chmod -R 775 storage/logs

الحل 3: التحقق من وجود المجلدات في الكود

php

// في AppServiceProvider
public function boot()
{
    $cachePaths = [
        storage_path('framework/cache'),
        storage_path('framework/sessions'),
        storage_path('framework/views'),
    ];
    
    foreach ($cachePaths as $path) {
        if (!is_dir($path)) {
            mkdir($path, 0755, true);
        }
    }
}

🔥 15. خطأ: UnexpectedValueException: The stream or file could not be opened

✅ الحلول المتقدمة:

الحل 1: تعيين مسار مخصص للـ Logs

php

// في config/logging.php
'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['single', 'slack'],
    ],
    
    'single' => [
        'driver' => 'single',
        'path' => storage_path('logs/laravel.log'),
        'level' => env('LOG_LEVEL', 'debug'),
        'permission' => 0644, // تعيين صلاحيات الملف
        'locking' => true, // قفل الملف للكتابة المتزامنة
    ],
],

الحل 2: استخدام Channel مختلف لبيئات مختلفة

php

// .env
LOG_CHANNEL=daily

// config/logging.php
'daily' => [
    'driver' => 'daily',
    'path' => storage_path('logs/laravel.log'),
    'level' => env('LOG_LEVEL', 'debug'),
    'days' => 7, // الاحتفاظ بآخر 7 أيام
    'permission' => 0644,
],

الحل 3: استخدام الـ Syslog (للسيرفرات)

php

'syslog' => [
    'driver' => 'syslog',
    'level' => env('LOG_LEVEL', 'debug'),
],

🛡 أخطاء الأداء وتحسينها

🔥 16. مشكلة: N+1 Query في الـ API

❌ الكود البطيء:

php

// Controller
$posts = Post::all();
foreach ($posts as $post) {
    $post->author->name; // N+1 Query
}

✅ الحلول المتقدمة:

الحل 1: Eager Loading

php

$posts = Post::with('author')->get();
foreach ($posts as $post) {
    echo $post->author->name; // استعلام واحد فقط
}

الحل 2: Lazy Eager Loading

php

$posts = Post::all();
if (request('with_author')) {
    $posts->load('author');
}

الحل 3: استخدام الـ Resource مع Relations

php

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'author' => new UserResource($this->whenLoaded('author')),
        ];
    }
}

// في Controller
return PostResource::collection(Post::with('author')->paginate());

🔥 17. مشكلة: Queries بطيئة جداً

✅ الحلول المتقدمة:

الحل 1: استخدام الـ Indexes

php

// إنشاء ميجريشن
Schema::table('posts', function (Blueprint $table) {
    $table->index('created_at');
    $table->index(['user_id', 'status']);
    $table->fullText('content'); // لـ Full-Text Search
});

// في Model
class Post extends Model
{
    protected $casts = [
        'created_at' => 'datetime',
    ];
}

الحل 2: استخدام الـ Raw Queries للاستعلامات المعقدة

php

$users = DB::select("
    SELECT u.*, COUNT(p.id) as posts_count
    FROM users u
    LEFT JOIN posts p ON u.id = p.user_id
    WHERE u.created_at >= ?
    GROUP BY u.id
    HAVING posts_count > 5
", [now()->subDays(30)]);

الحل 3: استخدام الـ Cache

php

use Illuminate\Support\Facades\Cache;

$users = Cache::remember('active_users', 3600, function () {
    return User::withCount('posts')
        ->having('posts_count', '>', 5)
        ->get();
});

// أو باستخدام Tags
Cache::tags(['users', 'posts'])->remember('active_users', 3600, function () {
    return User::withCount('posts')
        ->having('posts_count', '>', 5)
        ->get();
});

// حذف الكاش عند التحديث
Cache::tags(['users', 'posts'])->flush();

🔥 18. مشكلة: Session Lag أو فقدان البيانات

✅ الحلول المتقدمة:

الحل 1: استخدام Redis للـ Sessions

php

// config/session.php
'driver' => env('SESSION_DRIVER', 'redis'),

// .env
SESSION_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

الحل 2: استخدام الـ Database Sessions

bash

php artisan session:table
php artisan migrate

php

// config/session.php
'driver' => env('SESSION_DRIVER', 'database'),

الحل 3: التحقق من Cookie Configuration

php

// config/session.php
'cookie' => env('SESSION_COOKIE', 'laravel_session'),
'path' => '/',
'domain' => env('SESSION_DOMAIN', null),
'secure' => env('SESSION_SECURE_COOKIE', false),
'http_only' => true,
'same_site' => 'lax', // أو 'strict'

🔐 أخطاء الأمان المتقدمة

🔥 19. CSRF Token Mismatch

✅ الحلول:

الحل 1: إضافة الـ Token في الـ Forms

php

<form method="POST" action="/profile">
    @csrf
    <!-- أو -->
    {{ csrf_field() }}
</form>

الحل 2: إضافة الـ Token في Axios (لـ API)

javascript

axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').content;

// أو
axios.post('/api/data', data, {
    headers: {
        'X-CSRF-TOKEN': '{{ csrf_token() }}'
    }
});

الحل 3: استثناء Routes من CSRF (بحذر)

php

// app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
    'webhook/*',
    'api/webhook',
];

الحل 4: استخدام الـ API Tokens بدلاً من CSRF

php

// Sanctum
$user->createToken('token-name')->plainTextToken;

// في الطلبات
Authorization: Bearer {token}

🔥 20. XSS Protection

✅ الحلول المتقدمة:

الحل 1: استخدام Blade Auto-escaping

php

{{ $user->name }} // تلقائياً محمي

// لتجنب الإسكيب (بحذر شديد)
{!! $user->bio !!} // خطر

الحل 2: استخدام الـ Purifier (HTML Purifier)

bash

composer require mews/purifier

php

// config/purifier.php
return [
    'settings' => [
        'default' => [
            'HTML.Doctype' => 'HTML 4.01 Transitional',
            'HTML.Allowed' => 'p,b,i,u,a[href],img[src]',
            'CSS.AllowedProperties' => [],
            'AutoFormat.RemoveEmpty' => true,
        ],
    ],
];

// الاستخدام
$cleanHtml = Purifier::clean($request->input('content'));

الحل 3: استخدام Content Security Policy (CSP)

php

// في Middleware
public function handle($request, Closure $next)
{
    $response = $next($request);
    
    $response->header('Content-Security-Policy', "
        default-src 'self';
        script-src 'self' 'unsafe-inline' 'unsafe-eval';
        style-src 'self' 'unsafe-inline';
        img-src 'self' data: https:;
        font-src 'self';
        connect-src 'self' https://api.example.com;
    ");
    
    return $response;
}

🧪 أخطاء الاختبارات (Testing)

🔥 21. خطأ: PHPUnit\Framework\Exception: Class 'Tests\TestCase' not found

✅ الحلول:

الحل 1: التحقق من الـ Namespace

php

// tests/Feature/UserTest.php
namespace Tests\Feature; // صحيح

use Tests\TestCase; // يجب أن يكون موجوداً

الحل 2: تشغيل الـ Autoloader

bash

composer dump-autoload

الحل 3: التحقق من إعدادات phpunit.xml

xml

<!-- phpunit.xml -->
<phpunit>
    <testsuites>
        <testsuite name="Unit">
            <directory>tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory>tests/Feature</directory>
        </testsuite>
    </testsuites>
</phpunit>

الحل 4: إنشاء ملف TestCase

bash

php artisan make:test TestCase

🔥 22. خطأ: Failed asserting that false is true في الاختبارات

✅ الحلول المتقدمة:

الحل 1: Debugging الاختبارات

php

public function testUserCreation()
{
    $user = User::factory()->create([
        'email' => 'test@example.com',
    ]);
    
    $this->assertDatabaseHas('users', [
        'email' => 'test@example.com',
    ]);
    
    // لرؤية ما يحدث
    dump($user->toArray());
    // أو
    Log::info('User created', $user->toArray());
}

الحل 2: استخدام الـ Exception Handling في الاختبارات

php

public function testUserDeletion()
{
    $user = User::factory()->create();
    
    $response = $this->actingAs($user)
        ->delete("/users/{$user->id}");
    
    $response->assertStatus(302);
    
    // التحقق من أن المستخدم حُذف
    $this->assertDatabaseMissing('users', ['id' => $user->id]);
}

الحل 3: استخدام الـ Database Transactions

php

use Illuminate\Foundation\Testing\RefreshDatabase;

class UserTest extends TestCase
{
    use RefreshDatabase;
    
    public function test_user_can_be_created()
    {
        // Database سيتم إعادة تعيينها قبل كل اختبار
    }
}

📦 أخطاء الـ Packages الشهيرة

🔥 23. مشكلة: Laravel Sanctum Authentication Issues

✅ الحلول:

الحل 1: نشر التهيئة بشكل صحيح

bash

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate

الحل 2: إضافة Sanctum Middleware

php

// app/Http/Kernel.php
'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

الحل 3: إعداد Cors بشكل صحيح

php

// config/cors.php
return [
    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['http://localhost:3000'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true, // مهم!
];

🔥 24. مشكلة: Laravel Socialite

✅ الحلول:

الحل 1: نشر التهيئة

bash

composer require laravel/socialite
php artisan vendor:publish --provider="Laravel\Socialite\SocialiteServiceProvider"

الحل 2: إعداد الـ Services

php

// config/services.php
'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => env('GOOGLE_REDIRECT_URI'),
],

'facebook' => [
    'client_id' => env('FACEBOOK_CLIENT_ID'),
    'client_secret' => env('FACEBOOK_CLIENT_SECRET'),
    'redirect' => env('FACEBOOK_REDIRECT_URI'),
],

الحل 3: معالجة الأخطاء

php

try {
    $user = Socialite::driver('google')->user();
} catch (\Exception $e) {
    Log::error('Socialite error: ' . $e->getMessage());
    return redirect('/login')->withErrors(['email' => 'Authentication failed']);
}

🔧 أدوات متقدمة للـ Debugging

1. Laravel Horizon (للـ Queues)

bash

composer require laravel/horizon
php artisan horizon:install
php artisan migrate
php artisan horizon

2. Laravel Nova Debug Bar

bash

composer require beyondcode/laravel-query-detector --dev

3. Clockwork (بديل Debugbar)

bash

composer require itsgoingd/clockwork
php artisan vendor:publish --provider="Clockwork\Support\Laravel\ClockworkServiceProvider"

📊 جدول الأدوات حسب المشكلة

المشكلةالأداة المناسبةكيف تساعد
استعلامات بطيئةDebugbar / Telescopeتعرض وقت الاستعلام وعددها
أخطاء غير معروفةRay / dd()تكشف قيمة المتغيرات
مشاكل الأداءBlackfire / Xdebugتحليل الأداء خطوة بخطوة
أخطاء APIPostman / Insomniaاختبار الـ Endpoints
مشاكل QueueHorizonمراقبة الـ Jobs
أخطاء DatabaseLaravel Tinkerاختبار الاستعلامات مباشرة

📝 خطة طوارئ للحالات الحرجة

عندما ينفد كل شيء:

bash

# 1. نسخ احتياطي للمشروع
cp -r project project_backup_$(date +%Y%m%d)

# 2. حذف كل الكاش
php artisan optimize:clear
rm -rf bootstrap/cache/*
rm -rf storage/framework/cache/*

# 3. إعادة تثبيت التبعيات
rm -rf vendor
composer install

# 4. إعادة تعيين قاعدة البيانات (فقط للتطوير)
php artisan migrate:fresh --seed

# 5. إعادة تشغيل السيرفر
php artisan serve

🎯 خلاصة نهائية متقدمة

القواعد الذهبية للمطور المحترف:

  1. اقرأ Stack Trace كاملاً – الحل موجود في أول سطرين
  2. استخدم Logs بحكمة – لا تكتب Logs عشوائياً
  3. استخدم Exceptions – لا تخف من إلقائها
  4. اختبر كل شيء – حتى الـ Code الذي لا تتوقع أن يفشل
  5. تعلم من الأخطاء – سجل كل خطأ وكيف حليته
  6. اطلب المساعدة – Laravel community كبيرة جداً

مثال على حل متكامل لخطأ معقد:

php

// معالج شامل للأخطاء
public function handleComplexOperation($data)
{
    DB::beginTransaction();
    
    try {
        // التحقق من المدخلات
        if (empty($data)) {
            throw new InvalidArgumentException('Data cannot be empty');
        }
        
        // المعالجة
        $result = $this->processData($data);
        
        // التحقق من النتيجة
        if (!$result) {
            throw new RuntimeException('Processing failed');
        }
        
        DB::commit();
        
        // تسجيل نجاح العملية
        Log::info('Operation successful', ['data' => $data]);
        
        return $result;
        
    } catch (InvalidArgumentException $e) {
        DB::rollBack();
        Log::warning('Invalid input', ['error' => $e->getMessage()]);
        throw $e;
        
    } catch (RuntimeException $e) {
        DB::rollBack();
        Log::error('Processing failed', ['error' => $e->getMessage()]);
        
        // محاولة التعافي
        $fallback = $this->getFallbackData();
        return $fallback;
        
    } catch (\Exception $e) {
        DB::rollBack();
        Log::critical('Unexpected error', [
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString()
        ]);
        
        // إشعار المطور
        $this->notifyDeveloper($e);
        
        throw $e;
    }
}

هل لديك مشكلة محددة لم تحلها بعد؟

أرسل لي:

  • الكود كاملاً
  • رسالة الخطأ كاملة
  • محتوى laravel.log
  • إصدارات PHP و Laravel
  • البيئة (نظام التشغيل)

وسأعطيك حلاً مخصصاً ودقيقاً 100%! 🚀

Scroll to Top