function foo () {
global $var;
// rest of code
}
내 작은 PHP 프로젝트에서는 보통 절차적인 방식으로 진행합니다. 일반적으로 시스템 구성을 포함하는 변수가 있으며 함수에서이 변수에 액세스해야 할 때 global $var;
.
이것은 나쁜 습관입니까?
답변
사람들이 다른 언어로 전역 변수에 대해 이야기 할 때 그것은 PHP에서하는 것과는 다른 것을 의미합니다. 변수는 PHP에서 실제로 전역 적이 지 않기 때문 입니다. 일반적인 PHP 프로그램의 범위는 하나의 HTTP 요청입니다. 세션 변수는 일반적으로 많은 HTTP 요청을 포함하기 때문에 실제로 PHP “전역”변수보다 더 넓은 범위를 갖습니다.
종종 (항상?) 다음과 preg_replace_callback()
같은 메서드에서 멤버 함수를 호출 할 수 있습니다 .
preg_replace_callback('!pattern!', array($obj, 'method'), $str);
자세한 내용은 콜백 을 참조하십시오 .
요점은 객체가 PHP에 고정되어 어떤면에서 어색함을 유발한다는 것입니다.
다른 언어의 표준이나 구조를 PHP에 적용하는 것에 지나치게 신경 쓰지 마십시오. 또 다른 일반적인 함정은 모든 것 위에 객체 모델을 붙임으로써 PHP를 순수한 OOP 언어로 바꾸는 것입니다.
다른 무엇과 마찬가지로 “글로벌”변수, 절차 적 코드, 특정 프레임 워크 및 OOP를 사용하십시오. 이는 의미가 있고, 문제를 해결하고, 작성해야하는 코드의 양을 줄이거 나, 생각 때문이 아니라 유지 관리가 쉽고 이해하기 쉽기 때문입니다. 당신은해야합니다.
답변
주의 깊게 사용하지 않으면 전역 변수를 사용하면 문제를 찾기가 더 어려워 질 수 있습니다. PHP 스크립트를 요청하고 일부 함수에 존재하지 않는 배열의 인덱스에 액세스하려고한다는 경고가 표시되었다고 가정 해 보겠습니다.
액세스하려는 배열이 함수에 로컬 인 경우 함수에서 실수를했는지 확인합니다. 함수 입력에 문제가있을 수 있으므로 함수가 호출 된 위치를 확인합니다.
그러나 해당 배열이 전역 인 경우 전역 변수를 사용하는 모든 위치를 확인해야하며 그뿐만 아니라 전역 변수에 대한 참조가 액세스되는 순서를 파악해야합니다.
코드 조각에 전역 변수가있는 경우 해당 코드의 기능을 분리하기가 어렵습니다. 기능을 분리하려는 이유는 무엇입니까? 따라서 테스트하고 다른 곳에서 재사용 할 수 있습니다. 코드가있는 경우 테스트 할 필요가없고 재사용 할 필요가없는 경우 전역 변수를 사용하는 것이 좋습니다.
답변
나는 클레 투스에 동의합니다. 두 가지를 추가합니다.
- 접두사를 사용하여 즉시 글로벌로 식별 할 수 있습니다 (예 : $ g_).
- 한 자리에 선언하고 코드 전체에 뿌리지 마십시오.
안부, 돈
답변
누가 경험, 대학 학위 및 소프트웨어 공학에 대해 반대 할 수 있습니까? 나 말고. 객체 지향 단일 페이지 PHP 응용 프로그램을 개발할 때 네임 스페이스 충돌에 대해 걱정하지 않고 처음부터 전체를 빌드 할 수 있다는 사실을 알 때 더 재미 있다고 말할뿐입니다. 처음부터 건축하는 것은 많은 사람들이 더 이상하지 않는 일입니다. 그들은 직업, 기한, 보너스 또는 관심을 가질 평판이 있습니다. 이러한 유형은 위험이 큰 사전 빌드 된 코드를 너무 많이 사용하는 경향이 있으므로 전역 변수를 전혀 사용할 위험이 없습니다.
프로그램의 전역 영역에서만 사용 되더라도 전역 변수를 사용하는 것은 나쁠 수 있습니다.하지만 재미 있고 무언가를 만들고 싶은 사람들을 잊지 마십시오 .
이것이 전역 네임 스페이스에서 몇 개의 변수 (<10)를 사용하는 것을 의미한다면, 프로그램의 전역 영역에서만 사용됩니다. 그래, 그래, MVC, 의존성 주입, 외부 코드, 어쩌구, 어쩌구, 어쩌구. 그러나 코드의 99.99 %를 네임 스페이스와 클래스에 포함하고 외부 코드가 샌드 박스 처리 된 경우 전역 변수를 사용하면 세계가 끝나지 않습니다 (반복합니다. 세계가 끝나지 않습니다).
일반적으로 전역 변수를 사용하는 것이 좋지 않다고 말하지 않습니다 . 프로그램의 전역 영역 밖에서 전역 변수 (플래그 등)를 사용하는 것은 문제를 요구 하고 (장기적으로) 상태를 쉽게 추적 하지 못할 수 있기 때문에 부적절 하다고 말할 수 있습니다. 또한 더 많이 배울수록 사용과 관련된 버그를 추적하는 “즐거움”을 경험하게되므로 전역 변수에 대한 의존도가 낮아질 것입니다 . 이것만으로도 같은 문제를 해결할 다른 방법을 찾도록 장려 할 것입니다. 우연히도 이것은 PHP 사용자를 네임 스페이스와 클래스 (정적 멤버 등) 사용 방법을 배우는 방향으로 밀어 붙이는 경향이 있습니다.
컴퓨터 과학 분야는 방대합니다. 우리가 그것을 나쁘게 표시 하기 때문에 모든 사람이 무언가를하지 못하도록 겁 을 주면, 그들은 레이블 뒤에있는 이유를 진정으로 이해하는 재미를 잃게됩니다.
필요한 경우 전역 변수를 사용하고 이러한 변수 없이도 문제를 해결할 수 있는지 확인하십시오. 충돌, 테스트 및 디버깅은 문제에 대한 설명뿐만 아니라 문제의 실제 특성을 자세히 이해할 때 더 많은 것을 의미합니다.
답변
종료 된 SO 문서 베타에서 재 게시 됨
이 문제를 다음 의사 코드로 설명 할 수 있습니다.
function foo() {
global $bob;
$bob->doSomething();
}
첫 번째 질문은 분명한 것입니다.
어디
$bob
에서 왔습니까?
헷갈 리나요? 좋은. 방금 글로벌이 혼란스럽고 나쁜 습관으로 간주되는 이유를 배웠습니다. 이것이 실제 프로그램이라면, 다음 번 재미는 모든 인스턴스를 추적 $bob
하고 올바른 프로그램을 찾기를 바라는 것 $bob
입니다. 더 나쁜 것은 다른 사람이 가서 정의하면 $bob
(또는 해당 변수를 잊고 재사용 한 경우) 코드가 손상 될 수 있습니다 (위 코드 예제에서 잘못된 객체가 있거나 객체가 전혀 없으면 치명적인 오류가 발생할 수 있습니다). 거의 모든 PHP 프로그램은 코드를 include('file.php');
유지하는 작업 과 같은 코드를 사용 하므로 파일을 더 많이 추가할수록 기하 급수적으로 어려워집니다.
글로벌을 피하려면 어떻게해야합니까?
전역을 피하는 가장 좋은 방법은 Dependency Injection 이라는 철학 입니다. 여기서 필요한 도구를 함수 나 클래스에 전달합니다.
function foo(\Bar $bob) {
$bob->doSomething();
}
이것은 이해하고 유지하기 가 훨씬 쉽습니다. $bob
호출자가 그것을 아는 책임이 있기 때문에 어디에 설정 되었는지 추측 할 수 없습니다 (알아야 할 것을 전달합니다). 더 좋은 것은 전달되는 것을 제한하기 위해 타입 선언 을 사용할 수 있다는 것 입니다. 우리가 알 수 있도록 그 $bob
의 인스턴스 중 하나입니다 Bar
클래스, 또는 아이의 인스턴스 Bar
우리는 우리가 그 클래스의 방법을 사용할 수 있습니다 알고 의미합니다. 표준 자동 로더 (PHP 5.3부터 사용 가능)와 결합하여 이제 Bar
정의 된 위치를 추적 할 수 있습니다 . PHP 7.0 이상에는 확장 된 유형 선언이 포함되어 있으며, 여기서 int
또는 같은 스칼라 유형을 사용할 수도 있습니다 string
.
답변
같이:
global $my_global;
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']
나쁜 습관입니다 (WordPress처럼 $pagenow
) … 흠
간결하게 :
$my-global = 'Transport me between functions';
PHP 오류 이지만 :
$GLOBALS['my-global'] = 'Transport me between functions';
오류 가 아닙니다 . hypen은 .NET 과 같은 “일반적인”사용자 선언 변수와 충돌하지 않습니다$pagenow
. 대문자 사용은 사용중인 슈퍼 글로벌을 나타내며 코드에서 쉽게 발견 하거나 파일에서 찾기로 추적 합니다.
단일 솔루션에 대한 모든 클래스를 빌드하기 위해 게으른 경우 하이픈을 사용합니다.
$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';
그러나 더 광범위한 사용의 경우 ONE 전역을 배열로 사용합니다.
$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';
후자는 나를 위해 “콜라 라이트”목표 또는 사용에 대한 좋은 연습 이며 매번 일부 데이터를 “캐시”하기 위해 단일 클래스로 어수선하게하는 대신입니다. 내가 틀렸거나 여기에서 어리석은 것을 놓친 경우 의견을 말하십시오 …