PHP'deki Try / Catch bloğu İstisnayı yakalamıyor


100

Bu Örnek 1'i bu sayfadan çalıştırmaya çalışıyorum: 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";
?>

Ancak istenen çıktı yerine şunu elde ederim:

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

Kullandığım geliştirici ortamı UniServer 3.5ilePHP 5.2.3


1
Bize kodunuzu gösterir misiniz? Bu hatayı almak için yapabileceğiniz tek hata, yanlış istisnayı (veya hiçbirini) yakalamaktır.
Tammo

2
Kod TAMAMEN aynı (yeni satırlar ekledim) ... her neyse, kodu bir test dosyasına bir kez daha kopyaladım ve işte aynı hata mesajı: 0.2 Önemli hata: Yakalanmamış istisna 'İstisna' mesajı ile 'Sıfıra bölme . ' W: \ www \ test.php: 4'te Yığın izleme: # 0 W: \ www \ test.php (11): 4. satırda W: \ www \ test.php içinde ters (0) # 1 {ana} atılır Orada neler olduğu hakkında hiçbir fikrim yok ... belki hatalı PHP yapılandırması?
Krassi

1
Bazı eski uzantı sürümleri, istisna işlemeyle ilgili sorunlara neden oldu. 5.2.3 eski ve hatanın arkasında bir hata olabilir. PHP'yi yükseltebilir misin? Mevcut üretim versiyonu 5.5 olduğu düşünüldüğünde UniServer 3.5 de oldukça eskidir. 3.5 bir yazım hatası mı?
outis

1
UniServer sürüm bilgilerine ( wiki.uniformserver.com/index.php/… ) bakıldığında , 3.5 görünüşe göre bir yazım hatası değil. UniServer 5.5'e yükseltin ve örnek kodu tekrar deneyin.
outis

1
outis, bahşiş için teşekkürler :). O zamanlar yaptığım buydu - XAMPP'ye geçtim (UniServer'ın yeni sürümünü beğenmedim). 3.5 bir yazım hatası değil, ancak sunucu benim için mükemmel çalıştı, bu yüzden yükseltmekle hiç uğraşmadım.
Krassi

Yanıtlar:


222

Sadece istisnanın adını bile kopyalamış gibi göründüğü halde tam olarak bu problemi yaşadım ama yine de yakalamadı. Aptalca bir hatam olduğu ortaya çıktı ama aynı durumda başka biri olması durumunda davamı buraya göndermem gerektiğini düşündüm.

A adlı ad alanımda istisnam vardı ve komut dosyası B adında bir ad alanındaydı . Sorun, (PHP'de) \ B \ A \ MyException'a eşit olan A \ MyException'ım olmasıydı (çünkü betiğim B ! Adlı isim alanında bulunuyor ). Düzeltmek için tek yapmam gereken, istisna adına ters eğik çizgi (veya adı ne olursa olsun) eklemekti, böylece şöyle görünecekti: \ A \ MyException


7
Bunu gönderdiğiniz için çok teşekkür ederim çünkü hatamı fark etmeden birkaç gün geçirirdim.
tipu

82
Bu benim sorunumu çözdü, ad alanlı kodda basit bir tembel yakalama bloğu olmalıdır catch (\Exception $e). Ters eğik çizgi olmadan Exceptionad alanına özgüdür ve eşleşmez (veya yakalanmaz).
joemaller

3
Bunu gönderdiğiniz için teşekkürler!
keepkimi

2
Bunu gönderdiğiniz için teşekkür ederim, son birkaç saati yakalama bloğumun neden işe yaramadığı için delirerek geçirdim. Büyük facepalm.
Mitch

4
Şerefe!
sebze

68

Oldukça eski bir soru, henüz ...

Ben de bu problemi yaşadım (ve bu yazıyı böyle buldum) ama sadece basit deney, çözümü bulmama izin verdi. Sadece değiştirmeyi deneyin Exceptioniçin \Exception. Benim için çalıştı!

DÜZENLE:

Sivann'ın yorumlarda işaret ettiği gibi, ad alanını kullanmak da aynı şeyi yapmalıdır. Yani use \Exception as Exception;, sınıf beyanınızın önüne koyun .


Parlak! :) Muhtemelen anlamam saatlerimi alırdı, sadece isim aralığını düşünmedim. Teşekkürler!
Alexander Gilmanov

Evet! ayrıca: "\ İstisnayı İstisna olarak kullanın;" üstte aynı şeyi yapıyor.
sivann

@ sii-anik Sivann'ın yazdığı gibi ad alanını kullanmayı deneyin.
Enethion

Sadece use Exception;bunu yapmalıyım
Diego Ponciano

33

catch(\Exception $e)Bunun yerine koymaya çalışın catch(Exception $e). Hakkında çok iyi bilmediğiniz bir kod kullanıyorsanız veya - özellikle - bir çerçeve kullanıyorsanız, varsayılan PHP İstisnasını kendi başına bir kodla geçersiz kılabilir ve bu nedenle yanlış yola gidebilir ve istenmeyen sonuç. Az önce koyarsanız \Exception, temel PHP istisnasını yakaladığınızdan eminiz.


@crassi, önerimi denedin mi?
Vladimir Despotovic

2
bu benim için yaptı
cljk

CI4'te çalışıyorum ve bu benim için çalıştı.
Adnan Ahmad

20

C # (Csharp) gibi başka bir dilde yapabildiğiniz gibi PHP'de tipik try {} catch {} bloklarını kullanamazsınız.

Eğer bunu yaparsan:

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

'Anladım!' Mesajını görmeyeceksiniz. asla mesaj. Neden? Bunun nedeni PHP'nin her zaman "Fırlatılması" için bir İstisnaya ihtiyacı olmasıdır. Kendi hata işleyicinizi ayarlamanız ve onunla bir İstisna atmanız gerekir.

Set_error_handler işlevine bakın : http://php.net/manual/es/function.set-error-handler.php


6
Bu aynı değil;) Kendi kendinize bir istisna atmanız gerekiyordu ve ben de öyle dedim (<< Bunun nedeni PHP'nin "Fırlatılması" için her zaman bir İstisnaya ihtiyacı olması >>) @JaredFarrish
Rowinson Gallego

Evet ama nasıl aynı değil?
Jared Farrish

Bu bağlantı kesildi
Loathing

PHP 7.3.9 Sürümünde, $number = 5/0;bir istisna oluşturmaz. $numberolarak ayarlandı INF.
virtualmic

6

İlk başta, yakaladığınız / attığınız istisna adında bir yazım hatası var, ancak kodunuz tamamen aynıysa, tam olarak ne olup bittiğinden emin değilim.

Orijinal komut dosyasının aşağıdaki değişikliğini deneyin ve sonuçlarınızı yapıştırın. Sorununuzu biraz daha iyi teşhis etmenize yardımcı olacaktır.

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

Aşağıdaki konfigürasyonlarla aynı sorunu yaşadım,

PHP 5.2.14 (cli) (inşa: Aug 12 2010 17:32:30) Telif hakkı (c) 1997-2010 The PHP Group Zend Engine v2.2.0, Telif Hakkı (c) 1998-2010 Zend Technologies, eAccelerator v0.9.5 ile. 1 , Telif Hakkı (c) 2004-2006 eAccelerator, eAccelerator tarafından

Çözüm, eAccelerator'ı devre dışı bırakmak veya güncellemektir. İkisini de denedim ve her ikisi de işe yaradı. Hata burada bildirilmiştir https://eaccelerator.net/ticket/242 (NB. Firefox, SSL sertifikaları hakkında şikayette bulunur).

Şimdi çalıştırıyorum, aşağıdaki yapılandırmalarla düzgün bir şekilde yakalamaya çalışıyorum,

PHP 5.2.4 (cli) (inşa: 16 Ekim 2007 09:13:35) Telif Hakkı (c) 1997-2007 The PHP Group Zend Engine v2.2.0, Telif Hakkı (c) 1998-2007 Zend Technologies, eAccelerator v0.9.6 ile. 1 , Telif Hakkı (c) 2004-2010 eAccelerator, eAccelerator tarafından



3

Xdebug'da bir ayar var:

xdebug.show_exception_trace = 1

Bu, php'yi bir try catch bloğunda bile istisnalar üretmeye zorlar. Bunu çevir0


2
Benim durumumda xdebug modülünü tamamen devre dışı bırakmak zorunda kaldım (xdebug.show_exception_trace'i değiştirmek yeterli değildi).
Thomas Sahlin

Bu hatırlatıcı için teşekkürler. Bir süre kafam iyice karıştı.
Brian Litzinger

3

PHP 7 kullanıyorsanız, Exception yerine Throwable'a ihtiyacınız olabilir.


Bu oldukça eski bir gönderi. Cevap vermeye karar vermeden önce konunun tarihine bir göz atın. Bunun yanı sıra, cevabınız şu olduğu için pek yardımcı olmuyor: - tam değil - neden açıklaması yok
monofone

1
Açıklama, PHP7'nin Exception yerine Throwable'ı kullanmasıdır. Bu tartışma, sorunla karşılaştığımda bulduğum ilk tartışmaydı ve katkıda bulunmak istedim. Bunun gibi yorumlar, Stack'in topluluk dostu olmamasının nedenleridir.
user5528384

1
seni gücendirmek niyetim değildi. Bu gönderi "İlk gönderiler" İnceleme kuyruğunda göründü ve bence oldukça eski bir soruya yanıt göndermek yararlı olmadı. Ve Soru Throwable yazılırken PHP dünyasında icat edilmemişti. İçine Throwable'ın Exception (ve Error) tarafından uygulanan Arayüz olduğunu ve bu nedenle de yakalanabileceğini yazmanız yararlı olacaktır. Ancak, bir İstisnaya ek değildir.
monofone

2

TLDR; use Exception;her iki php dosyasının da üstünde olduğundan emin olun



1

Ben de bunu yaşıyorum. Rowinson Gallego'dan istisna atılması gereken durumu okudum. Bu yüzden kodumu şundan değiştirdim:

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

içine:

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

İşe yarıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.