programing

PHP에서 @ 연산자를 사용하여 오류 억제

goodjava 2023. 2. 3. 20:09

PHP에서 @ 연산자를 사용하여 오류 억제

PHP의 오류/경고를 억제하기 위해 @ 연산자를 사용하는 것이 타당하다고 생각하십니까?

그렇다면 어떤 상황에서 사용하시겠습니까?

코드 예는 환영입니다.

편집: 리플라이어에 대한 메모.에러 보고를 무효로 하는 것은 아니지만, 예를 들어 일반적인 방법은

@fopen($file);

나중에 확인하고...@를 없애려면

if (file_exists($file))
{
    fopen($file);
}
else
{
    die('File not found');
}

또는 이와 유사합니다.

문제는 다른 방법으로 처리할 수 없는 오류를 억제하기 위해 @를 사용해야 하는 곳이 있는가 하는 것입니다.

주의: 우선, PHP 개발자의 99%가 에러 억제 연산자(저도 그 중 하나였습니다)를 사용하고 있는 것을 알고 있기 때문에, 이것을 본 PHP 개발자는 동의하지 않을 것으로 예상됩니다.

PHP의 오류/경고를 억제하기 위해 @ 연산자를 사용하는 것이 타당하다고 생각하십니까?

다음 중 하나:

긴:
모든 것을 알지는 못하기 때문에 잘 모르지만, 지금까지 좋은 해결책이 될 만한 상황은 만나지 못했습니다.

쁜쁜: :
PHP를 사용한 지 7년 정도 된 것 같습니다만, 에러 억제 연산자에 의한 디버깅의 고민은 끝이 없고, 피할 수 없는 상황도 없었습니다.

문제는 에러를 억제하고 있는 코드의 일부가, 현재 표시되는 에러만을 일으킬 가능성이 있는 것입니다.단, 억제 회선이 의존하는 코드나 그 코드 실행 환경을 변경하면, 회선이 시도하고 있던 것과는 전혀 다른 에러를 출력하려고 할 가능성이 있습니다.무시하다.그러면 출력되지 않는 오류를 어떻게 추적합니까?지옥 디버깅에 오신 걸 환영합니다!

억제된 오류 때문에 내가 몇 달마다 얼마나 많은 시간을 낭비하고 있는지 깨닫는 데 많은 시간이 걸렸다.대부분의 경우(단, 전유물은 아니지만) 개발자 환경에서 오류가 없는 서드파티 스크립트/앱/라이브러리를 설치한 후입니다.그러나 php 또는 서버 구성의 차이 또는 의존관계 누락으로 인해 문제가 무엇인지 즉시 경고할 수 있지만 개발자가 ma를 추가할 때는 그렇지 않습니다.gic @ 。

대안(상황 및 원하는 결과에 따라 다름):
코드 조각으로 인해 특정 오류가 발생할 경우 해당 상황에서 실행되지 않도록 사용자가 알고 있는 실제 오류를 처리합니다.하지만 이 부분은 최종 사용자가 오류를 볼까 봐 걱정했던 부분이라고 생각합니다.이 부분은 지금부터 다루도록 하겠습니다.

일반적인 오류의 경우 페이지를 표시할 때 원하는 방식으로 출력되지만 최종 사용자로부터 숨겨져 기록되도록 오류 핸들러를 설정하여 사용자가 트리거하는 오류를 파악할 수 있습니다.

" " "를 설정합니다.display_errorsphp.ini에서 꺼짐(오류 핸들러가 계속 트리거됨) 및 오류 로깅을 활성화합니다.(권장하는) 라이브 서버뿐만 아니라 개발 서버를 사용하는 경우에도 이 단계는 개발 서버에서 필요하지 않으므로 오류 로그 파일을 확인하지 않고도 이러한 치명적인 오류를 디버깅할 수 있습니다.셧다운 기능을 사용하여 오류 핸들러에 치명적인 오류를 대량으로 전송하는 방법도 있습니다.

★★★★
이유가 있을지도 않기 까지 (@) 그럴 만한 이유가 있을지도 모르지만, 아직 본 적이 없기 때문에, 그때까지 (@) 에러 억제 연산자는 사악하다고 생각합니다.

자세한 내용은 PHP 매뉴얼의 Error Control Operators 페이지에서 확인하실 수 있습니다.

는 오류를 억제하고 처리할 것이다.그렇지 않으면 TOCTOU 문제(확인 시간, 사용 시간)가 발생할 수 있습니다.예를 들어 file_exists가 true를 반환한 후 fopen 전에 파일이 삭제될 수 있습니다).

하지만 오류를 없애기 위해 그냥 억누르지는 않을 거예요.잘 보이도록 해

네, 억압은 말이 됩니다.

를 들면, 「」는,fopen()를 실행하면 반환됩니다.FALSE파일을 열 수 없는 경우.그것도 괜찮지만 PHP 경고 메시지가 나타납니다.대부분의 경우 경고는 원하지 않습니다. - 확인하겠습니다.FALSE네 자신.

실제로 PHP 매뉴얼에서는 이 경우 @를 사용하는 것이 특히 권장되고 있습니다.

fopen()과 같은 함수를 사용할 때 경고를 발생시키지 않으려면 오류를 억제할 수 있지만 예외를 사용할 수 있습니다.

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}

모든 조건을 처리할 수 있다는 것을 모르는 한 오류 억제는 피해야 합니다.

이것은 처음 보는 것보다 훨씬 더 어려울 수 있다.

사용자가 페이지를 보고 오류를 보고 있다고 믿을 수 없기 때문에 실제로 해야 할 일은 php의 "error_log"를 보고 방법으로 사용하는 것입니다(또한 이러한 오류를 표시하지 않도록 해야 합니다).

그러면 적어도 시스템에서 모든 문제가 발생한 것에 대한 포괄적인 보고서를 얻을 수 있을 것입니다.

에러를 처리할 필요가 있는 경우는, 커스텀 에러 핸들러를 작성할 수 있습니다.

http://php.net/set-error-handler

그 후 예외(처리 가능)를 송신해, 관리에 이상한 에러를 보고하기 위해서 필요한 조작을 실시할 수 있습니다.

난 절대 '@'를 쓰지 않아...마침표

코드의 「@」의 사용법을 발견했을 때는, 사용 시점이나, 사용하는 기능 주위의 문서 블록에 코멘트를 붙여 명확하게 합니다.저도 이러한 에러 억제에 의해 「고스트의 추적」디버깅에 시달리고 있습니다만, 발견했을 때에 그 사용법을 강조 표시해, 다음 사람에게 용이하게 하고 싶다고 생각하고 있습니다.

네이티브 PHP 함수에 에러가 발생했을 경우에, 「@」라고 하는 것이 쉬운 방법이라고 생각되는 경우는, 대신에 같은 결과를 얻을 수 있지만, 코드에 명확하게 나타나 있는 것을 선택합니다.

$orig = error_reporting(); // capture original error level
error_reporting(0);        // suppress all errors
$result = native_func();   // native_func() is expected to return FALSE when it errors
error_reporting($orig);    // restore error reporting to its original level
if (false === $result) { throw new Exception('native_func() failed'); }

코드만 작성해도 훨씬 더 많은 코드입니다.

$result = @native_func();

하지만 나는 나를 따라오는 불쌍한 디버깅 영혼을 위해 내 억압의 필요성을 분명히 하는 것을 선호한다.

대부분의 사람들은 오류 메시지의 의미를 이해하지 못한다.
마마농농농농농농그들 중 대부분.

뭔가 잘못됐어!고고말말말말다다
이치노
에러 메시지의 가장 중요한 부분이기도 하지만, 그것이 제기되었다는 사실뿐만 아니라 의미도 있습니다.무엇이 잘못되고 있는지 알려줄 수 있다.에러 메세지는, 「숨기는 방법」의 문제로 귀찮게 하는 것이 아니고, 헬프를 위한 것입니다.그것은 신참 웹프로그래밍계의 가장 큰 오해 중 하나이다.

따라서 오류 메시지에 재갈을 물리지 말고 내용을 읽어야 한다."file not found" 값이 하나만 있는 것은 아닙니다.에러는 수천 가지가 될 수 있습니다.permission denied,save mode restriction,open_basedir restriction기타 등등.각각 적절한 조치가 필요합니다.하지만 재갈을 물린다면 무슨 일이 일어났는지 절대 모를 거야!

OP는 오류 보고와 오류 처리를 혼동하고 있지만, 큰 차이를 보이고 있습니다.
여기무슨일이 합니다.'가た일
에러 리포트는 프로그래머를 위한 것이지만, 프로그래머는 확실히 무슨 일이 일어났는지 알아야 합니다.

따라서 오류 메시지에 재갈을 물리지 마십시오. 다 프로그래머를 위해 로그를 기록하고 사용자를 위해 처리합니다.

php.ini의 경고와 오류를 억제하는 방법은 없습니까?이 경우 디버깅할 수 있는 것은 플래그 변경뿐이며 어떤 @가 문제를 숨기고 있는지 검출하지 않습니다.

@ 를 사용하면, 역효과가 날 수 있습니다.제 경험상, 항상 php.ini 또는 call에서 오류 보고를 해제해야 합니다.

error_reporting(0);

생산 현장에서요.이렇게 하면 개발 중에 행을 코멘트 아웃하고 오류를 표시하여 디버깅할 수 있습니다.

사용하고 있는 장소 중 하나는 소켓코드입니다.예를 들어 타임아웃이 설정되어 있는 경우 패킷을 취득할 수 없는 경우에도 @를 포함하지 않으면 경고가 표시됩니다.

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port )

제가 정말 사용해야 할 곳은 eval 기능뿐입니다.eval의 문제는 구문 오류로 인해 문자열을 구문 분석할 수 없는 경우 eval이 false를 반환하지 않고 일반 스크립트에 구문 분석 오류가 있는 것처럼 오류를 발생시킨다는 것입니다.문자열에 저장된 스크립트가 해석 가능한지 여부를 확인하려면 다음과 같은 방법을 사용할 수 있습니다.

$script_ok = @eval('return true; '.$script);

AFAIK, 이게 가장 우아한 방법이에요.

는 PHP를 합니다.E_NOTICE(를 들어 비시리얼라이즈 함수).

(PHP 버전 7+의 경우) 이 오류를 포착하는 가능한 방법은 발행된 모든 오류를 예외로 변환하고 이 오류를 발행하지 않도록 하는 입니다.E_NOTICE예외 에러 핸들러를 다음과 같이 변경할 수 있습니다.

function exception_error_handler($severity, $message, $file, $line) {                                                                       
    throw new ErrorException($message, 0, $severity, $file, $line);          
}                                                                            

set_error_handler('exception_error_handler');                          

try {             
    unserialize('foo');
} catch(\Exception $e) {
    // ... will throw the exception here
}       

오늘은 적어도 일시적으로 @ 연산자를 사용하고 싶은 경우의 좋은 예시가 되는 문제를 발견했습니다.

간단히 말하면, 에러 로그 트레이스에 로그인 정보(일반 텍스트의 유저명과 패스워드)가 기입되어 있는 것을 발견했습니다.

이 문제에 대한 자세한 내용은 다음과 같습니다.

로그온 로직은 자체 클래스 내에 있습니다.시스템은 다른 로그온 메커니즘을 제공해야 하기 때문입니다.서버 이행 문제로 인해 오류가 발생했습니다.이 에러는 패스워드 정보를 포함한 트레이스 전체를 에러 로그에 덤프 했습니다.어떤 방법에서는 사용자 이름과 패스워드를 파라미터로 상정하고 있기 때문에 트레이스는 에러 로그에 모든 것을 기입했습니다.

여기서 장기적인 수정은 사용자 이름과 비밀번호를 2개의 파라미터로 사용하는 것이 아니라 예를 들어 이들 2개의 값을 포함하는 단일 어레이 파라미터를 사용하여 해당 클래스를 리팩터링하는 것입니다(이 경우 트레이스는 파라미터의 어레이를 기입합니다).이 문제에 대처하는 다른 방법도 있지만, 그것은 전혀 다른 문제입니다.

어쨌거나.트레이스 메시지는 도움이 됩니다만, 이 경우는 전혀 해롭습니다.

트레이스 출력을 발견하자마자 배운 교훈:경우에 따라서는 에러 메시지를 당분간 억제하는 것이 추가 피해를 방지하기 위한 유용한 정지 갭 대책입니다.

나는 그것이 수업 디자인이 나쁜 경우라고 생각하지 않는다.이 오류 자체는 PDOException(MySQL 5.6에서 5.7로 이동하는 타임스탬프 문제)에 의해 트리거되었습니다.이 문제는 PHP에 의해 디폴트로 모든 것이 에러 로그에 덤프되었습니다.

일반적으로 다른 코멘트에서 설명한 모든 이유로 @ 연산자를 사용하는 것은 아니지만, 이 경우 에러 로그를 통해 문제가 적절히 해결될 때까지 신속하게 조치를 취할 수 있었습니다.

스크립트가 느려지기 때문에 모든 것을 억제하고 싶은 것은 아닙니다.

또한 php.ini와 스크립트 내에서도 오류를 제거할 수 있습니다(단, 라이브 환경에서 오류를 기록하고 php에서 오류를 기록할 때만 이 작업을 수행합니다).

<?php
    error_reporting(0);
?>

정보는 php.ini 버전을 사용하여 해제할 수 있습니다.

@를 사용한 에러 억제에 유효한 사용 예라고 생각되는 것이 있습니다.

PHP 5.6.something을 실행하는 시스템과 PHP 7.3.something을 실행하는 시스템이 있습니다.양쪽에서 정상적으로 동작하는 스크립트를 원하지만, PHP 5.6에는 존재하지 않는 것이 있기 때문에 random_compat과 같은 폴리필을 사용하고 있습니다.

내장 함수를 사용하는 것이 항상 가장 좋기 때문에 다음과 같은 코드가 있습니다.

if(function_exists("random_bytes")) {
    $bytes = random_bytes(32);
} else {
    @include "random_compat/random.php"; // Suppress warnings+errors
    if(function_exists("random_bytes")) {
        $bytes = random_bytes(32);
    } else if(function_exists('openssl_random_pseudo_bytes')) {
        $bytes = openssl_random_pseudo_bytes(4);
    } else {
        // Boooo! We have to generate crappy randomness
        $bytes = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',64)),0,32);
    }
}

폴리필로의 폴백은 에러나 경고를 생성해서는 안 됩니다.필요한 polyfill을 로드한 후 기능이 있는지 확인하고 있습니다.심지어 폴백으로 가는 예비역도 있다.그리고 폴백으로 폴백으로.

수 .include (예: 사용)file_exists따라서 경고를 억제하고 효과가 있는지 확인하는 방법밖에 없습니다.적어도 이 경우에는요.

존재하지 않는 어레이 키를 자동으로 증가시키는 사용 예를 한 가지 생각할 수 있습니다.

$totalCars = [];

$totalCars['toyota']++; // PHP Notice:  Undefined index: toyota

@$totalCars['toyota']++;
// [
//    "toyota" => 2,
// ]

커스텀 에러 처리 기능을 사용하고 있어, 에러(아마도 기존의 에러)를 억제하는 경우는, 이 방법을 사용합니다.에러 핸들러가 설정되어 있는 경우, 에러를 억제할 수 없기 때문에, 이 콘텍스트에서는 「@」를 사용하는 것은 좋은 방법이 아닙니다.

3개의 함수를 쓰고 이렇게 불러주세요.

# supress error for this statement
supress_error_start();  
$mail_sent = mail($EmailTo, $Subject, $message,$headers);
supress_error_end(); #Don't forgot to call this to restore error.  

function supress_error_start(){
    set_error_handler('nothing');
    error_reporting(0);
}

function supress_error_end(){
    set_error_handler('my_err_handler');
    error_reporting('Set this to a value of your choice');
}

function nothing(){ #Empty function
}

function my_err_handler('arguments will come here'){
      //Your own error handling routines will come here
}

제 경험상 에러 억제는 미래의 개발자들에게 또 다른 악습일 뿐이며, 에러의 복잡성을 숨기고, 에러 로그를 방지하는 예외와는 달리 가능한 한 피해야 합니다.그러나 "만약 그렇다면, 어떤 상황에서 이것을 사용하겠습니까?"라는 원래의 질문에 대답합니다.

예외 오류를 발생시키지 않고 오류 변수를 개체와 함께 유지하거나 오류를 기록하기 위해 글로벌 변수를 사용하거나 오류를 인쇄하기 위해 모두 함께 사용하여 잘못된 오류를 처리하는 레거시 코드나 라이브러리에 대해 사용해야 합니다.

mysqli 개체를 예로 들어 보겠습니다.

new mysqli($this->host, $this->username, $this->password, $this->db);

는 접속 시 발생시키지 이만을 저장합니다.오류만 저장합니다.mysqli::errno ★★★★★★★★★★★★★★★★★」mysli::error

현대의 코딩에서 발견한 하나의 해결책은 추악한 오류 메시지(특히 디버깅모드가 꺼진 프로덕션 서버에서는 아무에게도 도움이 되지 않음)를 억제하는 것이었습니다.그 대신 개발자는 자신의 예외를 발생시켜야 합니다.이는 현대의 관행을 고려하여 코더가 오류를 보다 빠르게 추적하는 데 도움이 됩니다.

  $this->connection = @new mysqli($this->host, $this->username, $this->password, $this->db);
  if($this->connection->connect_errno)
      throw new mysqli_sql_exception($this->connection->error);

의 을 알 수 .@개발 서버에서 오류 표시가 켜지는 것을 방지하기 위한 기호입니다.

을 사용하다이렇게 해서 제가 사용할 수 있었다.@그리고 동시에 나는 오류를 숨기지 않았고 무엇이 오류인지 추측하지도 않았다.

올바르게 사용한다면 그것은 정당하다고 말할 것이다.

DOMDocument 객체로 처리할 HTML 파일을 로드하려고 할 때 사용합니다.HTML에 문제가 있는 경우... 그리고 어떤 웹사이트가 적어도 문제가 없는 경우...DOMDocument -> 부하HTMLFile()은 @로 억제하지 않으면 오류를 발생시킵니다.이것이 내가 PHP에서 HTML 스크래퍼를 만드는 데 성공한 유일한 방법이다(아마도 더 나은 방법이 있을 것이다).

언급URL : https://stackoverflow.com/questions/136899/suppress-error-with-operator-in-php