변수 유효영역
변수의 유효영역은 변수가 정의된 환경을 말합니다. 대부분의 경우 모든 PHP 변수는 한군데의 유효영역만을 갖습니다. 이 한군데의 유효영역은 include되거나 require된 파일로도 확장됩니다. 예를 들면:
<?php
$a = 1;
include 'b.inc';
?>
위 예제코드에서는 include된 b.inc 스크립트안에서도 $a 변수가 사용가능합니다. 하지만, 사용자-선언 함수에서는 로컬 함수 유효영역이 적용됩니다. 함수내에서 사용되는 모든 변수는 기본값으로 로컬 변수 유효영역 안으로 제한됩니다. 예를 들면:
<?php
$a = 1; /* global scope */
function test()
{
echo $a; /* reference to local scope variable */
}
test();
?>
echo 문이 $a 변수의 로컬 버전을 참조하고 이 범위 내에서 값이 할당되지 않았기 때문에 이 스크립트는 출력을 생성하지 않습니다. 로컬 정의에 의해 특별히 재정의되지 않는 한 C의 전역 변수를 함수에 자동으로 사용할 수 있다는 점에서 이것이 C 언어와 약간 다르다는 것을 알 수 있습니다. 이것은 사람들이 실수로 전역 변수를 변경할 수 있다는 몇 가지 문제를 일으킬 수 있습니다. PHP에서 전역 변수는 해당 함수에서 사용하려는 경우 함수 내에서 global으로 선언되어야 합니다.
global 키워드
먼저 global
사용 예:
예제 #1 global 사용
<?php
$a = 1;
$b = 2;
function Sum()
{
global $a, $b;
$b = $a + $b;
}
Sum();
echo $b;
?>
위 스크립느는 "3
"을 출력할 것입니다. $a와 $b를 함수내에서 global로 선언함으로써, 각 변수에 대한 모든 참조는 전역 버전으로 참조될 것입니다. 함순에서 조작되는 전역변수의 수는 제한이 없습니다.
전역 유효영역의 변수에 접근할 수 있는 두번째 방법이 특별 PHP-선언 $GLOBALS 배열을 사용하는 것입니다. 이전 예제코드는 다음과 같이 다시 작성할 수 있습니다:
예제 #2 global 대신 $GLOBALS 사용하기
<?php
$a = 1;
$b = 2;
function Sum()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
Sum();
echo $b;
?>
$GLOBALS 배열은 전역변수명이 key가 되는 연관배열이고 배열의 원소 값이 그 변수의 내용이 됩니다. $GLOBALS이 어떻게 모든 유효영역에서 존재하는지 주의하세요. 이유는 $GLOBALS이 슈퍼전역변수이기 때문입니다. 아래에 슈퍼전역변수의 파워를 설명하는 예제코드를 볼 수 있습니다:
예제 #3 슈퍼글로벌과 범위를 보여주는 예
<?php
function test_superglobal()
{
echo $_POST['name'];
}
?>
메모: 함수 외부에서 global
키워드를 사용하는 것은 오류가 아닙니다. 함수 내부에서 파일이 포함된 경우 사용할 수 있습니다.
정적(static
) 변수 사용하기
변수 범위 지정의 또 다른 중요한 기능은 정적(static) 변수입니다. 정적(static) 변수는 로컬 함수 범위에만 존재하지만 프로그램 실행이 이 범위를 벗어날 때 값을 잃지 않습니다. 다음 예를 고려하십시오.
예제 #4 정적 변수의 필요성을 보여주는 예
<?php
function test()
{
$a = 0;
echo $a;
$a++;
}
?>
이 함수는 호출될 때마다 $a를 0으로 설정하고 0을 인쇄하기 때문에 매우 쓸모가 없습니다. 변수를 증가시키는 $a++는 함수가 종료되자마자 $a 변수가 사라지기 때문에 아무 소용이 없습니다. 현재 카운트를 추적하지 않는 유용한 계산 함수를 만들기 위해 $a 변수를 정적으로 선언합니다.
예제 #5 정적 변수의 사용 예
<?php
function test()
{
static $a = 0;
echo $a;
$a++;
}
?>
이제 $a는 함수의 첫 번째 호출에서만 초기화되고 test()
함수가 호출될 때마다 $a의 값을 인쇄하고 증가시킵니다.
정적 변수는 또한 재귀 함수를 처리하는 한 가지 방법을 제공합니다. 재귀 함수는 자신을 호출하는 함수입니다. 재귀 함수를 무한정 재귀하게 만들 수 있으므로 재귀 함수를 작성할 때 주의해야 합니다. 재귀를 종료하는 적절한 방법이 있는지 확인해야 합니다. 다음의 간단한 함수는 정지할 때를 알기 위해 정적 변수 $count를 사용하여 10까지 재귀적으로 계산합니다.
예제 #6 재귀 함수가 있는 정적 변수
<?php
function test()
{
static $count = 0;
$count++;
echo $count;
if ($count < 10) {
test();
}
$count--;
}
?>
정적 변수에는 상수 표현식의 결과인 값을 할당할 수 있지만 함수 호출과 같은 동적 표현식은 구문 분석 오류를 발생시킵니다.
예제 #7 정적 변수 선언
<?php
function foo(){
static $int = 0; // correct
static $int = 1+2; // correct
static $int = sqrt(121); // wrong (as it is a function)
$int++;
echo $int;
}
?>
메모: 정적 선언은 컴파일 타임에 해결됩니다.
전역(global
) 및 정적(static
) 변수를 사용한 참조
PHP는 참조 측면에서 변수에 대한 정적(static) 및 전역(global) 수정자를 구현합니다. 예를 들어, 전역(global
) 문을 사용하여 함수 범위 내에서 가져온 실제 전역(global) 변수는 실제로 전역 변수에 대한 참조를 생성합니다. 이로 인해 다음 예제에서 해결하는 예기치 않은 동작이 발생할 수 있습니다.
<?php
function test_global_ref() {
global $obj;
$new = new stdclass;
$obj = &$new;
}
function test_global_noref() {
global $obj;
$new = new stdclass;
$obj = $new;
}
test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>
위의 예는 다음을 출력합니다.
NULL object(stdClass)#1 (0) { }
유사한 동작이 정적 문에 적용됩니다. 참조는 정적으로 저장되지 않습니다.
<?php
function &get_instance_ref() {
static $obj;
echo 'Static object: ';
var_dump($obj);
if (!isset($obj)) {
$new = new stdclass;
// Assign a reference to the static variable
$obj = &$new;
}
if (!isset($obj->property)) {
$obj->property = 1;
} else {
$obj->property++;
}
return $obj;
}
function &get_instance_noref() {
static $obj;
echo 'Static object: ';
var_dump($obj);
if (!isset($obj)) {
$new = new stdclass;
// Assign the object to the static variable
$obj = $new;
}
if (!isset($obj->property)) {
$obj->property = 1;
} else {
$obj->property++;
}
return $obj;
}
$obj1 = get_instance_ref();
$still_obj1 = get_instance_ref();
echo "\n";
$obj2 = get_instance_noref();
$still_obj2 = get_instance_noref();
?>
위의 예는 다음을 출력합니다.
Static object: NULL Static object: NULL Static object: NULL Static object: object(stdClass)#3 (1) { ["property"]=> int(1) }
이 예는 정적 변수에 대한 참조를 할당할 때 &get_instance_ref()
함수를 두 번째로 호출할 때 기억되지 않는다는 것을 보여줍니다.