การจัดการข้อผิดพลาด PHP: die () Vs trigger_error () Vs throw Exception


119

เกี่ยวกับการจัดการข้อผิดพลาดใน PHP - เท่าที่ฉันรู้มี 3 สไตล์:

  1. die()หรือexit()สไตล์:

    $con = mysql_connect("localhost","root","password");
    
    if (!$con) {
     die('Could not connect: ' . mysql_error());
    }
  2. throw Exception รูปแบบ:

     if (!function_exists('curl_init')) {
    
          throw new Exception('need the CURL PHP extension. 
                               Recomplie PHP with curl');
        }
  3. trigger_error() รูปแบบ:

    if(!is_array($config) && isset($config)) {
            trigger_error('Error: config is not an array or is not set', E_USER_ERROR);
        }

ตอนนี้ในคู่มือ PHP ใช้ทั้งสามวิธี

  • สิ่งที่ฉันอยากรู้คือฉันควรชอบสไตล์ไหนและทำไม?

  • ทั้ง 3 ตัวนี้มีการเปลี่ยนทดแทนกันหรือไม่และสามารถใช้แทนกันได้หรือไม่?

OT เล็กน้อย: เป็นเพียงฉันหรือทุกคนคิดว่าตัวเลือกการจัดการข้อผิดพลาดของ PHP มีมากเกินไปจนทำให้นักพัฒนา php สับสน?


4
สิ่งเหล่านี้ไม่ใช่ "สไตล์" เป็นคุณสมบัติทางภาษาที่แตกต่างกัน เพื่อวัตถุประสงค์ที่แตกต่างกัน
มาริโอ

11
@mario: จุดประสงค์ที่เยื้องต่างกันคืออะไร? โปรด
ชี้แนะ

คุณตั้งคำถามได้อย่างยอดเยี่ยม ขอบคุณที่ถาม
นักบัญชีم

คำตอบ:


86

ไม่ควรใช้รหัสแรกในรหัสการผลิตเนื่องจากเป็นการขนส่งข้อมูลที่ไม่เกี่ยวข้องกับผู้ใช้ปลายทาง (ผู้ใช้ไม่สามารถทำอะไรเกี่ยวกับ"ไม่สามารถเชื่อมต่อกับฐานข้อมูล" )

คุณจะโยนข้อยกเว้นหากคุณรู้ว่า ณ จุดรหัสวิกฤตบางอย่างแอปพลิเคชันของคุณอาจล้มเหลวและคุณต้องการให้รหัสของคุณกู้คืนในระดับการโทรหลายระดับ

trigger_error()ช่วยให้คุณสามารถรายงานข้อผิดพลาดแบบละเอียด (โดยใช้ข้อความแสดงข้อผิดพลาดในระดับต่างๆ) และคุณสามารถซ่อนข้อผิดพลาดเหล่านั้นจากผู้ใช้ปลายทาง (โดยใช้set_error_handler()) แต่ยังคงแสดงให้คุณเห็นในระหว่างการทดสอบ

นอกจากนี้ยังtrigger_error()สามารถสร้างข้อความที่ไม่ร้ายแรงที่สำคัญในระหว่างการพัฒนาซึ่งสามารถระงับในรหัสการผลิตโดยใช้ตัวจัดการข้อผิดพลาดที่กำหนดเอง คุณสามารถสร้างข้อผิดพลาดร้ายแรงได้เช่นกัน ( E_USER_ERROR) แต่ไม่สามารถกู้คืนได้ หากคุณทริกเกอร์อย่างใดอย่างหนึ่งการทำงานของโปรแกรมจะหยุดที่จุดนั้น ด้วยเหตุนี้สำหรับข้อผิดพลาดร้ายแรงควรใช้ข้อยกเว้น ด้วยวิธีนี้คุณจะสามารถควบคุมโฟลว์โปรแกรมของคุณได้มากขึ้น:

// Example (pseudo-code for db queries):

$db->query('START TRANSACTION');

try {
    while ($row = gather_data()) {
       $db->query('INSERT INTO `table` (`foo`,`bar`) VALUES(?,?)', ...);
    }
    $db->query('COMMIT');
} catch(Exception $e) {
    $db->query('ROLLBACK');
}

ที่นี่หากมีโอกาสgather_data()เพียงแค่ครอปธรรมดา (โดยใช้E_USER_ERRORหรือdie()) INSERTข้อความก่อนหน้านี้จะทำให้มันเข้าสู่ฐานข้อมูลของคุณแม้ว่าจะไม่ต้องการและคุณจะไม่สามารถควบคุมสิ่งที่จะเกิดขึ้นต่อไปได้


2
จึงออกจากtrigger_error()และการขว้างปาข้อยกเว้น: ที่หนึ่งที่ฉันควรใช้และเมื่อ?
CuriousMind

@Gaurish ดูตัวอย่างเพิ่มเติมที่
Linus Kleen

2
หลังจากอ่านตัวอย่างของคุณฉันคิดว่าตอนนี้ฉันเข้าใจจุดประสงค์ของข้อยกเว้นการโยนได้ดีขึ้น ขอบคุณ :)
CuriousMind

1
@Pacerier นั้นขึ้นอยู่กับการกำหนดค่าของเซิร์ฟเวอร์จริงๆ ระบบอาจจะกำหนดให้AutocommitROLLBACKต่อค่าเริ่มต้นด้วยเหตุนี้อย่างชัดเจน ตัวอย่างรหัสหลอกนี้ครอบคลุมทั้งสองกรณี: เซิร์ฟเวอร์ที่ไม่ได้กำหนดค่าให้ทำงานอัตโนมัติ ( COMMITจำเป็นต้องมีคำสั่ง) และสิ่งที่ต้องทำ
Linus Kleen

1
@LinusKleen ไม่ปิด autocommit เมื่อเราเรียกใช้สายquery('START TRANSACTION');?
Pacerier

10

ฉันมักจะใช้วิธีแรกสำหรับการดีบักอย่างง่ายในโค้ดการพัฒนา ไม่แนะนำให้ผลิต วิธีที่ดีที่สุดคือโยนข้อยกเว้นซึ่งคุณสามารถจับได้ในส่วนอื่น ๆ ของโปรแกรมและจัดการข้อผิดพลาดบางอย่าง

ทั้งสามรูปแบบไม่ใช่การแทนที่กันในแบบดรอปอิน ข้อแรกไม่ใช่ข้อผิดพลาด แต่เป็นเพียงวิธีหยุดสคริปต์และแสดงข้อมูลการดีบักบางอย่างเพื่อให้คุณแยกวิเคราะห์ด้วยตนเอง ข้อที่สองไม่ใช่ข้อผิดพลาดตามข้อผิดพลาด แต่จะถูกแปลงเป็นข้อผิดพลาดหากคุณจับไม่ได้ ข้อสุดท้ายกำลังทำให้เกิดข้อผิดพลาดจริงในเอ็นจิ้น PHP ซึ่งจะได้รับการจัดการตามการกำหนดค่าสภาพแวดล้อม PHP ของคุณ (ในบางกรณีจะแสดงให้ผู้ใช้เห็นในกรณีอื่น ๆ เพียงแค่ล็อกไฟล์หรือไม่ได้บันทึกเลย)


1
จะเกิดอะไรขึ้นเมื่อมีการโยนข้อยกเว้น แต่ไม่ถูกจับ? มันจะทำให้เกิดข้อผิดพลาดร้ายแรงฉันเดา และด้วยtrigger_error()สิ่งเดียวกันก็เกิดขึ้น แล้วความแตกต่างคืออะไร?
CuriousMind

4
ความแตกต่างคือคุณสามารถจับข้อยกเว้นและจัดการได้ทุกวิธีที่คุณต้องการ
Emil Vikström
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.