[php] 참조 : 변수 범위 란 무엇이며, “정의되지 않은 변수”오류의 위치 및 위치에서 액세스 할 수있는 변수는 무엇입니까?
참고 : 이것은 PHP에서 변수 범위를 다루기위한 참조 질문입니다. 이 패턴에 맞는 여러 질문 중 하나를이 질문의 복제본으로 닫으십시오.
PHP에서 “가변 범위”란 무엇입니까? 한 .php 파일의 변수는 다른 .php 파일에 액세스 할 수 있습니까? 때때로 “정의되지 않은 변수” 오류가 발생하는 이유는 무엇 입니까?
답변
“가변 범위”란 무엇입니까?
변수에는 “범위”또는 “액세스 할 수있는 위치”가 제한되어 있습니다. 애플리케이션 어딘가에$foo = 'bar';
한 번 쓴다고 해서 애플리케이션 내 다른 곳 에서 참조 할 수있는 것은 아닙니다 . 변수$foo
$foo
에는 유효 범위 내에서 특정 범위가 있으며 동일한 범위의 코드 만 변수에 액세스 할 수 있습니다.
PHP에서 범위는 어떻게 정의됩니까?
매우 간단합니다 : PHP는 함수 범위를 가지고 있습니다 . 그것은 PHP에 존재하는 유일한 종류의 범위 구분자입니다. 함수 내부의 변수는 해당 함수 내에서만 사용할 수 있습니다. 함수 외부의 변수는 함수 외부에서는 사용할 수 있지만 함수 내부에서는 사용할 수 없습니다. 이것은 PHP에 특별한 범위가 있다는 것을 의미합니다 : 글로벌 범위. 함수 외부에서 선언 된 모든 변수는이 전역 범위 내에 있습니다.
예:
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
}
$foo
에 글로벌 , 범위 $baz
(A)에있다 지역 범위 안에 myFunc
. 내부 코드 만에 myFunc
액세스 할 수 $baz
있습니다. 외부 코드 만에 myFunc
액세스 할 수 $foo
있습니다. 어느 쪽도 다른쪽에 접근 할 수 없습니다 :
<?php
$foo = 'bar';
function myFunc() {
$baz = 42;
echo $foo; // doesn't work
echo $baz; // works
}
echo $foo; // works
echo $baz; // doesn't work
범위 및 포함 된 파일
파일 경계는 범위를 분리 하지 않습니다 .
a.php
<?php
$foo = 'bar';
b.php
<?php
include 'a.php';
echo $foo; // works!
include
다른 코드에 적용되는 것과 동일한 규칙이 d 코드에 적용됩니다 function
. 별도의 범위 만 있습니다. 범위 목적을 위해 복사 및 붙여 넣기 코드와 같은 파일을 포함하는 것을 고려할 수 있습니다.
c.php
<?php
function myFunc() {
include 'a.php';
echo $foo; // works
}
myFunc();
echo $foo; // doesn't work!
위의 예에서 a.php
inside가 포함 된 경우 내부 myFunc
의 모든 변수 a.php
에는 로컬 함수 범위 만 있습니다. 그것들 이 전역 범위에있는 것으로 보인다고 해서 a.php
반드시 그것이 의미하는 것은 아니며 실제로 코드가 포함 / 실행되는 컨텍스트에 달려 있습니다.
함수와 클래스 내부의 함수는 어떻습니까?
모든 새로운 function
선언은 새로운 범위를 소개합니다. 그것은 간단합니다.
함수 내부의 (익명) 함수
function foo() {
$foo = 'bar';
$bar = function () {
// no access to $foo
$baz = 'baz';
};
// no access to $baz
}
클래스
$foo = 'foo';
class Bar {
public function baz() {
// no access to $foo
$baz = 'baz';
}
}
// no access to $baz
범위는 무엇입니까?
범위 문제를 다루는 것은 성가신 것처럼 보일 수 있지만 복잡한 응용 프로그램을 작성하려면 제한된 변수 범위가 필수적입니다! 선언 한 모든 변수를 응용 프로그램 내 다른 곳에서 사용할 수 있다면 변경 내용을 추적하는 실제 방법없이 변수 전체를 단계별로 실행하게됩니다. 변수에 부여 할 수있는 현명한 이름이 너무 많기 때문에 변수 ” $name
“를 여러 곳에서 사용하고 싶을 것입니다 . 앱에서이 고유 한 변수 이름을 한 번만 가질 수 있다면 변수의 고유성을 확인하고 잘못된 코드에서 잘못된 변수를 변경하지 않도록하기 위해 정말 복잡한 이름 지정 체계를 사용해야합니다.
관찰 :
function foo() {
echo $bar;
}
범위가 없으면 위의 기능은 무엇을합니까? 어디 $bar
에서 왔습니까? 어떤 주가 있습니까? 심지어 초기화 되었습니까? 매번 확인해야합니까? 유지 관리 할 수 없습니다. 어느 것이 우리를 …
교차 범위 경계
올바른 방법 : 변수 전달 및 전달
function foo($bar) {
echo $bar;
return 42;
}
변수 $bar
가 함수 범위로 명시 적으로이 범위에 들어옵니다. 이 함수를 살펴보면 작동하는 값의 출처가 명확합니다. 그런 다음 명시 적으로 값을 반환 합니다. 호출자는 함수가 작동하는 변수와 반환 값의 위치를 알 수 있습니다.
$baz = 'baz';
$blarg = foo($baz);
변수의 범위를 익명 함수로 확장
$foo = 'bar';
$baz = function () use ($foo) {
echo $foo;
};
$baz();
익명 함수는 명시 적으로 $foo
주변 범위를 포함합니다. 이것은 전역 범위 와 동일하지 않습니다 .
잘못된 방법 : global
앞에서 언급했듯이 전역 범위는 다소 특별하며 함수는 명시 적으로 변수를 가져올 수 있습니다.
$foo = 'bar';
function baz() {
global $foo;
echo $foo;
$foo = 'baz';
}
이 함수는 전역 변수를 사용하고 수정합니다 $foo
. 이러지 마! (당신이 정말로 정말로 당신이하고있는 일을 정말로 알고 있지 않다면,하지 마십시오!)
이 함수의 모든 호출자는 다음과 같습니다.
baz(); // outputs "bar"
unset($foo);
baz(); // no output, WTF?!
baz(); // outputs "baz", WTF?!?!!
이 함수 에 부작용 이 있다는 표시는 없지만 아직 있습니다. 일부 함수는 계속 전역 상태를 수정 하고 필요로하므로 엉 키게됩니다 . 함수는 상태 비 저장 이되기를 원하며 , 입력에 대해서만 작용하고 정의 된 출력을 반환하지만 여러 번 호출합니다.
가능한 한 어떤 방식 으로든 전역 범위를 사용하지 않아야합니다. 가장 확실하게 전역 범위에서 변수를 로컬 범위로 “풀링”해서는 안됩니다.
답변
함수 범위 내에서 정의 된 변수는 외부에서 액세스 할 수 없지만 해당 함수가 완료된 후에는 해당 값을 사용할 수 없습니다. PHP는 static
정적 메소드와 속성을 정의하기 위해 객체 지향 PHP에서 널리 사용되는 잘 알려진 키워드를 가지고 있지만 static
정적 변수를 정의하기 위해 함수 내에서 사용될 수도 있습니다.
‘정적 변수’는 무엇입니까?
정적 변수는 프로그램 실행이이 범위를 벗어날 때 값을 잃지 않는 경우 함수 범위에 정의 된 일반 변수와 다릅니다. 정적 변수를 사용하는 다음 예제를 고려하십시오.
function countSheep($num) {
static $counter = 0;
$counter += $num;
echo "$counter sheep jumped over fence";
}
countSheep(1);
countSheep(2);
countSheep(3);
결과:
1 sheep jumped over fence
3 sheep jumped over fence
6 sheep jumped over fence
우리가 정의 $counter
하지 않으면 static
매번 에코 값은 $num
함수에 전달 된 매개 변수 와 동일 합니다. 를 사용 static
하면 추가 해결 방법없이이 간단한 카운터를 만들 수 있습니다.
정적 변수 사용 사례
- 결과적인 함수 호출 사이에 값을 저장합니다.
- 매개 변수로 전달할 방법이 없거나 목적이없는 경우 재귀 호출간에 값을 저장합니다.
- 일반적으로 한 번 검색하는 것이 더 나은 값을 캐시합니다. 예를 들어, 서버에서 변경 불가능한 파일을 읽은 결과입니다.
트릭
정적 변수는 로컬 함수 범위에만 존재합니다. 정의 된 함수 외부에서는 액세스 할 수 없습니다. 따라서 다음에 해당 함수를 호출 할 때까지 값이 변경되지 않도록 할 수 있습니다.
정적 변수는 스칼라 또는 스칼라 식으로 만 정의 할 수 있습니다 (PHP 5.6부터). 여기에 다른 값을 지정하면이 기사가 작성된 시점에서 필연적으로 오류가 발생합니다. 그럼에도 불구하고 다음 코드 줄에서 그렇게 할 수 있습니다.
function countSheep($num) {
static $counter = 0;
$counter += sqrt($num);//imagine we need to take root of our sheep each time
echo "$counter sheep jumped over fence";
}
결과:
2 sheep jumped over fence
5 sheep jumped over fence
9 sheep jumped over fence
정적 함수는 같은 클래스의 객체의 메소드간에 ‘공유’됩니다. 다음 예제를 보면 이해하기 쉽습니다.
class SomeClass {
public function foo() {
static $x = 0;
echo ++$x;
}
}
$object1 = new SomeClass;
$object2 = new SomeClass;
$object1->foo(); // 1
$object2->foo(); // 2 oops, $object2 uses the same static $x as $object1
$object1->foo(); // 3 now $object1 increments $x
$object2->foo(); // 4 and now his twin brother
이것은 같은 클래스의 객체에서만 작동합니다. 객체가 다른 클래스 (다른 클래스로 확장)에서 온 경우 정적 변수의 동작은 예상대로입니다.
정적 변수가 함수 호출간에 값을 유지하는 유일한 방법입니까?
함수 호출간에 값을 유지하는 또 다른 방법은 클로저를 사용하는 것입니다. 클로저는 PHP 5.3에서 도입되었습니다. 즉, 함수 범위 내의 일부 변수 집합에 대한 액세스를 다른 익명 함수로 제한 할 수 있습니다. 클로저 변수에 있으면 구조화 된 프로그래밍에서 ‘클래스 상수'(값으로 클로저로 전달 된 경우) 또는 ‘개인 속성'(참조로 전달 된 경우)과 같은 OOP 개념을 모방 할 수 있습니다.
후자는 실제로 정적 변수 대신 클로저를 사용할 수 있습니다. 사용할 것은 항상 개발자의 결정에 달려 있지만 정적 변수는 재귀 작업을 할 때 확실히 유용하며 개발자가 주목할 가치가 있음을 언급해야합니다.
답변
나는 기존의 것들과 PHP 매뉴얼 이 이것의 대부분을 설명하는 훌륭한 일을 하기 때문에 질문에 대한 완전한 대답을 게시하지 않을 것 입니다.
그러나 누락 된 하나 개의 주제는이었다 슈퍼 전역 을 포함하여 일반적으로 사용되는 $_POST
, $_GET
, $_SESSION
, 등이 변수가없이, 어떤 범위에 항상 사용할 수 있습니다 배열 인 global
선언.
예를 들어,이 함수는 PHP 스크립트를 실행하는 사용자의 이름을 인쇄합니다. 변수는 문제없이 함수에 사용 가능합니다.
<?php
function test() {
echo $_ENV["user"];
}
“글로벌이 나쁘다”라는 일반적인 규칙은 일반적으로 PHP에서 오용하지 않는 한 “글로벌은 나쁘지만 슈퍼 글로벌은 괜찮습니다”로 수정됩니다. (이러한 모든 변수는 쓰기 가능하므로 실제로 끔찍한 경우 종속성 주입을 피하는 데 사용할 수 있습니다.)
이러한 변수는 존재하지 않을 수 있습니다. 관리자는의 variables_order
지시문 을 사용하여 일부 또는 전부를 비활성화 할 수 php.ini
있지만 일반적인 동작은 아닙니다.
현재 슈퍼 글로벌 목록 :
$GLOBALS
-현재 스크립트의 모든 글로벌 변수$_SERVER
-서버 및 실행 환경에 대한 정보$_GET
-요청에 사용 된 HTTP 메소드에 관계없이 URL의 쿼리 문자열에 전달 된 값$_POST
–application/x-www-form-urlencoded
또는multipart/form-data
MIME 유형으로 HTTP POST 요청에 전달 된 값$_FILES
multipart/form-data
-MIME 유형으로 HTTP POST 요청에 전달 된 파일$_COOKIE
-현재 요청과 함께 전달 된 쿠키$_SESSION
-PHP에 의해 내부적으로 저장된 세션 변수$_REQUEST
-일반적으로$_GET
와$_POST
때로는 조합$_COOKIES
. 내용은의request_order
지침 에 따라 결정됩니다php.ini
.$_ENV
-현재 스크립트의 환경 변수