PHP: "أو" بيان بناء على تعليمات تفشل: كيفية رمي استثناء الجديد؟

StackOverflow https://stackoverflow.com/questions/1211237

سؤال

والجميع هنا يجب أن يعرف statemens "أو"، عادة لصقها على أمر يموت ():

$foo = bar() or die('Error: bar function return false.');

وهذا أكثر من مرة نرى شيئا مثل:

mysql_query('SELECT ...') or die('Error in during the query');

ولكن، أنا غير قادر على فهم بالضبط كيف أن يعمل "أو" بيان.

وأود أن رمي استثناء جديد بدلا من يموت ()، ولكن:

try{
    $foo = bar() or throw new Exception('We have a problem here');

ولا يعمل، وليس

$foo = bar() or function(){ throw new Exception('We have a problem here'); }

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

function ThrowMe($mess, $code){
    throw new Exception($mess, $code);
}
try{
    $foo = bar() or ThrowMe('We have a problem in here', 666);
}catch(Exception $e){
    echo $e->getMessage();
}

ولكن هل هناك طريقة لرمي استثناء جديد مباشرة بعد "أو" البيان؟

وأو هذا النوع من الهيكل هو إلزامي (أنا لا أميل liek وظيفة ThrowMe على الإطلاق):

try{
    $foo = bar();
    if(!$foo){
        throw new Exception('We have a problem in here');
    }
}catch(Exception $e){
    echo $e->getMessage();
}

تعديل : في ما أريد حقا لتجنب استخدام وسيلة إذا () تحقق كل عملية خطيرة محتملة أفعل، على سبيل المثال:

#The echo $e->getMessage(); is just an example, in real life this have no sense!
try{
    $foo = bar();
    if(!$foo){
        throw new Exception('Problems with bar()');
    }
    $aa = bb($foo);
    if(!$aa){
        throw new Exception('Problems with bb()');
    }
    //...and so on!
}catch(Exception $e){
    echo $e->getMessage();
}

#But i relly prefer to use something like:

try{
    $foo = bar() or throw new Exception('Problems with bar()');
    $aa = bb($foo) or throw new Exception('Problems with bb()');
    //...and so on!
}catch(Exception $e){
    echo $e->getMessage();
}

#Actually, the only way i figured out is:

try{
    $foo = bar() or throw new ThrowMe('Problems with bar()', 1);
    $aa = bb($foo) or throw new ThrowMe('Problems with bb()', 2);
    //...and so on!
}catch(Exception $e){
    echo $e->getMessage();
}

#But i'll love to thro the exception directly instead of trick it with ThrowMe function.
هل كانت مفيدة؟

المحلول

وor هو مجرد مشغل منطقي ، وانها مشابهة ل||.

والحيلة المشتركة لل

mysql_query() or die();

ويمكن فقط كذلك أن تكون مكتوبة

mysql_query() || die();

وماذا يحدث هنا هو المشغل "منطقي أو" (أيهما تختار) تحاول تحديد ما إذا كان أي من المعامل يقيم إلى TRUE. وهذا يعني يجب أن يكون المعاملات التعابير التي يمكن أن يلقي باعتباره منطقية.

وهكذا، والسبب

bar() or throw new Exception();

وغير قانوني، لأن

(boolean)throw new Exception();

وهو أيضا غير قانوني. في جوهرها، عملية رمي استثناء لا تولد قيمة مقابل المشغل للتحقق.

ولكن استدعاء دالة <م> لا توليد قيمة مقابل المشغل للتحقق (أي قيمة الإرجاع صريحة سيؤدي كثافة وظيفة عودته NULL الأمر الذي يلقي بظلال كما FALSE) الذي هو السبب في أنه يعمل للكم عند التفاف رمي استثناء في وظيفة.

وعلى أمل أن يساعد.

نصائح أخرى

لماذا لا bar() وbb() رمي الاستثناءات؟ في PHP الاستثناءات فقاعة، لذلك ليس هناك حاجة لرمي استثناء في وظيفة / طريقة حيث استدعاء bar() / bb(). قد يكون طرح هذه الاستثناءات التي كتبها bar() / bb(). في حال كنت ترغب في رمي استثناء آخر، يمكنك أن تفعل ببساطة:

function foo() {
    try {
        $bar = bar();
    } catch (BarException) {
        throw new FooException;
    }
}

وهناك حل وجدت يمكن ان تحل محل "أو يموت ()" في كل مكان هو التفاف رمي مع وظيفة مجهولة المصدر الذي يحصل دعا على الفور من قبل call_user_func:

call_user_func(function(){
    throw new Exception("ERROR");
});

ويمكنك أن ترى أنه يعمل من خلال تنفيذ هذا السيناريو على دمية:

false or call_user_func(function(){throw new Exception("ERROR");});

وأعتقد أنك تريد استخدام شيء من هذا القبيل هيكل الماضي، على الرغم من أن هناك حقا أي نقطة في استخدام الاستثناءات لذلك:

$foo = bar();
if(!$foo){
    echo 'We have a problem in here';
}

ولكل تعليق - أنا لا أعتقد أنك تستطيع أن تفعل ذلك في سطر واحد (أي دون الاختيار if(!$foo))، وأوافق على أن طريقة استثناء رمي أمر فظيع جدا. شخصيا، لكنني أفضل الوضوح من:

$foo = bar();
if(!$foo){
    throw new Exception('We have a problem in here');
}

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

وأعتقد أن هذا القيد على الأرجح إلى الأشياء دينامية الكتابة PHP، فإنه يمكن تحويل نتائج استدعاء دالة إلى الشرطي، ولكن لا نتائج throw.

وهنا حل سطر واحد من دون وظيفة إضافية:

if (!($foo = bar())) throw new Exception('We have a problem here');

ولقد تعرف ببساطة toss وظيفة لهذا الغرض.

function toss(Exception $exception): void
{
    throw $exception;
}

ولأن الملف / خط / كومة من المعلومات يتم التقاطها عندما الاستثناء <م> شيدت (new) لا القيت (throw) هذا لا يتعارض مع مكدس الاستدعاءات.

وهكذا يمكنك أن تفعل ذلك.

something() or toss(new Exception('something failed'));

ويمكنك أيضا إنشاء فئة استثناء مخصصة واستخدام انها طريقة منشئ ثابت بدلا من البناء throw new Exception().

والطبقة الاستثناء:

class CustomException extends Exception {
  static public function doThrow($message = "", $code = 0, Exception $previous = null) {
    throw new Exception($message, $code, $previous);
  }
}

والاستعمال:

try {

  $foo = bar() or CustomException::doThrow('Problems with bar()');
  $aa = bb($foo) or CustomException::doThrow('Problems with bb()');

} catch(Exception $e){
  echo $e->getMessage();
}
<اقتباس فقرة>   

<قوية> ملاحظة

     

إذا كنت تستخدم PHP 7 وأعلى - يمكنك إعادة تسمية طريقة ثابتة doThrow() إلى throw() ببساطة، لأن في PHP 7 والعالي يسمح لاستخدام كلمات محجوزة كأسماء طريقة

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top