Bir uyarıyı deneyebilir miyim?


358

Bazı php yerli işlevlerden atılan bazı uyarıları yakalamak ve sonra onları işlemek gerekir.

özellikle:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

DNS sorgusu başarısız olduğunda bir uyarı verir.

try/ catchbir uyarı bir istisna olmadığından çalışmaz.

Şimdi 2 seçeneğim var:

  1. set_error_handler overkill gibi görünüyor çünkü sayfadaki her uyarıyı filtrelemek için kullanmak zorundayım (bu doğru mu?);

  2. Hata bildirimini / görüntüsünü bu uyarılar ekrana yansıtılmayacak şekilde ayarlayın, ardından dönüş değerini kontrol edin; öyleyse false, ana bilgisayar adı için kayıt bulunamadı.

Buradaki en iyi uygulama nedir?


1
stackoverflow.com/questions/136899/… bu gibi şeyler hakkında iyi bir tartışma.
Mez

aşağıda silinen bir cevap var mı? sahibi mi yoksa biri mi?
user121196


@ user121196: Evet. Sahibi tarafından.
Orbit'te

Yanıtlar:


373

Hata işleyiciyi ayarlama ve geri yükleme

Bir olasılık, aramadan önce kendi hata işleyicinizi ayarlamak ve daha sonra önceki hata işleyiciyi geri yüklemektir restore_error_handler().

set_error_handler(function() { /* ignore errors */ });
dns_get_record();
restore_error_handler();

Bu fikir üzerine inşa edilebilir ve hataları sizin için kaydeden yeniden kullanılabilir bir hata işleyici yazabilirsiniz.

set_error_handler([$logger, 'onSilencedError']);
dns_get_record();
restore_error_handler();

Hataları istisnalara dönüştürme

Tüm php hatalarını istisnalara dönüştürmek için set_error_handler()ve ErrorExceptionsınıfını kullanabilirsiniz .

set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) {
    // error was suppressed with the @-operator
    if (0 === error_reporting()) {
        return false;
    }

    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    dns_get_record();
} catch (ErrorException $e) {
    // ...
}

Kendi hata işleyicinizi kullanırken dikkat etmeniz gereken önemli şey, error_reportingayarın atlanıp tüm hataları (bildirimler, uyarılar vb.) Hata işleyicinize iletmesidir. set_error_handler()Hangi hata türlerini almak istediğinizi tanımlamak için ikinci bir argüman ayarlayabilir veya ... = error_reporting()hata işleyicinin içinde kullanarak geçerli ayara erişebilirsiniz .

Uyarının bastırılması

Başka bir olasılık da @ operatörü ile çağrıyı bastırmak ve dns_get_record()daha sonra dönüş değerini kontrol etmektir . Ancak , hataların / uyarıların bastırılması için değil, tetiklenmesi için tetiklendiği için buna karşı öneriyorum .


3
işlev çağrısından hemen önce kendi hata işleyicimi, ardından hata denetimi yapıldığında restore_error_handler'ı ayarlaman önerilir mi?
user121196

2
çok sayıda eşzamanlı istek varsa iş parçacığı güvenli olacak ve her istek 1.set_error_handler () yapar. 3.restore_error_handler?
user121196

4
Teşekkürler; bu yardımcı olur. (Ve PHP'nin bir felaket olmadığını söylüyorlar.)
Aaron Miller

2
Hataları bastırmak için @ kullanmaktan kaçınmak için +1. E_WARNING aslında ölümcül olmayan bir hatadır. Genel olarak hataları daima uygun şekilde ele almalısınız. Uygulamanız set_error_handler kullanımını gerektiriyorsa, bunu yapın. Genellikle hataları günlüğe kaydetmeniz ve bir üretim ortamında görüntülemeyi devre dışı bırakmanız önerilir. Günlükleri kontrol ettikten sonra geliştirme ortamınızda nerede değişiklik yapacağınızı görebilirsiniz. @ Fopen / @ unlink'i gördüğüm çok fazla örnek var ve geliştiricinin hataları önlemek veya set_error_handler kullanarak hatayı işlemek için neden kontrol gerçekleştirmediğini merak ediyorum.
Ocak'ta fyrye

5
Uyarıları istisnalara dönüştürmeyle ilgili bir not: Bir uyarı uygulamanızı iptal etmeyecektir; yakalanmamış bir istisna olacaktır!
Álvaro González

149

Gerçekten işe yarayan çözüm, E_WARNINGparametre ile basit hata işleyicisini ayarlamak gibi çıktı:

set_error_handler("warning_handler", E_WARNING);
dns_get_record(...)
restore_error_handler();

function warning_handler($errno, $errstr) { 
// do something
}

4
Ayrıca callableburada anonim ile işlev beyanı yerine dize kullanılabilir
vp_arth

Teşekkürler, ancak kritik bloktan sonra hata işleyiciyi nasıl kaldırabilirim?
Yevgeniy Afanasyev

3
Mükemmel! Sadece trow new \Exception($errstr, $errno);warning_handlerfonksiyon. Teşekkürler.
Vladimir Vukanac

Buradaki en iyi cevap bu!
lewis4u

28

@Operatöre dikkat edin - uyarıları bastırırken ölümcül hataları da bastırır. Birisi yazmış bir sistemde bir sorun hata ayıklama çok zaman geçirdim @mysql_query( '...' )ve sorun mysql desteği PHP içine yüklenmemiş ve sessiz bir ölümcül hata attı oldu. PHP çekirdeğinin parçası olan şeyler için güvenli olacak, ancak lütfen dikkatli kullanın.

bob@mypc:~$ php -a
Interactive shell

php > echo @something(); // this will just silently die...

Başka çıkış yok - bu hata ayıklama iyi şanslar!

bob@mypc:~$ php -a
Interactive shell

php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error:  Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
bob@mypc:~$ 

Bu kez neden başarısız olduğunu görebiliriz.


5

Bir uyarıyı denemek / yakalamak istedim, ama aynı zamanda her zamanki uyarı / hata günlüğünü tutmak (örneğin /var/log/apache2/error.log); işleyicinin geri dönmesi gerekiyor false. Bununla birlikte, "yeni fırlat ..." ifadesi temel olarak yürütmeyi kesintiye uğrattığından, biri şu şekilde de tartışılan "işlevde sarma" hilesi yapmak zorundadır:

Php istisna atmak için statik bir yolu var mı

Veya kısaca:

  function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
  }
  function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
    return false && throwErrorException($errstr, 0, $errno, $errfile, $errline);
    # error_log("AAA"); # will never run after throw
    /* Do execute PHP internal error handler */
    # return false; # will never run after throw
  }
  ...
  set_error_handler('warning_handler', E_WARNING);
  ...
  try {
    mkdir($path, 0777, true);
  } catch (Exception $e) {
    echo $e->getMessage();
    // ...
  }

DÜZENLEME: Bu çalışma değil dışarı yakından bakıldığında sonra, döner: " return false && throwErrorException ...", temelde, olacaktır değil istisna ve sadece hata günlüğünde log; " false &&" bölümünde olduğu gibi " " kaldırılması, return throwErrorException ...istisna atma işini yapar, ancak error_log'da oturum açmaz ... Bu davranışı başka bir yerde belgelediğim halde görmedim.


4

Muhtemelen uyarıdan tamamen kurtulmaya çalışmalısınız, ancak bu mümkün değilse, çağrıyı @ (örn. @Dns_get_record (...)) ile başlatabilir ve daha sonra uyarı olup olmadığını anlayabileceğiniz tüm bilgileri kullanabilirsiniz ya da değil.


4

Normalde bu tek çözüm olmadıkça asla @ kullanmamalısınız. Bu durumda kaydın var olup olmadığını bilmek için önce dns_check_record işlevi kullanılmalıdır.


3

Bu kod satırlarını file_get_contents()harici bir URL'ye yapılan bir çağrı etrafında birleştirmek, " akış açılamadı: Bağlantı zaman aşımına uğradı " gibi uyarıları çok daha iyi kullanmama yardımcı oldu:

set_error_handler(function ($err_severity, $err_msg, $err_file, $err_line, array $err_context)
{
    throw new ErrorException( $err_msg, 0, $err_severity, $err_file, $err_line );
}, E_WARNING);
try {
    $iResult = file_get_contents($sUrl);
} catch (Exception $e) {
    $this->sErrorMsg = $e->getMessage();
}
restore_error_handler();

Bu çözüm nesne bağlamında da çalışır. Bir işlevde kullanabilirsiniz:

public function myContentGetter($sUrl)
{
  ... code above ...
  return $iResult;
}

2

Eğer dns_get_record()başarısız, bu dönmelidir FALSEsizinle uyarıyı bastırmak böylece, @ve sonra dönüş değerini kontrol edin.


0

bir boolean değeri döndürüp döndürmediğini kontrol etmeyi deneyin, ardından bunu bir koşul olarak koyabilirsiniz. Ben benzersiz tuşları ile bazı ihlal dönen oci_execute (...) ile karşılaştım.

ex.
oci_parse($res, "[oracle pl/sql]");
if(oci_execute){
...do something
}

0

Folderstructure

index.php //Script File
logs //Folder for log Every warning and Errors
CustomException.php //Custom exception File

CustomException.php

/**
* Custom error handler
*/
function handleError($code, $description, $file = null, $line = null, $context = null) {
    $displayErrors = ini_get("display_errors");;
    $displayErrors = strtolower($displayErrors);
    if (error_reporting() === 0 || $displayErrors === "on") {
        return false;
    }
    list($error, $log) = mapErrorCode($code);
    $data = array(
        'timestamp' => date("Y-m-d H:i:s:u", time()),
        'level' => $log,
        'code' => $code,
        'type' => $error,
        'description' => $description,
        'file' => $file,
        'line' => $line,
        'context' => $context,
        'path' => $file,
        'message' => $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']'
    );
    $data = array_map('htmlentities',$data);
    return fileLog(json_encode($data));
}

/**
* This method is used to write data in file
* @param mixed $logData
* @param string $fileName
* @return boolean
*/
function fileLog($logData, $fileName = ERROR_LOG_FILE) {
    $fh = fopen($fileName, 'a+');
    if (is_array($logData)) {
        $logData = print_r($logData, 1);
    }
    $status = fwrite($fh, $logData . "\n");
    fclose($fh);
//    $file = file_get_contents($filename);
//    $content = '[' . $file .']';
//    file_put_contents($content); 
    return ($status) ? true : false;
}

/**
* Map an error code into an Error word, and log location.
*
* @param int $code Error code to map
* @return array Array of error word, and log location.
*/
function mapErrorCode($code) {
    $error = $log = null;
    switch ($code) {
        case E_PARSE:
        case E_ERROR:
        case E_CORE_ERROR:
        case E_COMPILE_ERROR:
        case E_USER_ERROR:
            $error = 'Fatal Error';
            $log = LOG_ERR;
            break;
        case E_WARNING:
        case E_USER_WARNING:
        case E_COMPILE_WARNING:
        case E_RECOVERABLE_ERROR:
            $error = 'Warning';
            $log = LOG_WARNING;
            break;
        case E_NOTICE:
        case E_USER_NOTICE:
            $error = 'Notice';
            $log = LOG_NOTICE;
            break;
        case E_STRICT:
            $error = 'Strict';
            $log = LOG_NOTICE;
            break;
        case E_DEPRECATED:
        case E_USER_DEPRECATED:
            $error = 'Deprecated';
            $log = LOG_NOTICE;
            break;
        default :
            break;
    }
    return array($error, $log);
}
//calling custom error handler
set_error_handler("handleError");

yukarıdaki dosyayı böyle script dosyasına ekleyin

index.php

error_reporting(E_ALL);
ini_set('display_errors', 'off');
define('ERROR_LOG_FILE', 'logs/app_errors.log');

include_once 'CustomException.php';
echo $a; // here undefined variable warning will be logged into logs/app_errors.log

-2

Ben sadece düz bir işlem (örneğin $ prop = @ ($ yüksek / ($ genişlik - $ derinlik)); bölümü sıfır uyarı ile atlamak için) uyarıları bastırmak için @ kullanmanızı tavsiye ederim. Ancak çoğu durumda idare etmek daha iyidir.


2
Bu kesinlikle @ kullanmak istemediğiniz bir seferdir - işlem üzerinde kontrole sahipsiniz ve bunu yapmadan önce sıfıra bölünüp bölünmediğini kontrol edebilirsiniz.
Eborbob
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.