Coba / Tangkap blok di PHP tidak menangkap Exception


97

Saya mencoba menjalankan Contoh # 1 ini dari halaman ini: 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";
?>

Namun, alih-alih keluaran yang diinginkan, saya mendapatkan:

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

Lingkungan pengembang yang saya gunakan adalah UniServer 3.5denganPHP 5.2.3


1
Bisakah Anda menunjukkan kode Anda? Satu-satunya kesalahan yang dapat Anda lakukan untuk mendapatkan kesalahan ini adalah menangkap pengecualian yang salah (atau tidak sama sekali).
Tammo

2
Kode PERSIS identik (Saya baru saja menambahkan beberapa baris baru) ... bagaimanapun, saya menyalin kode sekali lagi ke dalam file tes dan berikut adalah pesan kesalahan yang sama: 0,2 Kesalahan fatal: Pengecualian 'Pengecualian' yang tidak tertangkap dengan pesan 'Pembagian oleh nol . ' di W: \ www \ test.php: 4 Pelacakan tumpukan: # 0 W: \ www \ test.php (11): inverse (0) # 1 {main} dilemparkan ke W: \ www \ test.php di baris 4 Saya benar-benar tidak tahu apa yang terjadi di sana ... mungkin konfigurasi PHP salah?
Krassi

1
Beberapa versi ekstensi yang lebih lama menyebabkan masalah dengan penanganan pengecualian. 5.2.3 sudah tua dan bug mungkin ada di balik kesalahan ini. Bisakah Anda meningkatkan PHP? UniServer 3.5 juga terbilang cukup tua, mengingat versi produksi saat ini adalah 5.5. Apakah 3.5 salah ketik?
keluar

1
Melihat info rilis UniServer ( wiki.uniformserver.com/index.php/… ), 3.5 ternyata bukan salah ketik. Tingkatkan ke UniServer 5.5 dan coba kode sampel lagi.
keluar

1
outis, terima kasih atas tipnya :). Inilah yang saya lakukan saat itu - beralih ke XAMPP (tidak suka versi baru UniServer). 3.5 bukan kesalahan ketik, tetapi server bekerja dengan sempurna untuk saya jadi saya tidak pernah repot memutakhirkannya.
Krassi

Jawaban:


217

Saya baru saja mengalami masalah ini di mana sepertinya saya telah menyalin nama pengecualian, namun tidak menangkapnya. Ternyata itu adalah kesalahan bodoh saya, tetapi saya pikir saya harus memposting kasus saya di sini jika ada orang lain dalam situasi yang sama.

Aku punya pengecualian saya di namespace saya disebut A dan script itu dalam namespace disebut B . Masalahnya adalah saya memiliki A \ MyException yang sama dengan (dalam PHP) \ B \ A \ MyException (karena skrip saya ada di namespace bernama B !). Yang harus saya lakukan untuk memperbaikinya adalah menambahkan garis miring terbalik (atau apa pun namanya) ke nama pengecualian sehingga akan terlihat seperti ini: \ A \ MyException


7
terima kasih banyak telah memposting ini karena saya akan pergi beberapa hari tanpa menyadari kesalahan saya.
tipu

79
Ini memecahkan masalah saya, blok tangkap malas sederhana dalam kode spasi nama seharusnya catch (\Exception $e). Tanpa garis miring terbalik Exceptionkhusus untuk namespace dan tidak akan cocok (atau tertangkap).
joemaller

3
Terima kasih telah memposting ini!
keepkimi

2
Terima kasih telah memposting ini, saya baru saja menghabiskan beberapa jam terakhir menjadi gila mengapa blok tangkap saya tidak berfungsi. Telapak muka utama.
Mitch

4
Bersulang! Menyelamatkan hari saya (dan neuron ...) :)
sayuran

67

Pertanyaan yang cukup lama, namun ...

Saya mengalami masalah ini juga (dan begitulah cara saya menemukan posting ini) tetapi hanya eksperimen sederhana yang memungkinkan saya menemukan solusinya. Coba saja ubah Exceptionke \Exception. Bekerja untuk saya!

EDIT:

Seperti yang ditunjukkan sivann di komentar, menggunakan namespace harus melakukan hal yang sama. Jadi, letakkan saja use \Exception as Exception;sebelum deklarasi kelas Anda.


Cemerlang! :) Mungkin butuh waktu berjam-jam untuk mengetahuinya, hanya tidak memikirkan namespacing. Terima kasih!
Alexander Gilmanov

Iya! juga: "use \ Exception as Exception;" di atas melakukan hal yang sama.
sivann

@ sii-anik Coba gunakan namespace seperti yang sivann tulis.
Enethion

hanya use Exception;harus melakukannya
Diego Ponciano

Terima kasih! @Enethion
Noamway

32

Cobalah untuk menempatkan, catch(\Exception $e)bukan catch(Exception $e). Jika Anda menggunakan kode yang tidak Anda ketahui dengan baik, atau - terutama - jika Anda menggunakan kerangka kerja, itu mungkin menimpa Pengecualian PHP default dengan salah satunya, dan oleh karena itu Anda mungkin pergi ke jalur yang salah dan mendapatkan hasil yang tidak diinginkan. Jika Anda hanya memasukkan \Exception, maka Anda yakin Anda menangkap pengecualian dasar PHP.


@crassi, apakah Anda mencoba saran saya?
Vladimir Despotovic

2
yang melakukannya untuk saya
cljk

20

Anda tidak bisa menggunakan blok try {} catch {} biasa dalam PHP seperti yang bisa Anda lakukan dalam bahasa lain seperti C # (Csharp).

Jika kamu melakukan ini:

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

Anda tidak akan melihat pesan 'Mengerti!' pesan tidak pernah. Mengapa? Itu hanya karena PHP selalu membutuhkan Pengecualian untuk "Dilempar". Anda perlu menyetel penangan kesalahan Anda sendiri dan melemparkan Pengecualian dengannya.

Lihat fungsi set_error_handler : http://php.net/manual/es/function.set-error-handler.php


6
Itu tidak sama;) Anda perlu membuat pengecualian sendiri, dan itulah yang saya katakan (<< Ini hanya karena PHP selalu membutuhkan Pengecualian untuk "Dilempar" >>) @JaredFarrish
Rowinson Gallego

Ya, tapi kenapa tidak sama?
Jared Farrish

Tautan itu mati, tetapi saya menemukan ini berguna: w3schools.com/php/func_error_set_error_handler.asp
Membenci

Dalam PHP Versi 7.3.9, $number = 5/0;tidak memunculkan pengecualian. $numberdiatur menjadi INF.
virtualmic

6

Awalnya saya adalah Anda memiliki kesalahan ketik dalam nama pengecualian yang Anda tangkap / lempar, tetapi jika kode Anda persis sama, saya tidak yakin persis apa yang sedang terjadi.

Coba modifikasi berikut dari skrip asli, dan tempelkan hasil Anda. Ini akan membantu mendiagnosis masalah Anda sedikit lebih baik.

<?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

Saya memiliki masalah yang sama dengan konfigurasi berikut,

PHP 5.2.14 (cli) (dibangun: Agustus 12 2010 17:32:30) Hak Cipta (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Hak Cipta (c) 1998-2010 Zend Technologies dengan eAccelerator v0.9.5. 1 , Hak Cipta (c) 2004-2006 eAccelerator, oleh eAccelerator

Solusinya adalah menonaktifkan eAccelerator atau memperbaruinya. Saya mencoba keduanya dan kedua perbaikan berhasil. Bug dilaporkan di sini https://eaccelerator.net/ticket/242 (NB. Firefox mengeluh tentang sertifikat SSL mereka).

Sekarang saya menjalankan coba tangkap dengan benar dengan konfigurasi berikut,

PHP 5.2.4 (cli) (dibangun: Okt 16 2007 09:13:35) Hak Cipta (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Hak Cipta (c) 1998-2007 Zend Technologies dengan eAccelerator v0.9.6. 1 , Hak Cipta (c) 2004-2010 eAccelerator, oleh eAccelerator



3

di Xdebug ada pengaturan:

xdebug.show_exception_trace = 1

Ini akan memaksa php untuk mengeluarkan pengecualian bahkan dalam blok coba tangkap. Putar ini ke0


2
Dalam kasus saya, saya harus menonaktifkan modul xdebug sepenuhnya (mengubah xdebug.show_exception_trace tidak cukup).
Thomas Sahlin

Terima kasih atas pengingat ini. Saya benar-benar bingung untuk beberapa saat.
Brian Litzinger

3

Jika Anda menggunakan PHP 7, Anda mungkin perlu Throwable, bukan Exception


Ini adalah postingan yang agak lama. Perhatikan tanggal topik sebelum Anda memutuskan untuk menjawab. Selain itu jawaban Anda tidak terlalu membantu karena: - tidak lengkap - tidak ada penjelasan mengapa
monofone

1
Penjelasannya adalah bahwa PHP7 menggunakan Throwable, bukan Exception. Diskusi ini adalah yang pertama kali saya temukan ketika saya menemui masalah dan saya ingin berkontribusi. Komentar seperti ini adalah alasan mengapa Stack tidak ramah komunitas.
pengguna5528384

1
itu bukan niat saya untuk menyinggung perasaan Anda. Posting ini muncul di antrian review "Posting pertama" dan menurut saya tidak berguna untuk mengirim jawaban atas pertanyaan yang agak lama. Dan pada saat penulisan, Question Throwable bahkan tidak ditemukan di dunia PHP. Akan sangat membantu jika Anda menulis dalam jawaban Anda bahwa Throwable adalah Antarmuka yang diimplementasikan oleh Exception (dan Error) dan dengan demikian dapat ditangkap juga. Tapi ini bukan suplemen untuk sebuah Pengecualian.
monofone


1

TLDR; pastikan Anda memiliki use Exception;di bagian atas kedua file php


0

Saya mengalami ini juga. Saya membaca komentar dari Rowinson Gallego yang menyatakan Exception harus dibuang. Jadi saya mengubah kode saya dari:

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

menjadi:

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

Berhasil.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.