728x90

PHP 함수를 구현한 코드에 버그가 있다고는 생각도 못했다.

그런데 입력값이 공백인 경우와 입력값이 0인 경우 동일한 결과를 처리하고 있다는 걸 알고 깜짝 놀랐다.

 

<?php
ini_set("display_startup_errors"1);
ini_set("display_errors"1);
error_reporting(E_ALL);
 
$aaa = "";
$bbb = 0;
 
if(empty($aaa&& empty($bbb)){
    echo 'aaa, bbb 둘다 값없슴<br/>';
else {
    echo 'aaa : '.$aaa.', bbb : '.$bbb.'<br/>';
}
 
echo 'aaa : '.Filter($aaa).'<br/>';
echo 'bbb : '.Filter($bbb).'<br/>';
 
function Filter($data){
    if(empty(trim($data))) {
        if($data === 0return 0;
        return '';
    }
    // 이하 함수 내용은 생략
}
?>

 

if문에서 둘다 입력값이 없는 경우를 체크하기 위한 함수를 구현하고, 0이 입력된 값을 체크했는데 원하지 않는 결과가 나왔다.

그래서 Filter 함수에서 data가 정확하게 0 을 입력한 경우에는 0을 반환하도록 코드를 보완했다.

 

if($keyword) {

 

}

를 할때에도 값이 0이 들어오면 false 로 인식되어 실제 값을 인식하지 못하는 현상이 발생한다.

그러므로 if(strlen($keyword)<1) 로 길이를 체크하여 길이가 없는 경우를 입력 값이 없는 경우로 간주하도록 구현하여 오류 발생을 방지하는 것도 방법이다.

 

 

 

블로그 이미지

Link2Me

,
728x90

자바스크립트 Ajax 로 받은 결과에 문제가 발생한 경우 디버깅하려고 하면 애로사항이 생겨 어려움을 겪을 수 있다.

이를 해결할 방법으로 시도해 본 사항을 적어둔다.

POST 변수로 넘기는 변수가 30개 이상된다고 하고, 파일 B에서 변수를 받아서 체크하고 함수를 이용하여 결과를 도출하는 경우에 어디에서 에러가 발생했는지 찾기가 어려워서 아래 코드를 활용하여 해결했다.

 

$('#panel_content').load(link, function() {
 
    $('#checkdone-submit').on('click',function(e){
        e.preventDefault(); // a 링크, submit 실행 방지
        var params = $('#baseChkRegister').serialize();
        $.post('baseChkRst.php',params,function(msg){
            //alert(msg);
            console.log(msg);
            var uri = $('#urlPath').attr('url-path');
            if(msg == 1){
                alert('등록되었습니다.');
            } else if(msg == 2){
                alert('수정했습니다.');
            } else {
                alert('정보 변경에 실패했습니다.');
            }
        });
    });
 
});
 

 

위와 같이 ajax 결과로 문제 해결이 되면 Good 이지만 그렇지 못한 경우에는 baseChRst.php 파일에서 넘겨받은 POST변수를 직접 코드의 INPUT 을 기록하고 코드를 한줄 한줄 검증하는 것으로 해결해야 할 수도 있다.

 

baseChkRst.php 파일 예시

파일 A에서 파일 B(baseChrRst.php)로 값을 전송하여 var_dump($_POST) 로 출력하면 console.log 에서 확인할 수 있다.

확인한 결과를 $test 에 복사하여 붙여넣기 한 이후에 실제 파일 A에서 값을 넘겼다고 가정하고 파일 B에서 에러가 발생한 코드를 echo 문으로 검증하는 과정을 거치면 문제가 된 코드를 찾아낼 수 있다.

$_POST 로 넘기는 변수의 개수가 30개 이상인 경우라서 에러를 찾기 힘들어서 찾아서 해결한 방법이다.

<?php
ini_set("display_startup_errors"1);
ini_set("display_errors"1);
error_reporting(E_ALL);
 
// javascript console.log 로 찍어서 확인한 메시지가 아래와 같다.
// 이 메시지를 배열로 저장해서 값이 넘어온 것을 가지고 디버깅을 할 목적이다.
$test = 'array(4) {
  ["uid"]=>
  string(1) "0"
  ["userID"]=>
  string(7) "hgd1806"
  ["userNM"]=>
  string(9) "홍길동"
  ["memo"]=>
  string(13) "이상없슴."
}';
 
var_export(unvar_dump($test)); // 화면 출력으로 결과 확인시
 
$_POST = unvar_dump($test); // 실제 변수로 넘어온 데이터라고 가정하고 코드 검증
extract($_POST); // 변수명만 추출하여 데이터 검증처리시 사용
 
// 실제 하단에 사용할 코드는 생략
 
// var_dump($_POST) 로 결과를 받아서 console.log 메시지를 다시 배열로 만들어 주기 위한 함수
function unvar_dump($str) {
    if (strpos($str"\n"=== false) {
        //Add new lines:
        $regex = array(
            '#(\[.*?\]=>)#',
            '#(string\(|int\(|float\(|array\(|NULL|object\(|})#',
        );
        $str = preg_replace($regex"\n\1"$str);
        $str = trim($str);
    }
    $regex = array(
        '#^\040*NULL\040*$#m',
        '#^\s*array\((.*?)\)\s*{\s*$#m',
        '#^\s*string\((.*?)\)\s*(.*?)$#m',
        '#^\s*int\((.*?)\)\s*$#m',
        '#^\s*bool\(true\)\s*$#m',
        '#^\s*bool\(false\)\s*$#m',
        '#^\s*float\((.*?)\)\s*$#m',
        '#^\s*\[(\d+)\]\s*=>\s*$#m',
        '#\s*?\r?\n\s*#m',
    );
    $replace = array(
        'N',
        'a:\1:{',
        's:\1:\2',
        'i:\1',
        'b:1',
        'b:0',
        'd:\1',
        'i:\1',
        ';'
    );
    $serialized = preg_replace($regex$replace$str);
    $func = function($match) {
        return 's:'.strlen($match[1]).':"'.$match[1].'"';
    };
    $serialized = preg_replace_callback(
        '#\s*\["(.*?)"\]\s*=>#'
        $func,
        $serialized
    );
    $func = function($match) {
        return 'O:'.strlen($match[1]).':"'.$match[1].'":'.$match[2].':{';
    };
    $serialized = preg_replace_callback(
        '#object\((.*?)\).*?\((\d+)\)\s*{\s*;#'
        $func
        $serialized
    );
    $serialized = preg_replace(
        array('#};#''#{;#'), 
        array('}''{'), 
        $serialized
    );
 
    return unserialize($serialized);
}
?>
 

 

unvar_dump 함수 코드 출처 : https://stackoverflow.com/questions/3531857/convert-var-dump-of-array-back-to-array-variable

 

Convert var_dump of array back to array variable

I have never really thought about this until today, but after searching the web I didn't really find anything. Maybe I wasn't wording it right in the search. Given an array (of multiple dimensions...

stackoverflow.com

 

 

 

블로그 이미지

Link2Me

,
728x90

코드를 수정하다보니 SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data 이런 에러메시지가 나온다.


아무리 찾아도 문제가 없는데 말이다.

변수명을 변경했는데 캐싱된 데이터가 계속 잘못된 정보를 서버로 보내면서 벌어진 현상이다.


크롬 브라우저에서 Disable cache 를 하지 않아서 생긴 현상이다. 윽ㅠㅠㅠㅠㅠㅠ

블로그 이미지

Link2Me

,
728x90

mysql_query() expects parameter 2 to be resource, boolean given in


DB 데이터 업데이트 작업을 하는데 MySQLi 가 아닌 MySQL 로 하다보니 위와 같은 메시지가 나온다.


이런 메시지가 나오는 것은 MySQL 연결 정보가 제대로 연결되지 않아서다.


$db= mysql_connect("localhost","root","user_password");
mysql_select_db("dbname", $db);

블로그 이미지

Link2Me

,
728x90

Web 사이트 개발을 하고 나서 취약점을 점검해볼 수 있는 TOOL 을 설치해봤다.

www.zaproxy.org/download/

에서 다운로드 한다.

 

 

지자체 사이트는 시험삼아 넣어봤더니 결과를 한참 늦게 피드백을 준다.

내 호스팅 사이트는 결과를 엄청 빠르게 보여준다.

보안 설정이 취약한 부분이 뭔지 결과를 경고 메시지로 보여준다.

 

Secure Coding 관련으로 공부를 좀 하고 경고 메시지가 없어지도록 해야겠다.

블로그 이미지

Link2Me

,
728x90

PHP 서버와 안드로이드 클라이언트간에 연동 테스트를 하는데 결과가 표시되지 않는다.

서버를 직접 실행해서 메시지를 확인해보니...

Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given

와 같은 메시지가 나온다.


이 메시지 나오는 원인은 SQL 문의 칼럼이 잘못된 곳이 있을 경우에 나온다.

echo $sql.'<br />'; 로 결과를 화면에 찍어보고 잘못 오타가 난 칼럼 또는 칼럼에 전혀 없는 명칭을 사용하고 있지는 않는지 확인해보는 것이 좋다.

블로그 이미지

Link2Me

,
728x90

<?php
class DBController {
    private $host = 'localhost';
    private $database = 'test';
    private $userid = 'root';
    private $password = 'autoset';
    protected $db; // 변수를 선언한 클래스와 상속받은 클래스에서 참조할 수 있다.

    public function __construct() {
        $this->db = $this->connectDB();
        // construct 메소드는 객체가 생성(인스턴스화)될 때 자동으로 실행되는 특수한 메소드다.
    }

    function __destruct(){
        mysqli_close($this->connectDB());
        //mysqli_close($this->db);
    }

    private function connectDB() {
        $dbconn = mysqli_connect($this->host, $this->userid, $this->password, $this->database);
        mysqli_set_charset($dbconn, "utf8"); // DB설정이 잘못되어 euc-kr 로 되어 있으면 문제가 됨
        if (mysqli_connect_errno()) {
           printf("Connect failed: %s\n", mysqli_connect_error());
           exit();
        } else {
          return $dbconn;
        }
    }

}//end dbClass
?>

<?php
class LoginClass extends DBController {
// class 자식클래스 extends 부모클래스
    // 회원 가입 여부 체크
    public function isUserExisted($u) {
        if(!isset($u) || empty($u)) {
            return '-1';
        } else {
            $sql ="SELECT count(userID) from members WHERE userID='".$u."'";
            $result = mysqli_query($this->db, $sql);
            if($row = mysqli_fetch_array($result)){
                return $row[0]; // 미가입이면 0 반환, 가입이면 1 반환
            } else {
                return -1;
            }
        }
    }
}//end class LoginClass
?>


PHP 함수를 만들어서 사용하는 경우 개수를 체크하기 위해 count(*)를 사용한다.
이 경우 반환값은 정수일까? String(문자열)일까?

아래 코드를 직접 실행해보면 결과가 나온다.
변수 타입 확인은 getttype 함수 또는 var_dump 함수로 확인할 수 있다.
<?php
$userID ='jsk005@naver.com';
include_once 'dbController.php';
require_once 'loginClass.php';
$c = new LoginClass();
$rs = $c->isUserExisted($userID);

if($rs === 1){
    echo 'Variable Type is Integer<br />';
} else if($rs == '1'){
    echo '
Variable Type is string <br />';
    echo gettype($rs);
    //var_dump($rs);
}
?>

결과는 정수 타입이 아니라 String 이다.


블로그 이미지

Link2Me

,
728x90

APM(Apache + PHP + MySQL) 소스설치 방식으로 PHP 버전은 5.6.30 버전을 설치했더니

Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead  메시지가 뜨면서 접속이 제대로 안된다.


기존 모든 소스를 수정해야 하나, APM 소스 설치를 다시 해야 하나 고민되어 검색을 했더니 이렇게 하라고 나온다.


$link = @mysql_connect($db_server,$db_user_name,$db_password);

@ 를 앞에 붙이라고 나온다.

오류 제어 연산자(@) : PHP의 코드가 오류가 있을 때 오류 메시지를 무시하도록 하는 연산자

오류 메시지를 어떤 상황에서든 출력하지 않도록 하고자 할 때 사용하는 연산자이다.


<?php
error_reporting(E_ALL ^ E_DEPRECATED);

이렇게 추가하라고 알려주기도 한다.


원인이 The mysql_* functions has been deprecated as of PHP 5.5.0 버전 이상부터 나오는 현상이란다.


근본적으로는 mysqli_* 방식이나 PDO 방식으로 변경해야 되는데 전부 수정하기에는 엄두가 나지 않는다.

일단 앞에 오류제어 연산자 @를 붙이는 방법으로 임시 조치하여 사용해보고 있다.


PHP 5.4.6 에서 정상 동작하는 코드가 PHP 5.6.30 에서 동작되지 않는 것이 있었는데 코드를 세부적으로 살펴보니 낮은 버전에서는 MySQL 연결 문법을 대략 생략해도 동작되던게 동작되지 않는 증상이라 수정처리했더니 잘 동작한다.


APM 소스 설치시 옵션에 따라서 약간씩 설치가 되는 사이트도 있고 아닌 곳도 있어서 설치하면서 고생을 좀 했다.

phpize 를 이용해서 미처 설치하지 못한 옵션을 추가하는 방법도 알게되고 난 후에는 여러모로 APM 소스 설치가 편리하기는 하더라.

PHP 5.6.30 에서 속도가 좀 더 개선(?)된 느낌이 들기는 한다.


다시 정리하자면

기존 코드 수정을 최소화하면서 이용하는 방법은

mysql_connect( $this->host, $this->user, $this->pass ) or die('error connection');

@mysql_connect( $this->host, $this->user, $this->pass ) or die('error connection');

로 해주면 없어진다.

mysql_connect( $this->host, $this->user, $this->pass ) or die('error connection');

@mysql_connect( $this->host, $this->user, $this->pass ) or die('error connection');

로 해주면 없어진다.



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


제대로 변경하려면

연동에 사용되는 함수를 찾아서 전부 변경해줘야 한다.

$connect = mysqli_connect('localhost', 'user', 'password', 'dbname');


replace all mysql_* functions into mysqli_* functions


//PHP 5.4 o earlier (DEPRECATED)
$con = mysql_connect($host,$user,$password) or exit("Connection Error");
$conn = mysql_select_db($db, $con);

mysql_query("set names utf8");


//PHP 5.5 (New method)
$conn =  mysqli_connect($host,$user,$password,$db);



PDO (PHP Data Objects) 방식으로 연동

- 연동방식으로 만든 함수를 많이 수정해야만 정상동작되는거 같다. 기존 함수를 변환시 주의할 점이 좀 있다.

$conn = new PDO($hostDb, $user, $password);
또는

$conn = new PDO('mysql:host=localhost;dbname={$dbname};charset=utf8', $user, $password);

로 한다.


블로그 이미지

Link2Me

,
728x90

ajax 로 form 값을 전송하는데 정상적으로 처리가 안된다.

이것 때문에 몇시간을 삽질했다. 네이버 검색하면 메시지 자체가 검색되지 않는다.

구글링을 하면 검색결과가 많은데 제대로 된 해결책을 찾기가 쉽지 않다.


error

 parsererror,SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

 증상

 error 메시지는 나오는데 DB 테이블에는 정보가 업데이트되고 있음

 원인

 함수에서 warning 메시지 발생으로 인한 문제로 판명됨

 조치

 아래에 자세히 기술


$.ajax({
    url: 'memberInfo.php',
    type: 'POST',
    data: {
        uid:$("#memberuid").val(),
        userNM:$("#memberName").val(),
        mobileNO:$("#memberMobile").val()
    },
    dataType: "json",
    success: function (response) {
        if(response.result == 1){
            alert('수정 완료');
            location.replace('index.php'); // 화면 갱신
        }
        if(response.result == 0){
            alert('수정 실패');
        }
    },
    error: function(jqXHR, textStatus, errorThrown){
        alert("arjax error Type : " + textStatus + "\n" + errorThrown);
    }
});


데이터가 정상적으로 넘어가는지 확인하려고 alert 으로 일일이 찍어봤다.

정상적으로 잘 넘어간다.


그래서 memberInfo.php 파일에서 변수가 넘어왔다고 가정하고 직접 실행을 해봤으나, 정상적이다.

테스트로 값을 넘기는 거라 임의의 값으로 처리하면서 DB 저장되는 건 주석처리를 해버렸다.

<?php
if(!isset($_SESSION)) {
    session_start();
}

//$_POST['userNM'] ='홍길동';
//$_POST['mobileNO'] ='010-123-7777';

if (empty($_POST)) {
    echo json_encode(array('result'=>'0'));
    exit;
} else {
    @extract($_POST);
    include_once $_SERVER['DOCUMENT_ROOT'].'/_core/config/config.php';
    include_once $_SERVER['DOCUMENT_ROOT'].'/_core/config/dbconnect.php'; // db접속
    include_once $_SERVER['DOCUMENT_ROOT'].'/phpclass/dbClass.php';
    $u=new MySQLiDbClass;

    $mobileNO = preg_replace("/[^0-9]/", "", $mobileNO); //전화번호 숫자이외에 제거
    $QSET ="userNM='".$userNM."',";
    $QSET.="mobileNO='".$mobileNO."'";
    $u->getDbUpdate('member_id',$QSET,"uid=".$uid);
    echo json_encode(array('result'=>'1'));
}

?>


DB에는 제대로 저장되는지 확인해봤다.

DB 테이블에는 정상적으로 update가 되고 있다.

단지 화면상으로 결과를 돌려주는 부분에서 에러를 발생시키고 있다.


문제 해과정

1단계 :

dataType: "json" 을 dataType: "text" 로 변경하고

success : function(response) { alert(response); 를 추가한다.

그러면 아래와 같이 출력되는 메시지를 전부 보여준다.


<br />
<b>Warning</b>:  mysqli_query() expects at least 2 parameters, 1 given in <b>C:\AutoSet9\public_html\workspace\phpclass\dbClass.php</b> on line <b>184</b><br />
<br />
<b>Warning</b>:  mysqli_query() expects at least 2 parameters, 1 given in <b>C:\AutoSet9\public_html\workspace\phpclass\dbClass.php</b> on line <b>185</b><br />
{"result":"1"}


2단계 :

Warning 이 발생한 부분을 찾아서 수정해준다.


//DB업데이트
function getDbUpdate($table,$set,$where){
    global $dbconn;
    mysqli_query($dbconn,'set names utf8');
    mysqli_query($dbconn,'set sql_mode=\'\'');
    $sql ="update ".$table." set ".$set.($where?' where '.$this->getSqlFilter($where):'');
    mysqli_query($dbconn,$sql);
    return 1;
}


3단계 :

dataType: "json" 으로 원복 조치


$rs=$d->getDbUpdate('member_id',$QSET,"uid=".trim($uid));
if($rs == 1){
    echo json_encode(array('result'=>'1'));
}else{
    echo json_encode(array('result'=>'0'));
}   


원인은 mysqli_query 부분을 제대로 입력하지 않아서 경고메시지가 출력되었던 것이었다.

결과값이 1이면 처리하라는 if문의 결과값만 돌려줄 줄 알았는데 그게 아니었다.

화면에 출력되는 경고메시지가 있다보니, echo json_encode(array('result'=>'1')); 메시지 이외의 값도 결과로 돌려주었었나 보다.

함수 하나를 이용하더라도 완벽하게 만들어서 이용해야 한다는 걸 다시 한번 느꼈다.

블로그 이미지

Link2Me

,
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

,
728x90

배열이 아닌 것을 배열 변수로 만들어서 검색결과를 알고 싶은 경우가 있다.

검색조건(search_item) 은 이름, 전화번호, 부서명 등으로 지정하고

검색어를 넣어서 배열에서 검색결과 처리를 하고자 할 경우 로직의 예이다.


첫번째 행의 변수는 $search[0] 로 할당하고, 두번째 행

$search_keyword = isset($_REQUEST['searchValue']) ? urldecode($_REQUEST['searchValue']) : '';


$search[1] = isset($_REQUEST['searchValue']) ? urldecode($_REQUEST['searchValue']) : '';

로 하면 배열 선언이 없는 상태라서 에러가 발생한다.


이렬 경우 보통은

php.ini 에서

error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE

로 처리하라고 되어 있다.

개발하면서 이 옵션은

error_reporting = E_ALL

로 설정해서 개발을 해야 에러가 발생하는 부분을 전부 화면에 표시를 해주므로 로직상의 문제점을 제거하면서 개발을 할 수 있다.


$search_item = isset($_REQUEST['searchName']) ? $_REQUEST['searchName'] : '';
$search_keyword = isset($_REQUEST['searchValue']) ? urldecode($_REQUEST['searchValue']) : '';

if(strlen($search_keyword) == 0){  // 입력값이 없으면 목록 없음 출력
    echo '<li data-icon="false">';
    echo '<a href="#">목록이 없습니다</a>';
    echo '</li>';
} else {
    // 검색어 값이 존재하면 배열 변수로 저장

    $search = array($search_item,$search_keyword);


    $c=new MemberClass;
    $rs=$c->MemberSearch($search);

    if($rs==0){    // 검색결과가 없으면
        echo '<li data-icon="false">';
        echo '<a href="#">목록이 없습니다.</a>';
        echo '</li>';

    } else { // 검색결과가 있으면
        // 검색결과 처리
    }

}


블로그 이미지

Link2Me

,
728x90

if(!isset($_SESSION['userID']) || empty($_SESSION['userID']) || empty($_GET['uid'])){
    // 세션 및 접속 조건을 만족하지 못하면 (비정상접속)
    // 둘중의 하나를 적어준다.
    echo ("<script>alert('정상적인 접속이 아닙니다');window.top.location.replace('index.php');</script>");
    //echo ("<meta http-equiv='Refresh' content='0; URL=index.php'>");
    exit;
}

// 접속 IP 체크는 필요한 경우에 코드를 추가한다.


require_once $_SERVER['DOCUMENT_ROOT'].'/dbconnect.php'; // 데이터베이스 접속


블로그 이미지

Link2Me

,
728x90

echo '<script type="text/javascript">alert("파일을 찾을 수가 없습니다!");</script>';


echo '<script type="text/javascript">alert("txt 파일만 등록할 수 있습니다.");</script>';


이렇게 값을 직접 적는 것은 쉽게 해결했는데 값을 받아서 넣는 것에서 원하는 결과가 나오지 않는다.

기본기 부족으로 소소한 곳에서 헤메는 것을 방지하기 위해 기록해둔다.


$msg = '신규'.number_format($newcount).'건, 갱신'.number_format($upcount).'건, 총'.number_format($total_line).'건 등록되었습니다.';


echo "<script type=\"text/javascript\">alert('$msg');</script>";


echo "<script type=\"text/javascript\">alert(\"$msg\");history.go(-1);</script>";


참고로 PHP 가 얼마나 애를 먹이는 언어인지 참고하면 좋을 거 같아서 링크를 걸어둔다.

http://noraesae.github.io/PHP-a-fractal-of-bad-design-kr/

블로그 이미지

Link2Me

,
728x90

인터넷 검색해서 겨우 겨우 제대로 된 방법을 알아냈다. 인터넷의 좋은 점은 자료가 널려 있다는 것이고 단점은 제대로 된 자료를 찾기가 정말 어렵다는 점이다.

나는 인터넷에서 찾아낸 것을 테스트를 해서 결과를 확인해보고 정리를 하는 편이다.


에러 메시지 출력을 검사할 때는 반드시 잘 동작하는 파일을 기준으로 검사를 먼저 해본 다음에 에러가 발생하는 파일에 적용하는 것이 필요하다.


홈페이지 계정 root 폴더에 존재하는 .htaccess 에 하단 내용을 추가하면 에러메시지가 화면에 출력됨

# vi .htaccess 한 다음에 아래 2줄을 넣어줌.

php_value error_reporting 22527
php_flag display_errors on


를 하니까 홈페이지 모든 화면에 Warning 메시지가 보인다..

form post 로 값을 넘긴 특정한 파일만 검색하는 경우에는 아래 자바스크립트를 넣어서 코드 한줄 한줄 찍어가면서 분석한다. 왜냐하면 form post 로 넘기면 값을 확인하기가 쉽지 않기 때문이다.
echo "<script>alert('$content')</script>";

찍어보고 싶은 변수를 지정하면서 값이 넘어오는지 넘어오지 않는지 확인한다.


코드가 간단한 경우에는 크롬브라우저 개발자 모드로 확인하면 헤더정보, Response 정보 등을 확인할 수 있는데 이런 걸로 분석이 어렵게 만들어진 프레임웍이 있을 수도 있기 때문이다.


코드를 공통 함수에 넣어서 사용한다면 아래처럼 해당 파일에 한줄 넣어주면 된다.

include_once $g['path_core'].'function/string.func.php';


// PHP 디버깅시 사용할 함수
function Err($str)
{
    echo("<script> alert('".$str."');</script>");
}

블로그 이미지

Link2Me

,