Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

Try, Catch, Finally

جزء من قسم Object Oriented Programming في رحلة PHP على Coddy — الدرس 68 من 91.

الآن بعد أن عرفت كيفية إنشاء الاستثناءات وإلقائها، ستحتاج إلى تعلم كيفية التقاطها. يتيح لك هيكل try-catch-finally التعامل مع الاستثناءات بسلاسة بدلاً من السماح لها بالتسبب في تعطل تطبيقك.

قم بلف الكود الذي قد يطرح استثناءً في كتلة try، ثم قم بمعالجة الاستثناء في كتلة catch:

<?php
class Calculator {
    public function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("Cannot divide by zero");
        }
        return $a / $b;
    }
}

$calc = new Calculator();

try {
    echo $calc->divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage();
}

الناتج:

Error: Cannot divide by zero

يمكنك التقاط أنواع مختلفة من الاستثناءات باستخدام كتل catch متعددة. يقوم PHP بالتحقق منها بالترتيب، لذا ضع الاستثناءات الأكثر تحديداً أولاً:

<?php
try {
    // كود محفوف بالمخاطر
} catch (InvalidArgumentException $e) {
    echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
    echo "Something went wrong: " . $e->getMessage();
}

يتم تشغيل كتلة finally بغض النظر عما إذا كان قد تم طرح استثناء أو التقاطه. إنها مثالية لمهام التنظيف مثل إغلاق الاتصالات:

<?php
try {
    echo "Attempting operation\n";
    throw new Exception("Failed");
} catch (Exception $e) {
    echo "Caught: " . $e->getMessage() . "\n";
} finally {
    echo "Cleanup complete";
}

المخرجات:

Attempting operation
Caught: Failed
Cleanup complete

يتم تنفيذ كتلة finally حتى لو قمت بعمل return من داخل كتل try أو catch، مما يجعلها موثوقة لعمليات التنظيف الأساسية.

challenge icon

التحدي

سهل

لنقم ببناء نظام معالجة ملفات يوضح كيفية عمل try-catch-finally معاً للتعامل مع الأخطاء بسلاسة مع ضمان حدوث عملية التنظيف دائماً.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • FileException.php — أنشئ فئة FileException مخصصة ترث من Exception. سيمثل هذا الأخطاء المتعلقة بالملفات في نظامك.
  • FileProcessor.php — أنشئ فئة FileProcessor تحاكي عمليات الملفات. قم بتضمين ملف FileException. يجب أن تحتوي الفئة الخاصة بك على:
    • خاصية منطقية (boolean) خاصة باسم $isOpen مهيأة بـ false
    • دالة open(string $filename): void تقوم بضبط $isOpen على true وتطبع "Opening: [filename]". إذا كان اسم الملف هو "invalid.txt"، قم برمي FileException مع الرسالة "Cannot open file"
    • دالة process(): void تطبع "Processing file...". إذا كانت $isOpen هي false، قم برمي RuntimeException مع الرسالة "File not open"
    • دالة close(): void تقوم بضبط $isOpen على false وتطبع "File closed"
    • دالة isOpen(): bool تعيد الحالة الحالية
  • main.php — قم بتضمين ملف FileProcessor. ستتلقى مدخلاً واحداً: اسم الملف.

    أنشئ كائناً من FileProcessor واستخدم هيكل try-catch-finally للقيام بما يلي:

    • في كتلة try: استدعِ open() مع اسم الملف، ثم استدعِ process()
    • التقط FileException أولاً واطبع "File error: [message]"
    • التقط RuntimeException واطبع "Runtime error: [message]"
    • في كتلة finally: تحقق مما إذا كان الملف مفتوحاً باستخدام isOpen()، وإذا كان الأمر كذلك، استدعِ close(). ثم اطبع "Cleanup complete"

تضمن كتلة finally حدوث عملية التنظيف سواء نجحت العمليات أو فشلت. هذا النمط ضروري لإدارة الموارد مثل الملفات، أو اتصالات قاعدة البيانات، أو مقابس الشبكة (network sockets) حيث يجب أن يحدث التنظيف بغض النظر عما يحدث أثناء المعالجة.

ورقة مرجعية

استخدم try-catch-finally للتعامل مع الاستثناءات بسلاسة وضمان تشغيل كود التنظيف دائمًا:

<?php
try {
    // كود قد يطرح استثناءً
} catch (ExceptionType $e) {
    // التعامل مع الاستثناء
    echo $e->getMessage();
}

قم بالتقاط أنواع متعددة من الاستثناءات باستخدام كتل catch منفصلة. ضع الاستثناءات الأكثر تحديدًا أولاً:

<?php
try {
    // كود خطر
} catch (InvalidArgumentException $e) {
    echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
    echo "Something went wrong: " . $e->getMessage();
}

يتم تنفيذ كتلة finally بغض النظر عما إذا كان قد تم طرح استثناء أو التقاطه، مما يجعلها مثالية لعمليات التنظيف:

<?php
try {
    // محاولة إجراء العملية
} catch (Exception $e) {
    // التعامل مع الخطأ
} finally {
    // كود التنظيف يعمل دائمًا
}

جرّب بنفسك

<?php
require_once 'FileProcessor.php';

// قراءة المدخلات
$filename = trim(fgets(STDIN));

// TODO: إنشاء مثيل من FileProcessor

// TODO: استخدم هيكل try-catch-finally:
// - في كتلة try: استدعِ open() مع اسم الملف، ثم استدعِ process()
// - التقط FileException أولاً واطبع "File error: [message]"
// - التقط RuntimeException واطبع "Runtime error: [message]"
// - في كتلة finally: تحقق مما إذا كان الملف مفتوحاً باستخدام isOpen()، وإذا كان كذلك استدعِ close()
//   ثم اطبع "Cleanup complete"

?>
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming