MVC를 사용할 때 PHP에서 오류 처리 throw /

최근에 Codeigniter를 많이 사용하고 있지만 신경에 걸리는 한 가지는 오류를 처리하고 사용자에게 표시하는 것입니다. 지저분하지 않고 오류를 처리하는 데 결코 능숙하지 않았습니다. 내 주요 관심사는 사용자에게 오류를 반환 할 때입니다.

함수에서 0 또는 1을 반환 한 다음 if / else를 사용하여 오류를 처리하는 대신 예외 및 throw / catch 예외를 사용하는 것이 좋습니다. 따라서 사용자에게 문제를보다 쉽게 ​​알릴 수 있습니다.

나는 예외를 피하는 경향이있다. 몇 년 전 대학의 Java 교사는 “예외는 프로덕션 코드에서 디버깅에 더 이상 사용해서는 안된다”고 말했습니다. 그가 거짓말하고 있다는 느낌이 들었습니다.

그러나 예를 들어 데이터베이스에 사용자를 추가하는 코드가 있습니다. 프로세스 중에 데이터베이스 문제, 중복 항목, 서버 문제 등과 같이 둘 이상의 문제가 발생할 수 있습니다. 등록하는 동안 문제가 발생하면 사용자는 이에 대해 알아야합니다.

MVC 프레임 워크를 사용하고 있음을 염두에두고 PHP에서 오류를 처리하는 가장 좋은 방법은 무엇입니까?



답변

함수에서 0 또는 1을 반환 한 다음 if / else를 사용하여 오류를 처리하는 대신 예외 및 throw / catch 예외를 사용하는 것이 좋습니다. 따라서 사용자에게 문제를보다 쉽게 ​​알릴 수 있습니다.

아니, 아니!

예외와 오류를 혼용하지 마십시오. 예외는 예외입니다. 오류가 아닙니다. 사용자에게 제품 수량을 입력하도록 요청하고 사용자가 “hello”를 입력하면 오류입니다. 예외는 아닙니다. 사용자의 잘못된 입력을 보는 데 예외가 없습니다. 입력을 확인할 때와 같이 예외가 아닌 경우에 예외를 사용할 수없는 이유는 무엇입니까? 다른 사람들은 이미 그것을 설명하고 입력 검증에 대한 올바른 대안을 보여주었습니다.

이것은 또한 사용자가 예외에 신경 쓰지 않고 예외표시하는 것은 비우호적이고 위험하다는 것을 의미 합니다. 예를 들어, SQL 쿼리를 실행하는 동안 예외가 발생하면 쿼리 자체가 드러납니다. 그러한 메시지를 모든 사람에게 보여줄 위험을 감수 하시겠습니까?

데이터베이스 문제, 중복 항목, 서버 문제 등과 같이 둘 이상의 문제가 발생할 수 있습니다. 등록하는 동안 문제가 발생하면 사용자가 이에 대해 알아야합니다.

잘못된. 사용자로, 난 정말 걱정하지 않는다 등 I 데이터베이스 문제, 중복 된 항목을 알 필요가 없습니다 당신의 문제. 내가 알아야 할 것은 이미 존재하는 사용자 이름을 입력 한 것입니다. 이미 말했듯이, 잘못된 입력은 예외가 아닌 오류를 유발해야합니다.

이러한 오류를 출력하는 방법은 무엇입니까? 상황에 따라 다릅니다. 이미 사용중인 사용자 이름의 경우 양식을 제출하기 전에 사용자 이름이 이미 사용되었다고 말하는 작은 빨간색 플래그가 사용자 이름 근처에 표시되고 싶습니다. JavaScript가 없으면 제출 후 동일한 플래그가 나타나야합니다.

AJAX 가능 오류의 예

다른 오류의 경우 오류가있는 전체 페이지를 표시하거나 사용자에게 문제가 있음을 알리는 다른 방법 (예 : 메시지가 표시되면 페이지 상단에서 사라짐)을 선택하십시오. 문제는 프로그래밍보다 사용자 경험 과 더 관련이 있습니다 .

프로그래머의 관점에서 오류 유형에 따라 다른 방식으로 오류가 전파됩니다. 예를 들어, 사용자 이름이 이미 사용 된 경우 AJAX 요청 http://example.com/?ajax=1&user-exists=John은 다음을 나타내는 JSON 객체를 반환합니다.

  • 사용자가 이미 존재하고
  • 사용자에게 표시 할 오류 메시지입니다.

두 번째 요점은 중요합니다. JavaScript가 비활성화 된 양식을 제출하고 JavaScript가 활성화 된 중복 사용자 이름을 입력 할 때 동일한 메시지가 표시되도록해야합니다. 서버 측 소스 코드와 JavaScript에서 오류 메시지의 텍스트를 복제하지 않으려 고합니다!

이것은 실제로 Stack Exhange 웹 사이트에서 사용되는 기술입니다. 예를 들어, 본인의 답변을 상향 조정하려고하면 AJAX 응답에 다음과 같은 오류가 표시됩니다.

{"Success":false,"Warning":false,"NewScore":0,"Message":"You can't vote for your own post.",
"Refresh":false}

다른 방법을 선택하고 양식을 채우기 전에 HTML 페이지에서 오류를 사전 설정할 수도 있습니다. 장점 : AJAX 응답으로 오류 메시지를 보낼 필요가 없습니다. 단점 : 접근성은 어떻습니까? CSS없이 페이지를 탐색하면 모든 가능한 오류가 표시됩니다.


답변

함수에서 0 또는 1을 반환 한 다음 if / else를 사용하여 오류를 처리하는 대신 예외 및 throw / catch 예외를 사용하는 것이 좋습니다. 따라서 사용자에게 문제를보다 쉽게 ​​알릴 수 있습니다.

예, 그렇습니다!

깨끗한 코드를 원한다면 거의 독점적으로 예외를 사용해야하며 오류 코드를 사용하지 않아도됩니다. 오류 코드는 의미가 없습니다. 그들은 거의 항상 많은 정보를 공개하지 않는 수치 상수에 묶여 있습니다. 코드를 읽을 수 없게 만들고 오류와 함께 데이터를 전파하기가 어려워집니다.

그러나 예외는 클래스이며 원하는 정보를 포함 할 수 있습니다. 따라서 사용자는 숫자 필드에 ‘abc’와 같은 잘못된 입력을 입력했습니다. 오류 코드를 사용하면 많은 버블 링없이이 정보를 오류 처리기로 전파 할 수 없습니다. 예외가 무료로 제공하는 것. 또한 예외를 사용하면 함수와 메서드에 의미있는 반환 값을 가지면서도 여전히 실패 할 수 있습니다. 더 좋은 점은 예외가 처리하려는 위치에 바로 전파된다는 것입니다. 의미있는 데이터가 포함 된 오류 코드를 위의 처리기 1 ~ 2 개 레이어에 전파해야하는 스파게티 코드의 양을 상상해보십시오.

또한 예외는 오류 코드보다 훨씬 의미 적으로 표현됩니다. 오류 코드는 예외 처리로 인해 코드가 깨끗 해지는 스파게티 코드로 이어집니다.

또한 상태 코드 확인을 잊어 버리기 쉽습니다. Java와 같은 언어에서는 예외 (예 : C #이 누락 된 것)를 처리해야합니다.

MVC 프레임 워크를 사용하고 있음을 염두에두고 PHP에서 오류를 처리하는 가장 좋은 방법은 무엇입니까?

예외를 사용하여 컨트롤러에서 처리하십시오.


답변

이 편리한 작은 수업을 고려하십시오.

class FunkyFile {               

    private $path;
    private $contents = null;

    public function __construct($path) { 
        $this->setPath($path); 
    }

    private function setPath($path) {
        if( !is_file($path) || !is_readable($path) ) 
            throw new \InvalidArgumentException("Hm, that's not a valid file!");

        $this->path = realpath($path);
        return $this; 
    }

    public function getContents() {
        if( is_null($this->contents) ) {
            $this->contents = @file_get_contents( $this->path );
            if($this->contents === false) 
                throw new \Exception("Hm, I can't read the file, for some reason!");                                 
        }

        return $this->contents;            
    }

}

예외를 완벽하게 사용하는 것입니다. 에서 FunkyFile's관점의 경로 중 하나가 유효하지 않은 경우, 또는 situtation를 해결하기 위해 할 수있는 절대적으로 아무것도 없다 file_get_contents실패합니다. 정말 예외적 인 상황;)

그러나 코드 어딘가에서 잘못된 파일 경로를 발견했다는 것을 사용자에게 알 가치가 있습니까? 예를 들면 다음과 같습니다.

class Welcome extends Controller {

    public function index() {

        /**
         * Ah, let's show user this file she asked for
         */                 
        try {
            $file = new File("HelloWorld.txt");
            $contents = $file->getContents();   
            echo $contents;
        } catch(\Exception $e) {
            log($e->getMessage());

            echo "Sorry, I'm having a bad day!"; 
        }                           
    }        
}

사람들에게 당신이 나쁜 하루를 보내고 있다고 말하는 것 외에, 당신의 선택은 다음과 같습니다 :

  1. 폴백

    정보를 얻는 다른 방법이 있습니까? 위의 간단한 예제에서는 가능성이 없지만 마스터 / 슬레이브 데이터베이스 스키마를 고려하십시오. 주인이 응답하지 않았을 수도 있지만, 아마도 아마도 노예가 아직 밖에있을 수도 있습니다 (또는 그 반대).

  2. 사용자의 잘못입니까?

    사용자가 잘못된 입력을 제출 했습니까? 글쎄, 그녀에게 말해. 오류 메시지를 짖거나 오류 메시지를 양식과 함께 제공하여 올바른 경로를 입력 할 수 있습니다.

  3. 네 잘못이야?

    그리고 당신에 의해, 나는 사용자 가 아닌 것을 의미 합니다. 따라서 잘못된 파일 경로를 입력하는 것부터 서버에 잘못되는 것까지 다양합니다. 엄밀히 말하면, 503 HTTP 오류가 발생했습니다 . 서비스를 사용할 수 없습니다. CI에는 show_404()기능이 있으므로 쉽게 구축 할 수 있습니다 show_503().

충고 한마디, 당신은 불량 예외를 고려해야합니다. CodeIgniter는 복잡한 코드이므로 예외가 언제 발생하는지 알 수 없습니다. 마찬가지로 자신의 예외를 잊어 버릴 수 있으며 가장 안전한 옵션은 모든 예외 처리기를 catch하는 것입니다. PHP에서는 set_exception_handler로이를 수행 할 수 있습니다 .

function FunkyExceptionHandler($exception) {
    if(ENVIRONMENT == "production") {
        log($e->getMessage());
        show_503();
    } else {
        echo "Uncaught exception: " , $exception->getMessage(), "\n";
    }   
}

set_exception_handler("FunkyExceptionHandler");

또한 set_error_handler 를 통해 불량 오류를 처리 할 수 ​​있습니다 . 예외와 동일한 처리기를 작성하거나 모든 오류를 변환 ErrorException하여 예외 처리기로 처리 할 수 ​​있습니다.

function FunkyErrorHandler($errno, $errstr, $errfile, $errline) {
    // will be caught by FunkyExceptionHandler if not handled
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}

set_error_handler("FunkyErrorHandler");


답변