코딩짜는 일상

[PHP] 문자열, 배열 주고 받기- addslashes(), urlencode(), serialize() 본문

IT/PHP

[PHP] 문자열, 배열 주고 받기- addslashes(), urlencode(), serialize()

Remily 2022. 4. 22. 00:31
반응형

일단 이야기는 다음과 같습니다.

 

DB에서 조회한 내용들을 List로 보여주는 list.php가 있습니다.
저는 이 내용을 EXCEL로 다운로드하고자 PHPExcel 라이브러리를 사용하는 코드를 작성하였습니다.
그리고 해당 코드가 길어서 따로 분리하고자 별도의 excel_down.php를 만들었는데
이때 조회 조건을 GET으로 넘겨 excel_down.php에서 DB를 조회하게 했습니다.

 

 

이 경우 list.php의 조회 쿼리를 수정하면 excel_down.php도 똑같이 수정해줘야 하는 단점이 있죠.

 

그래서 유지보수를 용이하게 하기 위해 list.php에서 DB를 조회하고
그 결과를 excel_down.php가 넘겨받는 방식으로 바꾸고자 했습니다.

 

 

 


첫번째 시도

조회 쿼리(문자열)를 주고받기

 

list.php는 해당 페이지에 text box, select box 등을 두어 검색 조건을 입력받습니다.

그리고 입력받은 조건으로 DB를 조회할 쿼리를 작성하죠.

 

list.php에서 DB를 조회할 때 썼던 쿼리를

excel_down.php가 똑같이 사용하면 둘의 결과값이 같을 거라는 생각을 했습니다.

$string = " SELECT * FROM member WHERE name LIKE '김%' ORDER BY name ASC; ";
// (예시)성이 김씨인 사람을 조회하는 쿼리

 

 

다만 여기에는 문제가 하나 있습니다.

 

검색조건이 숫자면 상관없지만 문자라면,
작은 따옴표' 또는 큰 따옴표"를 써서 구분해야 합니다.

'김%' // 예시의 이 부분

 

 

문제는 PHP가 이것을 단순히 문장 내용의 일부로써 인식하는 게 아니라

PHP문법의 시작 또는 종결로 인식하고 잘못된 쿼리로 인식한다는 점이죠.

만약 "SELECT * FROM member WHERE name LIKE "김%" ORDER BY name ASC;" 이렇게 작성하면

"SELECT * FROM member WHERE name LIKE "     // 여기는 문자열 1  
김%                                         // 여기는 PHP 코드 또는 변수 (어느 쪽이던 에러)  
" ORDER BY name ASC;"                       // 여기는 문자열 2로 인식합니다.

 

 

그래서 따옴표 앞에 백슬러쉬\를 입력해 이스케이프(Escape) 해줍니다.

$escape_string = addslashes($string);  
// 출력  
// SELECT * FROM member WHERE name LIKE '김%' ORDER BY name ASC;

 

 

그 후 GET이나 POST로 이스케이프한 문자열을 excel_down.php에 전달했다면,

SQL 쿼리에선 \'를 인식하지 못하니 백슬러쉬를 전부 빼줘야겠죠.

$string = stripcslashes($escape_string);  
// 출력  
// SELECT * FROM member WHERE name LIKE '김%' ORDER BY name ASC;

 

 

여담이지만 처음엔 왜 전달받은 문자열에 백슬러쉬\가 섞이는지 알지 못했습니다.

 

앞서 서버를 설치한 사람이 magic_quotes_gpc 설정을 해두어 자동으로 전달받은 문자열이 이스케이프된 것이었죠.

 

[PHP] addslashes(), stripslashes() 그리고, get_magic_quotes_gpc()

addslashes() 함수와 그와 반대되는 stripslashes() 함수 DB 작업을 하기 위해서 쿼리를 작성하게 되는데, 이때 DB 시스템은 작은따옴표 ' 와 큰따옴표 " 그리고 백슬래시 / 그리고, NULL byte 를 문자열을 구

zzaps.tistory.com

 

 

이걸 몰라서 한참을 혼자 해매다가 차선책으로 배열을 주고받으려 시도했습니다.

 

아래 두번째 시도에서 배열 주고 받기가 나오는 이유입니다...

 


추가

 

이 외에도 urlencode()urldecode()를 이용하는 방법dl 있습니다.

_-을 제외한 모든 문자열을 %16진수와 +기호 등으로 바꾸어주죠!

// 문자열 전달을 위해 엔코딩  
$encoding = urlencode($string);

// 전달받은 내용을 문자열로 디코딩  
$string = urldecode($encoding);

 

 

 


두번째 시도

배열을 주고 받기

 

Array  
(  
    [0] => Array  
        (  
            [0] => apple  
            [1] => america  
            [2] => 1000  
        )  
    [1] => Array  
        (  
            [0] => samsung  
            [1] => korea  
            [2] => 500  
        )  
    [2] => Array  
        (  
            [0] => TSMC  
            [1] => taiwan  
            [2] => 250  
        )  
)

 

 

위 배열을 GET 또는 POST로 주고 받은 뒤 출력하면 아래와 같습니다.

Array

 

 

원인을 자세히는 모르겠지만 아마 첫번째 행만 전달되어 Array라고 뜨는 것 같습니다.

 

배열을 GET 또는 POST로 주고 받는 방법을 찾다가 이분의 글을 찾았습니다.

 

POST, GET으로 배열값 받기(직렬화)

간혹 많은 량의 변수 및 데이터를 다른 페이지로 이동시켜서 처리해야할 경우가 많습니다. 이를 위해서 최...

blog.naver.com

 

 

이 분 덕분에 문자열 이스케이프도 알게 되었고 배열의 직렬화가 왜 필요한지도 알게 되었습니다. ㅠㅠ


앞서 배열을 전송하면 가장 첫번째 행인 Array만 전송되는 것을 보셨죠?

그렇기에 배열을 한 줄로 바꿔주는 직렬화 작업이 필요합니다.


물론 배열값에 따옴표가 있을 수 있으니 addslashes() 또는 urlencode() 해줍니다.

$seri_array = urlencode(serialize($array));  
// 직렬화한 다음 엔코딩 해준다

 

 

이것을 POST나 GET으로 넘겨 받았다면,
다시 원래대로 바꿔줘야겠죠?

$array = unserialize(urldecode($seri_array));  
// 보낼 때와 반대로 디코딩 후 직렬화 해제

 

 

 


맺음

 

배열을 주고받아 엑셀을 다운로드하는 코드를 만들었을 때,
조회되는 결과가 100 줄이 넘어가면 트래픽이 쓸데없이 크지 않겠냐는 피드백을 받았습니다.


또 SQL 쿼리문을 주고받을 때,
list.php 에 나온 내용과 엑셀로 다운로드할 내용이 다르면 어쩔 거냐는 피드백도 있었습니다.

 

물론 나름대로 해결책을 찾아 해결했습니다만..
백엔드는 참 많은 걸 고려해야 하고 비판적으로 보는 시야도 갖춰야 하는 것 같습니다ㅎㅎ

반응형