บล็อก Try / Catch ใน PHP ไม่พบ Exception


100

ฉันพยายามเรียกใช้ตัวอย่าง # 1 นี้จากหน้านี้: http://php.net/manual/en/language.exceptions.php

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}
try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
// Continue execution
echo "Hello World\n";
?>

อย่างไรก็ตามแทนที่จะได้ผลลัพธ์ที่ต้องการฉันได้รับ:

0.2
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.' 
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7

สภาพแวดล้อมของนักพัฒนาที่ฉันใช้อยู่UniServer 3.5ด้วยPHP 5.2.3


1
คุณช่วยแสดงรหัสของคุณให้เราดูได้ไหม ข้อผิดพลาดเดียวที่คุณสามารถทำได้เพื่อรับข้อผิดพลาดนี้คือการตรวจจับข้อยกเว้นที่ไม่ถูกต้อง (หรือไม่มีเลย)
Tammo

2
รหัสเหมือนกันทุกประการ (ฉันเพิ่งเพิ่มบรรทัดใหม่) ... อย่างไรก็ตามฉันคัดลอกโค้ดอีกครั้งลงในไฟล์ทดสอบและนี่คือข้อความแสดงข้อผิดพลาดเดียวกัน: 0.2 ข้อผิดพลาดร้ายแรง: ข้อยกเว้นที่ไม่ถูกจับ 'ข้อยกเว้น' พร้อมข้อความ 'หารด้วยศูนย์ . ' ใน W: \ www \ test.php: 4 Stack trace: # 0 W: \ www \ test.php (11): ผกผัน (0) # 1 {main} โยนใน W: \ www \ test.php ในบรรทัดที่ 4 ฉันไม่รู้จริงๆว่าเกิดอะไรขึ้นที่นั่น ... อาจจะผิดพลาดในการกำหนดค่า PHP?
Krassi

1
ส่วนขยายรุ่นเก่าบางรุ่นทำให้เกิดปัญหาในการจัดการข้อยกเว้น 5.2.3 เป็นรุ่นเก่าและข้อบกพร่องอาจอยู่เบื้องหลังข้อผิดพลาด คุณสามารถอัพเกรด PHP ได้หรือไม่? UniServer 3.5 นั้นค่อนข้างเก่าเช่นกันเนื่องจากเวอร์ชันการผลิตปัจจุบันคือ 5.5 3.5 เป็นการพิมพ์ผิดหรือเปล่า?
outis

1
เมื่อดูข้อมูลการเปิดตัว UniServer ( wiki.uniformserver.com/index.php/… ) เห็นได้ชัดว่า 3.5 ไม่ใช่การพิมพ์ผิด อัปเกรดเป็น UniServer 5.5 แล้วลองใช้โค้ดตัวอย่างอีกครั้ง
outis

1
ขอบคุณสำหรับเคล็ดลับ :) นี่คือสิ่งที่ฉันทำในตอนนั้น - เปลี่ยนเป็น XAMPP (ไม่เหมือนกับ UniServer เวอร์ชันใหม่) 3.5 ไม่ใช่การพิมพ์ผิด แต่เซิร์ฟเวอร์ทำงานได้อย่างสมบูรณ์แบบสำหรับฉันดังนั้นฉันจึงไม่ต้องกังวลกับการอัปเกรด
Krassi

คำตอบ:


222

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

ผมมีข้อยกเว้นของฉันใน namespace ของฉันเรียกว่าและสคริปต์ที่อยู่ใน namespace ที่เรียกว่าB ปัญหาคือฉันมีA \ MyExceptionซึ่งเท่ากับ (ใน PHP) \ B \ A \ MyException (เนื่องจากสคริปต์ของฉันอยู่ในเนมสเปซที่เรียกว่าB !) สิ่งที่ฉันต้องทำเพื่อแก้ไขคือเพิ่มแบ็กสแลช (หรืออะไรก็ตามที่เรียกว่า) ในชื่อข้อยกเว้นดังนั้นมันจะมีลักษณะดังนี้: \ A \ MyException


7
ขอบคุณมากสำหรับการโพสต์สิ่งนี้เพราะฉันจะหายไปหลายวันโดยไม่ได้ตระหนักถึงความผิดพลาดของฉัน
tipu

82
นี้แก้ปัญหาของฉันที่เรียบง่ายจับบล็อกขี้เกียจในรหัส namespaced catch (\Exception $e)ควรจะเป็น การไม่มีแบ็กสแลชExceptionจะเฉพาะเจาะจงสำหรับเนมสเปซและจะไม่ถูกจับคู่ (หรือถูกจับได้)
joemaller

3
ขอบคุณสำหรับการโพสต์สิ่งนี้!
keepkimi

2
ขอบคุณสำหรับการโพสต์สิ่งนี้ฉันเพิ่งใช้เวลาสองสามชั่วโมงที่ผ่านมาบ้าไปแล้วว่าทำไมบล็อกการจับของฉันไม่ทำงาน หน้าหลัก
Mitch

4
ไชโย! บันทึกวันของฉัน (และเซลล์ประสาท ... ) :)
ผัก

68

คำถามค่อนข้างเก่า แต่ ...

ฉันมีปัญหานี้เช่นกัน (และนั่นคือวิธีที่ฉันพบโพสต์นี้) แต่การทดลองง่ายๆทำให้ฉันพบวิธีแก้ปัญหา เพียงแค่ลองเปลี่ยนไปException \Exceptionทำงานให้ฉัน!

แก้ไข:

ตามที่ sivann ชี้ไว้ในความคิดเห็นการใช้เนมสเปซควรทำสิ่งเดียวกัน ดังนั้นเพียงใส่use \Exception as Exception;ก่อนการประกาศชั้นเรียนของคุณ


ยอดเยี่ยม! :) อาจจะใช้เวลาหลายชั่วโมงในการคิดออก แต่ไม่ได้คิดเกี่ยวกับการกำหนดเนมสเปซ ขอบคุณ!
Alexander Gilmanov

ใช่ ด้วย: "use \ Exception as Exception;" ที่ด้านบนทำสิ่งเดียวกัน
sivann

@ sii-anik ลองใช้เนมสเปซเหมือนกับที่ sivann เขียน
Enethion

เพียงแค่use Exception;ควรจะทำมัน
ดิเอโก Ponciano

33

พยายามใส่catch(\Exception $e)แทนcatch(Exception $e). หากคุณใช้รหัสที่คุณไม่รู้จักเป็นอย่างดีหรือโดยเฉพาะอย่างยิ่งหากคุณใช้กรอบงานมันอาจแทนที่ข้อยกเว้น PHP เริ่มต้นด้วยหนึ่งในตัวมันเองดังนั้นคุณอาจไปผิดเส้นทางและได้รับ ผลลัพธ์ที่ไม่ต้องการ หากคุณเพิ่งใส่\Exceptionแสดงว่าคุณกำลังจับข้อยกเว้น PHP พื้นฐานได้


@crassi คุณลองทำตามคำแนะนำของฉันหรือไม่?
Vladimir Despotovic

2
ที่ทำเพื่อฉัน
cljk

ฉันทำงานใน CI4 และได้ผลสำหรับฉัน
Adnan Ahmad

20

คุณไม่สามารถใช้บล็อก try {} catch {} แบบทั่วไปใน PHP ได้เหมือนกับที่คุณสามารถทำได้ในภาษาอื่นเช่น C # (Csharp)

หากคุณทำสิ่งนี้:

try{
    //division by zero
    $number = 5/0;
}
catch(Exception $ex){
    echo 'Got it!';
}

คุณจะไม่เห็นข้อความ 'รับทราบ!' ข้อความไม่เคย ทำไม? เป็นเพียงเพราะ PHP ต้องการ Exception เสมอเพื่อให้ "Thrown" คุณต้องตั้งค่าตัวจัดการข้อผิดพลาดของคุณเองและโยนข้อยกเว้นไปด้วย

ดูset_error_handlerฟังก์ชัน : http://php.net/manual/es/function.set-error-handler.php


6
ไม่เหมือนกัน;) คุณต้องโยนข้อยกเว้นด้วยตัวเองและนั่นคือสิ่งที่ฉันพูด (<< เป็นเพียงเพราะ PHP ต้องการ Exception เสมอเพื่อให้เป็น "โยน" >>) @JaredFarrish
Rowinson Gallego

ใช่ แต่มันไม่เหมือนกันได้อย่างไร?
Jared Farrish

ลิงก์นั้นตายแล้ว แต่ฉันพบว่ามีประโยชน์: w3schools.com/php/func_error_set_error_handler.asp
ความเกลียดชัง

ใน PHP เวอร์ชัน 7.3.9 $number = 5/0;ไม่ได้เพิ่มข้อยกเว้น จะกำหนด$number INF
virtualmic

6

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

ลองแก้ไขสคริปต์ต้นฉบับดังต่อไปนี้และวางผลลัพธ์ของคุณ จะช่วยวินิจฉัยปัญหาของคุณได้ดีขึ้นเล็กน้อย

<?php

//set up exception handler to report what we didn't catch
function exception_handler($exception) {

    if($exception instanceof MyException) {
        echo "you didn't catch a myexception instance\n";

    } else if($exception instanceof Exception) {
        echo "you didn't catch a exception instance\n";

    } else {
        echo "uncaught exception of type: ".gettype($exception)."\n";
    }

    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

//install the handler
set_exception_handler('exception_handler');

class MyException extends Exception {
}

function inverse($x) {
    if (!$x) {
        throw new MyException('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (MyException $e) {
    echo 'Caught myexception: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>

4

ฉันมีปัญหาเดียวกันกับการกำหนดค่าต่อไปนี้

PHP 5.2.14 (cli) (สร้าง: 12 สิงหาคม 2553 17:32:30 น.) ลิขสิทธิ์ (c) 1997-2010 PHP Group Zend Engine v2.2.0, ลิขสิทธิ์ (c) 1998-2010 Zend Technologies พร้อม eAccelerator v0.9.5 1 , ลิขสิทธิ์ (c) eAccelerator 2004-2006 โดย eAccelerator

วิธีแก้ปัญหาคือปิดใช้งาน eAccelerator หรืออัปเดต ฉันลองทั้งสองอย่างและการแก้ไขทั้งสองได้ผล รายงานข้อผิดพลาดที่นี่https://eaccelerator.net/ticket/242 (NB. firefox บ่นเกี่ยวกับใบรับรอง SSL)

ตอนนี้ฉันกำลังใช้งาน try catch อย่างถูกต้องด้วยการกำหนดค่าต่อไปนี้

PHP 5.2.4 (cli) (สร้าง: 16 ตุลาคม 2550 09:13:35) ลิขสิทธิ์ (c) 1997-2007 PHP Group Zend Engine v2.2.0, ลิขสิทธิ์ (c) 1998-2007 Zend Technologies พร้อม eAccelerator v0.9.6 1 , ลิขสิทธิ์ (c) eAccelerator 2004-2010 โดย eAccelerator



3

ใน Xdebug มีการตั้งค่า:

xdebug.show_exception_trace = 1

สิ่งนี้จะบังคับให้ php ส่งออกข้อยกเว้นแม้ในบล็อก try catch เปลี่ยนเป็น0


2
ในกรณีของฉันฉันต้องปิดการใช้งานโมดูล xdebug อย่างสมบูรณ์ (การเปลี่ยน xdebug.show_exception_trace ไม่เพียงพอ)
Thomas Sahlin

ขอบคุณสำหรับการแจ้งเตือนนี้ ฉันสับสนไปชั่วขณะ
Brian Litzinger

3

หากคุณใช้ PHP 7 คุณอาจต้องใช้ Throwable แทน Exception


นี่เป็นโพสต์ที่ค่อนข้างเก่า ดูวันที่ของหัวข้อก่อนที่คุณจะตัดสินใจตอบ นอกจากนั้นคือคำตอบของคุณที่ไม่เป็นประโยชน์อย่างที่เป็นอยู่: - ไม่สมบูรณ์ - ไม่มีคำอธิบายว่าทำไม
เสียงเดียว

1
คำอธิบายคือ PHP7 ใช้ Throwable แทน Exception การสนทนานี้เป็นเรื่องแรกที่ฉันพบเมื่อพบปัญหาและต้องการมีส่วนร่วม ความคิดเห็นเหล่านี้เป็นสาเหตุที่ทำให้ Stack ไม่เป็นมิตรกับชุมชน
user5528384

1
ไม่ใช่เจตนาของฉันที่จะทำให้คุณขุ่นเคือง โพสต์นี้ปรากฏในคิวการตรวจสอบ "โพสต์แรก" และในความคิดของฉันการโพสต์คำตอบสำหรับคำถามที่ค่อนข้างเก่าก็ไม่มีประโยชน์ และในขณะที่เขียน Question Throwable ไม่ได้ถูกคิดค้นขึ้นในโลก PHP จะเป็นประโยชน์ถ้าคุณเขียนตอบว่า Throwable คืออินเทอร์เฟซที่ดำเนินการโดย Exception (และ Error) และสามารถตรวจจับได้เช่นกัน แต่ไม่ใช่ส่วนเสริมของข้อยกเว้น
monofone



1

ฉันกำลังประสบปัญหานี้เช่นกัน ฉันอ่านความคิดเห็นจาก Rowinson Gallego ซึ่งต้องทิ้งข้อยกเว้นของรัฐ ดังนั้นฉันจึงแก้ไขรหัสของฉันจาก:

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw $e;
}

เข้าสู่:

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw new Exception($e->getMessage(),$e->getCode());
}

มันได้ผล.

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