728x90

PHP를 배울 때 가장 먼저 알아야 할 사항이 디버깅 요령인데 독학으로 배워 게시글 기록을 보면 순서없이 중구난방이다.

최근에서야 디버깅을 이렇게 하면 도움이 되겠다 싶은 걸 적어본다.

 

변수지정 기초지식 : http://link2me.tistory.com/523 참조

 

파일 A에서 파일 B로 데이터를 넘길 때 파일 B에서 확인하는 방법이다. (의미를 모르면 http://link2me.tistory.com/1110 부터 읽어라)

 

파일A에서 form 으로 넘긴 변수(method="post")가 제대로 잘 넘어오는지 확인하는 방법

- 파일 A란?  PHP Form, Android, C# 등 값을 POST (또는 GET) 방식으로 넘기는 코드를 의미함.

 

<?php
var_dump($_POST); // var_dump 또는 print_r 둘 중에 하나를 선택해서 확인하라.

echo '<pre>';print_r($_POST);echo '</pre>';

출처: https://link2me.tistory.com/1130 [소소한 일상 및 업무TIP 다루기]

echo '<pre>';print_r($_POST);echo '</pre>'; // 가독성이 좋게 하려면 print_r 과 pre 태그를 사용하면 된다.

exit; // 이 명령어 다음에 적힌 코드들은 실행하지 말고 빠져나가라.

       // 변수가 넘어오는지 테스트 목적이므로 아래 코드 실행 방지 목적
?>

로 하면 배열로 넘어온 값을 확인할 수 있다.

print_r() : 변수 정보를 알기 쉬운 형식으로 출력한다.

var_dump() : 기본적으로 print_r()함수와 같지만 데이터 유형 등 출력되는 정보가 많다.

var_export() : 그대로 PHP 스크립트로서 해석할 수 있는 형식으로 출력한다.

 

직접 테스트해 보고자 한다면 로그인 폼 전송예제 http://link2me.tistory.com/1479 에서 파일을 받으면 된다.

 

코드 작성시 체크 포인트

<?php
// 에러 메시지를 찾고자 할 때 추가할 코드 (개발 시에는 반드시 아래 3줄을 추가해서 하라)

ini_set("display_startup_errors", 1);
ini_set("display_errors", 1);
error_reporting(E_ALL);

// 운용 모드에서는

// error_reporting(0); // 모든 오류를 표시하지 않는다.
if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){ // 반드시 이 한줄을 넣어라.

    // 보안에 안전하려면
    // POST 방식으로 보낸 데이터가 있는지 체크
    echo '<pre>';print_r($_POST);echo '</pre>';
}

?>



<?php
// 보안을 고려한 코드 작성시 (보통은 php.ini 에 해당항목을 수정한다)

ini_set('error_reporting', E_ALL | E_STRICT);
ini_set('display_startup_errors', 'Off');
ini_set('display_errors', 'Off');

ini_set('log_errors', 'On');
?>
Notice: Undefined index: 라고 경고메시지가 뜨는 것이 싫을 경우에는

코드 상단에 error_reporting(E_ALL ^ E_NOTICE); 를 추가해주면 된다.
error_reporting(0); // 모든 오류를 표시하지 않는다. (운용환경에서는 이걸 사용하라)

하지만 개발을 할 때에는 경고 메시지도 모두 출력되도록 하여 에러를 완전히 잡는 것이 중요하다.
 //페이지 변수 설정
$page = isset($_GET['page'])? trim($_GET['page']) : 1;
파일 B에서 코드 구현시 파일 A에서 값이 넘어오지 않을 때에도 동작되도록 코드를 구현해야 할 경우가 있다.
이런 상황에서 삼항연산자로 간단하게 했더니 경고 메시지가 출력된다.
Notice: Undefined variable:

$ym=$_GET['ym'] ? $_GET['ym'] : date("Ym"); //현재 년월
 
이걸 정확하게
if(isset($_GET['ym'])){
    $ym = $_GET['ym'];
} else {
    $ym = date("Ym");
}
로 수정해줘야 경고메시지가 없어진다는 걸 확인했다.

 
결국 isset 으로 변수 설정 유무 검사를 추가해야만 경고 메시지가 없어진다.

$ym=isset($_GET['ym']) ? $_GET['ym'] : date("Ym"); //현재 년월
잘 만들어진 빌더를 분석하다보면 isset 처리를 하지 않아 경고메시지가 출력되는 걸 종종 발견하게 된다.

기존 코드를 유지보수 하다가 수정한 것이 있어서 http://link2me.tistory.com/1085 에 적어둔게 있다.

 

경고메시지를 php.ini 파일을 수정해서 나오지 않도록 하는 방법을 알아보자.

error_reporting 키워드를 검색어로 찾아서 아래와 같이 수정한다.

 

error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE
- E_DEPRECATED : 향후 PHP 버전에서 동작을 하지 않을 수도 있는 코드에 대해서 로그를 발생 시킨다
- E_NOTICE : 초기화 되지 않은 변수를 사용했을 때 에러 로그를 생성한다.

 

php.ini 파일을 수정했으면 아파치를 재시작하면 변경한 내용으로 적용된다.

php.ini 에 추가하면 에러 버그를 못잡을 수도 있으니 해당 파일 상단에 아래와 같이 처리하는 걸 권장한다.

 

완벽하게 코드를 만드는 습관을 들이는게 중요하다.
사소한 것을 하나씩 무시하다보면 중요한 곳에서 버그가 생길 수 있다.

mysqli_query 에 에러가 발생할 경우 아래와 같이 원인을 찾을 수 있게 코딩하는 것도 좋다.

 

<?php
$sql = "SQL statement here";
$result = mysqli_query($dbconn,$sql) or trigger_error("SQL: $sql - Error: ".mysqli_error(), E_USER_ERROR);
?>

 

SQL 문이 정상적으로 잘 생성되었는지 여부를 확인할 수 있게 echo 문으로 출력해보는 것도 필요하다.

결국 PHP구문을 통해서 생성한 SQL 문이 DB에 저장되도록 하는 것이기 때문이다.

echo $sql; 로 생성된 SQL 구문을 직접 DB에 넣었을 때 에러없이 잘 들어가면 SQL문은 에러가 없다는 뜻이다.

SQL문에서 에러가 생기는 경우도 종종있다. 문법이 잘못되었거나, 오타가 있거나 등등...

//DB데이터 ARRAY -> 테이블에 출력할 데이터 배열
function getDbArray($table,$where,$flddata,$orderby,$rowsPage,$curPage){
    $sql = 'select '.$flddata.' from '.$table.($where?' where '.$this->getSqlFilter($where):'').($orderby?' order by '.$orderby:'').($rowsPage?' limit '.(($curPage-1)*$rowsPage).', '.$rowsPage:'');
    echo $sql; // SQL 문이 정상적으로 실행되는지 여부 파악 목적
    if($result = mysqli_query($this->db,$sql)){
        return $result;
    }
}
 

echo $sql; 출력으로 웹 브라우저 화면상에서 나온 SQL 문을 직접 DB에서 쿼리해보는 것이 가장 좋은 해결 방법이다.

link2me.tistory.com/1917 은 phpMyAdmin 인데 phpMyAdmin 은 잘 다루면 엄청 편리하고, 보안을 신경써야 한다.

 

 

MySQLi 절치지향 방식으로 만든 함수를 PDO 함수로 컨버팅하면서 함수 이상 유무를 확인하는 과정에서 아래와 같이 테스트를 했다.

함수의 결과가 배열일 수도 있고 그냥 String 일 수도 있어서 in_array 함수를 이용하여 배열과 문자열을 구분하여 출력하도록 하면 원하는 결과를 깔끔하게 확인할 수 있다.

 <?php
require_once 'path.php';
require_once $g['path_class'].'dbconnect.php';
require_once $g['path_class'].'adminClass.php';
$a = new adminClass;

$codeID = 4;
$rs = $a->StaffPositionMNCount($codeID);
if(is_array($rst)){
    echo '<pre>';print_r($rs);echo '</pre>';
} else {
    echo $rs;
}
?>

 

 

ajax, jQuery 등을 사용하는 경우 메시지 분석이 어려울 때가 있다.

그래서 echo '<script type="text/javascript">alert("'.$errline.'");</script>'; 로 에러를 확인하지만 문제는 복사가 안된다.

 

echo '<script type="text/javascript">window.prompt("메세지를 복사해주세요", "'.$sql.'");</script>';

로 하면 메시지 복사가 가능해진다.

대부분 에러가 발생하는 원인을 찾으려면 SQL 문을 직접 DB에 입력해보면 에러 메시지가 뭔지 쉽게 확인할 수 있다.

 

 

이제 파일 B 코드 구현 사항이 문제가 없는지 확인하는 방법이다.

즉, Android 와 통신하는데 PHP 코드에는 문제가 없는지 확인하는 방법이라고 봐도 된다.

아래 코드는 로그인 처리하는 파일 B(a.loginChk.php) 코드 예제이다.

초보자의 코드라면 loginClass.php 없이

보통은 여기에서

$sql = "select * from tableName where 조건";

$result=mysqli_query($db,$sql);

$row=mysqli_fetch_array($result);

와 같은 처리를 하는데, 이걸 loginClass Class에 함수로 만들어서 모아둔 것이라고 보면 된다.

 

== 정상적인 코드
<?php
// 파일을 직접 실행하는 비정상적 동작을 방지 하기 위한 목적
if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    if(isset($userID) && !empty($userID) && isset($password) && !empty($password)) {
        include_once 'dbController.php';
        require_once 'loginClass.php';
        $c = new LoginClass();
        $user = $c->getUser($userID, $password);
        if ($user != false) {
            $_SESSION['userID'] = $user['userID'];
            $_SESSION['userNM'] = $user['userNM'];
            $_SESSION['admin'] = $user['admin'];
            echo json_encode(array('result' => '1'));
        } else {
            echo json_encode(array('result' => '0'));
        }
    }else {// 입력받은 데이터에 문제가 있을 경우
        echo json_encode(array('result' => '-2'));
    }
} else { // 비정상적인 접속인 경우
    echo 0; // a.loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
?>
== 디버깅 코드
<?php
//if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    // $_POST 변수로 넘어온 값이 라고 가정하고 변수에 값을 직접 넣어서 결과가 정상 반환되는지 확인한다.
    $userID = "jsk005";
    $password = "abc1234";
    if(isset($userID) && !empty($userID) && isset($password) && !empty($password)) {
        include_once 'dbController.php';
        require_once 'loginClass.php';
        $c = new LoginClass();
        $user = $c->getUser($userID, $password);
        if ($user != false) {
            $_SESSION['userID'] = $user['userID'];
            $_SESSION['userNM'] = $user['userNM'];
            $_SESSION['admin'] = $user['admin'];
            echo json_encode(array('result' => '1'));
        } else {
            echo json_encode(array('result' => '0'));
        }
    }else {// 입력받은 데이터에 문제가 있을 경우
        echo json_encode(array('result' => '-2'));
    }
/*
} else { // 비정상적인 접속인 경우
    echo 0; // a.loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
*/
?>

 

변수가 많을 때에는 직접 변수를 넘겨서 var_dump 로 출력시키고 console.log 로 출력된 메시지를 복사해서 처리하는 방법이 유용할 수 있다.

참조 : https://link2me.tistory.com/2070

 

도움이 되셨다면 00 클릭해 주세요.

블로그 이미지

Link2Me

,