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 둘 중에 하나를 선택해서 확인하라.
출처: 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 클릭해 주세요.
'Web 프로그램 > Web 디버깅' 카테고리의 다른 글
PHP 5.5.0 이상에서 Deprecated: mysql_connect() (2) | 2017.05.25 |
---|---|
[ajax 에러] JSON.parse: unexpected character at line 1 column 1 of the JSON data (0) | 2017.02.18 |
Undefined index 에러 해결방법 (0) | 2016.09.10 |
비정상 접속 체크 (0) | 2016.05.04 |
PHP alert 창 띄우기 (0) | 2016.04.10 |