외부 소스에서 온 변수

외부 소스에서 온 변수

폼, 쿠키, URL 쿼리 등 외부에서 들어온 데이터가 PHP에서 어떻게 변수로 변신하는지 알아봐요. $_POST, $_GET, $_COOKIE 같은 슈퍼글로벌의 동작 원리를 다룹니다.

출처: Variables From External Sources

본문

HTML 폼 (GET과 POST)

폼이 PHP 스크립트로 제출되면 그 폼의 정보는 자동으로 스크립트에서 사용할 수 있게 돼요. 이 정보에 접근하는 방법은 몇 가지가 있는데, 예를 들면 다음과 같습니다.

<form action="foo.php" method="post">
    Name:  <input type="text" name="username" /><br />
    Email: <input type="text" name="email" /><br />
    <input type="submit" name="submit" value="Submit me!" />
</form>

HTML 폼에서 데이터에 접근하는 방법은 딱 두 가지뿐이에요. 현재 사용 가능한 방법은 아래에 나열됩니다.

<?php
echo $_POST['username'];
echo $_REQUEST['username'];

GET 폼을 쓰는 것도 마찬가지인데, 대신 적절한 GET 미리 정의 변수를 쓰면 돼요. GET은 QUERY_STRING(URL에서 '?' 뒤의 정보)에도 적용됩니다. 예를 들어 http://www.example.com/test.php?id=3$_GET['id']로 접근할 수 있는 GET 데이터를 담고 있어요. $_REQUEST도 참고하세요.

참고: 변수 이름에 있는 점(.)과 공백(space)은 밑줄(_)로 변환돼요. 예를 들어 <input name="a.b" />$_REQUEST["a_b"]가 됩니다.

PHP는 폼 변수 문맥에서 배열도 이해해요(관련 FAQ 참고). 예를 들어 관련된 변수들을 묶을 수도 있고, 여러 개 선택 가능한 select 입력에서 값을 가져오는 데 쓸 수도 있죠. 폼을 자기 자신에게 POST하고 제출 시 데이터를 출력해보는 예제를 볼게요.

<?php
if ($_POST) {
    echo '<pre>';
    echo htmlspecialchars(print_r($_POST, true));
    echo '</pre>';
}
?>
<form action="" method="post">
    Name:  <input type="text" name="personal[name]" /><br />
    Email: <input type="text" name="personal[email]" /><br />
    Beer: <br />
    <select multiple name="beer[]">
        <option value="warthog">Warthog</option>
        <option value="guinness">Guinness</option>
        <option value="stuttgarter">Stuttgarter Schwabenbräu</option>
    </select><br />
    <input type="submit" value="submit me!" />
</form>

참고: 외부 변수 이름이 유효한 배열 문법으로 시작하면, 뒤따르는 문자는 조용히 무시돼요. 예를 들어 <input name="foo[bar]baz">$_REQUEST['foo']['bar']가 됩니다.

IMAGE SUBMIT 변수 이름

폼을 제출할 때 일반 제출 버튼 대신 이미지를 사용할 수 있어요. 사용자가 이미지 어딘가를 클릭하면, 폼이 sub_xsub_y라는 두 개의 추가 변수와 함께 서버로 전송됩니다. 이 변수들은 이미지 안에서 사용자가 클릭한 좌표를 담고 있어요. 경험 많은 분들은 브라우저가 실제로 보내는 변수 이름이 밑줄이 아니라 점(.)을 담고 있다는 걸 눈치채실 거예요. 하지만 PHP는 점을 자동으로 밑줄로 변환합니다.

<input type="image" src="image.gif" name="sub" />

HTTP 쿠키

PHP는 » RFC 6265에서 정의하는 HTTP 쿠키를 투명하게 지원해요. 쿠키는 원격 브라우저에 데이터를 저장해 재방문 사용자를 추적하거나 식별하는 메커니즘입니다. setcookie() 함수로 쿠키를 설정할 수 있어요. 쿠키는 HTTP 헤더의 일부라서, SetCookie 함수는 브라우저로 어떤 출력이 보내지기 전에 호출돼야 합니다. 이건 header() 함수와 같은 제약이에요. 쿠키 데이터는 그 후 $_COOKIE 같은 적절한 쿠키 데이터 배열과 $_REQUEST에서 사용할 수 있습니다. 자세한 내용과 예제는 setcookie() 매뉴얼 페이지를 참고하세요.

참고: PHP 7.2.34, 7.3.23, 7.4.11부터 각각 보안상의 이유로 들어오는 쿠키의 이름은 더 이상 url-decoding 되지 않습니다.

하나의 쿠키 변수에 여러 값을 할당해야 한다면, 배열로 할당할 수 있어요. 예를 들면 다음과 같습니다.

<?php
setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
setcookie("MyCookie[bar]", 'Testing 2', time()+3600);

그러면 두 개의 별도 쿠키가 만들어지지만 스크립트 안에서는 MyCookie가 하나의 배열이 됩니다. 하나의 쿠키에 여러 값을 한 번에 설정하려면, 우선 그 값을 serialize()explode()로 처리하는 걸 고려해보세요.

쿠키는 경로(path)나 도메인(domain)이 다르지 않는 한 브라우저에서 같은 이름의 이전 쿠키를 교체한다는 점을 주의하세요. 그래서 쇼핑 카트 애플리케이션에서는 카운터를 유지하고 넘겨줄 수 있어요.

<?php
if (isset($_COOKIE['count'])) {
    $count = $_COOKIE['count'] + 1;
} else {
    $count = 1;
}
setcookie('count', $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);

들어오는 변수 이름의 점

일반적으로 PHP는 변수가 스크립트로 전달될 때 그 이름을 바꾸지 않아요. 하지만 점(period, full stop)은 PHP 변수 이름에서 유효한 문자가 아니라는 점을 알아둬야 합니다. 그 이유를 봅시다.

<?php
$varname.ext;  /* invalid variable name */

파서가 보는 것은 $varname이라는 변수, 그다음 문자열 결합 연산자, 그리고 그다음 베어스트링(barestring, 즉 알려진 키워드나 예약어와 일치하지 않는 따옴표 없는 문자열) 'ext'입니다. 당연히 의도한 결과가 아니죠.

이런 이유로 PHP는 들어오는 변수 이름의 모든 점을 자동으로 밑줄로 바꾼다는 점을 기억하는 게 중요해요.

변수 타입 결정

PHP는 변수의 타입을 결정하고 (일반적으로) 필요할 때 변환하므로, 특정 변수가 어떤 타입인지 항상 명확한 건 아니에요. PHP에는 변수의 타입을 알아내는 몇 가지 함수가 있습니다. gettype(), is_array(), is_float(), is_int(), is_object(), is_string() 같은 것들이죠. Types 챕터도 참고하세요.

HTTP는 텍스트 프로토콜이라서, $_POST$_GET 같은 슈퍼글로벌 배열로 들어오는 대부분의(전부는 아니더라도) 내용은 문자열로 남아 있어요. PHP는 값을 특정 타입으로 변환하려고 시도하지 않습니다. 아래 예제에서 $_GET["var1"]에는 문자열 "null"이, $_GET["var2"]에는 문자열 "123"이 담겨 있어요.


/index.php?var1=null&var2=123

변경 이력

버전 설명
7.2.34, 7.3.23, 7.4.11 보안상의 이유로 들어오는 쿠키의 이름이 더 이상 url-decoding 되지 않습니다.

더 알아보기