PHP 네임스페이스(namespace)는 PHP 5.3에서 추가되었습니다. C#과 Java를 공부했다면 네임스페이스는 새로운 것이 아닙니다. 그러나 이는 PHP에서 여전히 매우 중요한 의미를 갖습니다.
PHP 네임스페이스는 다음 두 가지 유형의 문제를 해결할 수 있습니다.
사용자가 작성한 코드와 PHP 내부 클래스/함수/상수 또는 타사 클래스/함수/상수 간의 이름 충돌.
소스 코드의 가독성을 높이기 위해 매우 긴 식별자 이름(일반적으로 첫 번째 유형의 문제를 완화하기 위해 정의됨)에 대한 별칭(또는 짧은) 이름을 만듭니다.
기본적으로 모든 상수, 클래스 및 함수 이름은 PHP가 네임스페이스를 지원하기 전과 마찬가지로 전역 공간에 배치됩니다.
네임스페이스는 키워드 네임스페이스를 사용하여 선언됩니다. 파일에 네임스페이스가 포함되어 있으면 다른 모든 코드보다 먼저 네임스페이스를 선언해야 합니다. 구문 형식은 다음과 같습니다.
<?php // 'MyProject' 네임스페이스 네임스페이스에 코드를 정의합니다. MyProject; // ... code...
다음과 같이 동일한 파일에 서로 다른 네임스페이스 코드를 정의할 수도 있습니다.
<?php 네임스페이스 MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }namespace AnotherProject;const CONNECT_OK = 1;class Connection { /* .. . */ }함수 연결() { /* ... */ }?>
단일 파일에 여러 네임스페이스를 정의하는 데 이 구문을 사용하는 것은 권장되지 않습니다. 다음 중괄호 형식의 구문을 사용하는 것이 좋습니다.
<?phpnamespace MyProject { const CONNECT_OK = 1; 클래스 연결 { /* ... */ } function connect() { /* ... */ }}namespace AnotherProject { const CONNECT_OK = 1; . */ } 함수 연결() { /* ... */ }}?>
네임스페이스가 아닌 전역 코드를 네임스페이스 코드와 결합하려면 중괄호 구문만 사용할 수 있습니다. 전역 코드는 이름 없는 네임스페이스 문과 중괄호로 묶어야 합니다. 예를 들면 다음과 같습니다.
<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }}namespace { // 전역 코드 session_start();$a = MyProject connect();echo MyProjectConnection::start();}?>
네임스페이스를 선언하기 전에 유효한 유일한 코드는 소스 파일의 인코딩을 정의하는 선언문입니다. 공백을 포함한 모든 비 PHP 코드는 네임스페이스 선언 앞에 나타날 수 없습니다.
<?phpdeclare(encoding='UTF-8'); //MyProject 네임스페이스에 포함되지 않은 여러 네임스페이스 및 코드 네임스페이스 정의 {const CONNECT_OK = 1;class Connection { /* ... */ }function connect () { / * ... */ }}namespace { // 전역 코드 session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
다음 코드는 구문 오류를 발생시킵니다.
<html><?phpnamespace MyProject; // 네임스페이스 앞에 "<html>"이 나타나면 치명적인 오류가 발생합니다. 네임스페이스는 프로그램 스크립트의 첫 번째 문이어야 합니까?>
디렉터리와 파일 간의 관계와 마찬가지로 PHP 네임스페이스를 사용하면 계층적 네임스페이스 이름을 지정할 수도 있습니다. 따라서 네임스페이스 이름은 계층적 방식으로 정의될 수 있습니다.
<?phpnamespace MyProjectSubLevel; //계층적 단일 네임스페이스 선언 const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
위의 예에서는 상수 MyProjectSubLevelCONNECT_OK, MyProjectSubLevelConnection 클래스 및 MyProjectSubLevelConnect 함수를 만듭니다.
PHP 네임스페이스의 클래스 이름은 세 가지 방법으로 참조될 수 있습니다.
정규화되지 않은 이름 또는 접두사가 없는 클래스 이름( 예: $a=new foo(); 또는 foo::staticmethod();) 현재 네임스페이스가 currentnamespace이면 foo는 currentnamespacefoo로 확인됩니다. foo를 사용하는 코드가 전역 코드이고 어떤 네임스페이스에도 코드를 포함하지 않는 경우 foo는 foo로 확인됩니다. 경고: 네임스페이스의 함수 또는 상수가 정의되지 않은 경우 정규화되지 않은 함수 또는 상수 이름은 전역 함수 또는 상수 이름으로 확인됩니다.
정규화된 이름 또는 $a = new subnamespacefoo(); 또는 subnamespacefoo::staticmethod();와 같은 접두사가 포함된 이름입니다 . 현재 네임스페이스가 currentnamespace이면 foo는 currentnamespacesubnamespacefoo로 확인됩니다. foo를 사용하는 코드가 전역 코드인 경우(어떤 네임스페이스에도 포함되지 않은 코드) foo는 subnamespacefoo로 확인됩니다.
정규화된 이름 또는 전역 접두사 연산자를 포함하는 이름( 예: $a = new currentnamespacefoo() 또는 currentnamespacefoo::staticmethod();) 이 경우 foo는 항상 코드에서 리터럴 이름 currentnamespacefoo로 확인됩니다.
다음은 이 세 가지 방법을 사용하는 예입니다.
file1.php 파일 코드
<?phpnamespace FooBarsubnamespace; const FOO = 1;function foo() {}class foo{ static function staticmethod() {}}?>
file2.php 파일 코드
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* Unqualified name*/foo() // 구문 분석 FooBarfoofoo::staticmethod(); 함수입니다. // FooBarfoo 클래스로 구문 분석되며 메서드는 staticmethodecho FOO입니다. 상수 FooBarFOO/* 정규화된 이름*/subnamespacefoo()로 확인됩니다. // FooBarsubnamespacefoosubnamespacefoo::staticmethod()로 확인됩니다. // FooBarsubnamespace; foo, // 및 클래스 메소드 staticmethodecho subnamespaceFOO; // 상수 FooBarsubnamespaceFOO로 구문 분석됨 /* 정규화된 이름 */FooBarfoo(); // FooBarfooFooBarfoo::staticmethod()로 해석됩니다. // FooBarfoo 클래스로 해석됩니다. 메서드 staticmethodecho FooBarFOO; //상수 FooBarFOO로 해석됨?>
전역 클래스, 함수 또는 상수에 액세스하려면 strlen(), Exception 또는 INI_ALL과 같은 정규화된 이름을 사용할 수 있습니다.
네임스페이스 내의 전역 클래스, 함수 및 상수에 액세스합니다.
<?phpnamespace Foo;function strlen() {}const INI_ALL = 3;class Exception {}$a = strlen('hi'); // 전역 함수 호출 strlen$b = INI_ALL$ // 전역 상수에 액세스 c = new Exception('error'); // 전역 클래스 인스턴스화 Exception?>
PHP 네임스페이스의 구현은 언어 자체의 동적 특성에 영향을 받습니다. 따라서 아래 코드를 네임스페이스로 변환하려면 해당 요소에 동적으로 액세스하세요.
example1.php 파일 코드:
<?phpclass classname{ function __construct() { echo __METHOD__,"n"; }}function funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'classname';$obj = new $a; // classname::__construct$b = 'funcname';$b() // funcnameecho 인쇄 상수('constname'), "n"; // 전역 인쇄?>
정규화된 이름(네임스페이스 접두사를 포함한 클래스 이름)을 사용해야 합니다. 동적 클래스 이름, 함수 이름 또는 상수 이름에서는 정규화된 이름과 정규화된 이름 사이에 차이가 없으므로 앞에 백슬래시가 필요하지 않습니다.
네임스페이스의 요소에 동적으로 액세스
<?phpnamespace 네임스페이스 이름;클래스 클래스 이름{ function __construct() { echo __METHOD__,"n"; }}function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php' ;$a = 'classname';$obj = new $a; // 출력 클래스 이름::__construct$b = 'funcname';$b(); // 함수 이름 출력 echo 상수('constname'), "n"; // 출력 전역/* 큰따옴표를 사용하는 경우 사용 방법은 "\namespacename\classname" "* /$a = 'namespacenameclassname';$obj = new $a; // 출력 네임스페이스 이름클래스 이름::__construct$a = 'namespacenameclassname';$obj = new $a; // 출력 네임스페이스 이름클래스 이름::__construct$b = 'namespacenamefuncname';$b(); // 출력 네임스페이스 이름funcname$b = 'namespacenamefuncname';$b() // 출력 네임스페이스 이름funcnameecho 상수( 'namespacenameconstname'), "n"; // 출력 네임스페이스decho 상수('namespacenameconstname'), "n"; 출력 네임스페이스가 있습니까?>
PHP는 현재 네임스페이스 내의 요소에 액세스하는 두 가지 추상 메서드인 __NAMESPACE__ 매직 상수와 네임스페이스 키워드를 지원합니다.
__NAMESPACE__ 상수의 값은 현재 네임스페이스의 이름을 포함하는 문자열입니다. 네임스페이스에 포함되지 않은 전역 코드에는 빈 문자열이 포함됩니다.
__NAMESPACE__ 예, 네임스페이스의 코드
<?phpnamespace MyProject;echo '"', __NAMESPACE__, '"' // "MyProject" 출력?>
__NAMESPACE__ 예, 전역 코드
<?phpecho '"', __NAMESPACE__, '"' // 출력 ""?>
__NAMESPACE__ 상수는 이름을 동적으로 생성할 때 유용합니다. 예를 들면 다음과 같습니다.
__NAMESPACE__를 사용하여 동적으로 이름 만들기
<?phpnamespace MyProject;function get($classname){ $a = __NAMESPACE__ . $classname 반환;
키워드 네임스페이스를 사용하면 현재 네임스페이스나 하위 네임스페이스의 요소에 명시적으로 액세스할 수 있습니다. 클래스의 self 연산자와 동일합니다.
네임스페이스 연산자, 네임스페이스의 코드
<?phpnamespace MyProject; blahblah를 내 것으로 사용; // "네임스페이스 사용: 가져오기/별칭 지정"을 참조하세요. blahblahmine()namespaceblahmine(); MyProjectblahmine()namespacefunc() 함수 호출; // MyProjectfunc()namespacesubfunc() 함수 호출; MyProjectsubfunc()namespacecname::method(); // MyProjectcname$a 클래스의 정적 메서드 "메서드"를 호출합니다 = new 네임스페이스subcname() // MyProjectsub 클래스의 개체를 인스턴스화합니다. cname$b = 네임스페이스CONSTANT; // $b에 상수 MyProjectCONSTANT 값을 할당합니다.>
네임스페이스 연산자, 전역 코드
<?phpnamespacefunc(); // 함수 func()namespacesubfunc() 호출; // subfunc()namespacecname::method() 함수 호출; class cname$a = new 네임스페이스subcname(); // 클래스의 객체를 인스턴스화합니다. subcname$b = 네임스페이스CONSTANT; // 상수 값을 $b에 할당합니다.
PHP 네임스페이스 지원에는 별칭 또는 가져오기를 사용하는 두 가지 방법이 있습니다. 클래스 이름에 별칭을 사용하거나 네임스페이스 이름에 별칭을 사용하는 것입니다.
PHP에서 앨리어싱은 use 연산자를 통해 구현됩니다. 다음은 가능한 세 가지 가져오기 방법을 모두 사용하는 예입니다.
1. 별칭을 가져오거나 사용하려면 use 연산자를 사용하세요.
<?phpnamespace foo;use MyFullClassname as Another;// 다음 예는 NSname으로 MyFullNSname을 사용하는 것과 동일합니다. use MyFullNSname;// 전역 클래스 가져오기 use ArrayObject;$obj = new 네임스페이스Another; // fooAnother 객체 인스턴스화 $obj = new Another; // MyFullClassname 객체 인스턴스화 NSnamesubnsfunc(); MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // ArrayObject 객체 인스턴스화 // "use ArrayObject"를 사용하지 않는 경우 fooArrayObject 객체를 인스턴스화하시겠습니까? >
2. 한 줄에 여러 개의 use 문이 포함되어 있습니다.
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // MyFullClassname 객체 인스턴스화 NSnamesubnsfunc() // 함수 호출 MyFullNSname 하위func?>
가져오기 작업은 컴파일 중에 수행되지만 동적 클래스 이름, 함수 이름 또는 상수 이름은 수행되지 않습니다.
3. 가져오기 및 동적 이름
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // MyFullClassname 객체 인스턴스화 $a = 'Another';$obj = new $a; 또 다른 객체?>
또한 가져오기 작업은 정규화되지 않은 이름과 정규화된 이름에만 영향을 미칩니다. 정규화된 이름은 결정적이므로 가져오기의 영향을 받지 않습니다.
4. 정규화된 이름 가져오기
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // MyFullClassname 인스턴스화 class $obj = new Another; // 또 다른 클래스 인스턴스화 $obj = new Another thing; // MyFullClassnamething class $obj = new Anotherthing; // 또 다른thing 클래스를 인스턴스화합니까?>
네임스페이스 내에서 PHP는 정규화되지 않은 클래스, 함수 또는 상수 이름을 발견하면 다른 우선 순위 전략을 사용하여 이름을 확인합니다. 클래스 이름은 항상 현재 네임스페이스의 이름으로 확인됩니다. 따라서 시스템 내부에 있거나 네임스페이스에 포함되지 않은 클래스 이름에 액세스할 때는 정규화된 이름을 사용해야 합니다. 예를 들면 다음과 같습니다.
1. 네임스페이스의 전역 클래스에 액세스
<?phpnamespace ABC;class Exception extends Exception {}$a = new Exception('hi'); // $a는 클래스 ABCException의 객체입니다. $b = new Exception( 'hi'); // $b는 클래스의 객체입니다. Exception $c = new ArrayObject; // 치명적인 오류, 클래스 ABCArrayObject를 찾을 수 없습니다.
함수와 상수의 경우, 함수나 상수가 현재 네임스페이스에 존재하지 않으면 PHP는 전역 공간의 함수나 상수를 사용하게 됩니다.
2. 네임스페이스의 전역 함수/상수 백업
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n"; // 출력 "45"echo INI_ALL, " n"; // 출력 "7" - 전역 상수 INI_ALLecho strlen('hi') 사용, "n"; // if 출력 "2" (is_array('hi')) { // 출력 "배열이 아님" echo "배열임n";} else { echo "배열이 아님n";}?>
네임스페이스가 정의되지 않으면 PHP가 네임스페이스 개념을 도입하기 전과 마찬가지로 모든 클래스와 함수가 전역 공간에 정의됩니다. 이름 앞에 가 붙으면 이름이 다른 네임스페이스에 있더라도 이름이 전역 공간에 있음을 나타냅니다.
전역 공간 지침 사용
<?phpnamespace ABC;/* 이 함수는 ABCfopen입니다. */function fopen() { /* ... */ $f = fopen(...); // 전역 호출 fopen 함수는 $f;} ?>를 반환합니다.
네임스페이스 도입 이후 가장 오류가 발생하기 쉬운 것은 클래스를 사용할 때 이 클래스에 대한 검색 경로가 무엇인지입니다.
<?phpnamespace A;use BD, CE as F;// 함수 호출 foo(); // 먼저 네임스페이스 "A"에 정의된 foo() 함수를 호출하려고 시도합니다. // 그런 다음 전역 호출을 시도합니다. function" foo"foo(); // 전역 공간 함수 "foo" 호출 myfoo(); // 네임스페이스 "Amy"에 정의된 "foo" 함수 호출 F(); 먼저 네임스페이스 "A"에 정의된 함수 "F"를 호출하려고 시도합니다. // 그런 다음 전역 함수 "F"를 호출하려고 합니다. // 클래스 참조 new B() // 네임스페이스 "A"에 정의된 클래스 "B"를 만듭니다. class "AB" new D(); // 찾을 수 없는 경우 클래스 "AB" 자동 로드를 시도합니다. new D() // 가져오기 규칙을 사용하여 네임스페이스 "B"에 정의된 클래스 "D"의 개체를 만듭니다. " // 찾을 수 없는 경우 "BD" 클래스를 자동으로 로드하려고 시도합니다. F(); // 가져오기 규칙을 사용하여 네임스페이스 "C"에 정의된 클래스 "E"의 개체를 만듭니다. // 찾을 수 없는 경우 클래스 "CE"를 자동 로드하려고 시도합니다. new B(); 전역 공간에 정의된 클래스 "B" // 찾을 수 없으면 클래스 "B"를 자동 로드합니다. new D(); // 전역 공간에 정의된 클래스 "D"의 개체를 만듭니다. // 찾을 수 없으면 다음을 시도합니다. 자동 로드 클래스 "D" 신규 F(); // 전역 공간에 정의된 "F" 클래스의 객체를 생성합니다. // 찾을 수 없으면 클래스 "F"를 자동 로드합니다. // 다른 네임스페이스에서 정적 메서드 또는 네임스페이스 함수를 호출합니다. Bfoo() ; // "AB" 네임스페이스에서 "foo" 함수 호출 B::foo(); // "A" 네임스페이스에 정의된 "B" 클래스의 "foo" 메서드 호출 // 클래스 "AB"가 찾을 수 없음 , 그런 다음 클래스 "AB"를 자동으로 로드하려고 시도합니다. D::foo(); // 가져오기 규칙을 사용하여 네임스페이스 "B"에 정의된 클래스 "D"의 "foo" 메서드를 호출합니다. // 클래스 "BD " " 찾을 수 없으면 "BD"Bfoo() 클래스를 자동으로 로드합니다. // "B" 네임스페이스에서 "foo" 함수를 호출합니다. B::foo(); 전역 공간 클래스 "B"의 기능 "foo" 메서드 // 클래스 "B"를 찾을 수 없으면 클래스 "B"를 자동 로드하려고 시도합니다. // 현재 네임스페이스 AB::foo()의 정적 메서드 또는 함수 // 네임스페이스 "A"를 호출합니다. A"에 정의된 클래스 "B"의 "foo" 메서드 // "AAB" 클래스를 찾을 수 없으면 클래스 "AAB"AB::foo() 자동 로드를 시도합니다. // 네임스페이스 "A"에 정의된 클래스 "B"의 "foo" 메서드 호출 // 클래스 "AB"를 찾을 수 없으면 클래스 "AB" 자동 로드를 시도합니까?>
이름 확인은 다음 규칙을 따릅니다.
함수, 클래스 및 상수의 정규화된 이름에 대한 호출은 컴파일 타임에 해결됩니다. 예를 들어 new AB 는 클래스 AB 로 확인됩니다.
모든 정규화되지 않은 이름과 정규화된 이름(정규화된 이름이 아님)은 현재 가져오기 규칙에 따라 컴파일 타임에 변환됩니다. 예를 들어 ABC 네임스페이스를 C 로 가져온 경우 CDe() 호출은 ABCDe() 로 변환됩니다.
네임스페이스 내에서 가져오기 규칙에 따라 변환되지 않은 모든 정규화된 이름에는 현재 네임스페이스 이름이 앞에 추가됩니다. 예를 들어 CDe()가 AB 네임스페이스 내에서 호출되면 CDe()는 ABCDe() 로 변환됩니다.
정규화되지 않은 클래스 이름은 현재 가져오기 규칙에 따라 컴파일 타임에 변환됩니다(짧은 가져오기 이름 대신 전체 이름이 사용됨). 예를 들어 네임스페이스 ABC를 C로 가져온 경우 new C()는 new ABC() 로 변환됩니다.
네임스페이스(예: AB) 내에서 정규화되지 않은 이름에 대한 함수 호출은 런타임 시 해결됩니다. 예를 들어 foo() 함수 호출은 다음과 같이 구문 분석됩니다.
현재 네임스페이스에서 ABfoo() 라는 함수를 찾습니다.
전역 공간에서 foo() 함수를 찾아 호출해 보세요.
네임스페이스(예: AB ) 내의 정규화되지 않은 이름 또는 정규화된 이름 클래스(정규화되지 않은 이름)에 대한 호출은 런타임 시 해결됩니다. 다음은 new C() 와 new DE()를 호출하는 구문 분석 과정이다. new C() 구문 분석:
현재 네임스페이스에서 클래스 ABC 를 찾습니다.
클래스 ABC 를 자동 로드해 보세요.
새로운 DE() 분석:클래스 이름 앞에 현재 네임스페이스 이름을 추가하여 ABDE 로 만든 다음 해당 클래스를 찾습니다.
ABDE 클래스를 자동 로드해 보세요.
전역 네임스페이스에서 전역 클래스를 참조하려면 정규화된 이름 new C()를 사용해야 합니다.