FAQ: 네임스페이스에 대해 알아야 할 것들

FAQ: 네임스페이스에 대해 알아야 할 것들 (FAQ: things you need to know about namespaces)

네임스페이스 사용에 관한 자주 묻는 질문(FAQ)을 다룹니다. 흔한 질문들과, 여러분이 완전히 이해하면 도움이 되는 몇 가지 구현 세부 사항으로 나뉘어 있습니다.

출처: FAQ: things you need to know about namespaces

본문

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

이 FAQ는 두 부분으로 나뉩니다. 흔한 질문(common questions)과, 완전히 이해하는 데 도움이 되는 몇 가지 구현 특이점입니다.

먼저, 흔한 질문들입니다.

  • 네임스페이스를 사용하지 않으면 이런 것들을 신경 써야 하나요?
  • 네임스페이스 안에서 내부(내장) 또는 전역 클래스를 어떻게 사용하나요?
  • 네임스페이스 클래스, 함수, 상수를 그들의 네임스페이스 안에서 어떻게 사용하나요?
  • \my\name이나 \name 같은 이름은 어떻게 해석되나요?
  • my\name 같은 이름은 어떻게 해석되나요?
  • name 같은 비정규화 클래스 이름은 어떻게 해석되나요?
  • name 같은 비정규화 함수 이름이나 상수 이름은 어떻게 해석되나요?

네임스페이스 구현에는 이해하면 도움이 되는 몇 가지 구현 세부 사항이 있습니다.

  • import 이름은 같은 파일에 정의된 클래스와 충돌하면 안 됩니다.
  • 중첩 네임스페이스는 허용되지 않습니다.
  • 동적 네임스페이스 이름(따옴표로 감싼 식별자)은 백슬래시를 이스케이프해야 합니다.
  • 백슬래시를 포함해 참조하는 정의되지 않은 상수는 치명적 오류(fatal error)로 끝납니다.
  • 특수 상수 null, true, false는 재정의할 수 없습니다.

네임스페이스를 사용하지 않으면 이런 것들을 신경 써야 하나요?

아니요. 네임스페이스는 기존 코드나, 네임스페이스를 포함하지 않는 앞으로 작성할 코드에 어떤 영향도 주지 않습니다. 원한다면 이렇게 코드를 작성할 수 있습니다.

예제 #1 네임스페이스 밖에서 전역 클래스 접근하기 (Accessing global classes outside a namespace)

<?php
$a = new \stdClass;
print $a::class;

이것은 기능적으로 다음 코드와 동일합니다.

예제 #2 네임스페이스 밖에서 전역 클래스 접근하기 (Accessing global classes outside a namespace)

<?php
$a = new stdClass;
print $a::class;

네임스페이스 안에서 내부 또는 전역 클래스를 어떻게 사용하나요?

예제 #3 네임스페이스 안에서 내부 클래스 접근하기 (Accessing internal classes in namespaces)

<?php
namespace foo;
$a = new \stdClass;
print $a::class . "\n";

function test(?\ArrayObject $parameter_type_example = null) {}

$a = \FilesystemIterator::CURRENT_AS_FILEINFO;
print $a . "\n";

// extending an internal or global class
class MyException extends \Exception {}
print MyException::class . "\n";

네임스페이스 클래스, 함수, 상수를 그들의 네임스페이스 안에서 어떻게 사용하나요?

예제 #4 네임스페이스 안에서 내부 클래스, 함수, 상수 접근하기 (Accessing internal classes, functions or constants in namespaces)

<?php
namespace foo;

class MyClass {}

// using a class from the current namespace as a parameter type
function test(?MyClass $parameter_type_example = null) {}
// another way to use a class from the current namespace as a parameter type
function test2(?\foo\MyClass $parameter_type_example = null) {}

// extending a class from the current namespace
class Extended extends MyClass {}
print Extended::class . "\n";

// accessing a global function
$a = \strlen("test");
print $a . "\n";

// accessing a global constant
$b = \INI_ALL;
print $b . "\n";

\my\name이나 \name 같은 이름은 어떻게 해석되나요?

\로 시작하는 이름은 항상 겉보기 그대로 해석됩니다. 즉 \my\name은 실제로 my\name이고, \ExceptionException입니다.

예제 #5 완전 정규화 이름 (Fully Qualified names)

<?php
namespace foo;
$a = new \my\name(); // instantiates "my\name" class
echo \strlen('hi'); // calls function "strlen"
$a = \INI_ALL; // $a is set to the value of constant "INI_ALL"

my\name 같은 이름은 어떻게 해석되나요?

백슬래시를 포함하지만 백슬래시로 시작하지 않는 my\name 같은 이름은 두 가지 방식으로 해석될 수 있습니다.

  • my에 다른 이름을 별칭으로 지정하는 import 문이 있으면, my\namemy에 그 import 별칭이 적용됩니다.
  • 그렇지 않으면 my\name 앞에 현재 네임스페이스 이름이 붙습니다.

예제 #6 정규화 이름 (Qualified names)

<?php
namespace foo;
use blah\blah as foo;

$a = new my\name(); // instantiates "foo\my\name" class
foo\bar::name(); // calls static method "name" in class "blah\blah\bar"
my\bar(); // calls function "foo\my\bar"
$a = my\BAR; // sets $a to the value of constant "foo\my\BAR"

name 같은 비정규화 클래스 이름은 어떻게 해석되나요?

백슬래시를 포함하지 않는 name 같은 클래스 이름은 두 가지 방식으로 해석될 수 있습니다.

  • name에 다른 이름을 별칭으로 지정하는 import 문이 있으면 그 import 별칭이 적용됩니다.
  • 그렇지 않으면 name 앞에 현재 네임스페이스 이름이 붙습니다.

예제 #7 비정규화 클래스 이름 (Unqualified class names)

<?php
namespace foo;
use blah\blah as foo;

$a = new name(); // instantiates "foo\name" class
foo::name(); // calls static method "name" in class "blah\blah"

name 같은 비정규화 함수 이름이나 상수 이름은 어떻게 해석되나요?

백슬래시를 포함하지 않는 name 같은 함수나 상수 이름은 두 가지 방식으로 해석될 수 있습니다.

  • 먼저, name 앞에 현재 네임스페이스 이름이 붙습니다.
  • 마지막으로, 현재 네임스페이스에 해당 상수나 함수가 존재하지 않으면, 존재한다면 전역 상수나 함수 이름이 사용됩니다.

예제 #8 비정규화 함수 또는 상수 이름 (Unqualified function or constant names)

<?php
namespace foo;
use blah\blah as foo;

const FOO = 1;

function my() {
    print __FUNCTION__ . "\n";
}
function foo() {
    print __FUNCTION__ . "\n";
}
function sort(&$a)
{
    \sort($a); // calls the global function "sort"
    $a = array_flip($a);
    return $a;
}

my(); // calls "foo\my"
print strlen('hi') . "\n"; // calls global function "strlen" because "foo\strlen" does not exist
$arr = array(1,3,2);
$b = sort($arr); // calls function "foo\sort"
var_dump($b);
foo(); // calls function "foo\foo" - import is not applied

$a = FOO; // sets $a to value of constant "foo\FOO" - import is not applied
print $a;
$b = INI_ALL; // sets $b to value of global constant "INI_ALL"
print $b;

import 이름은 같은 파일에 정의된 클래스와 충돌하면 안 됩니다.

다음의 스크립트 조합은 합법적입니다.

file1.php

<?php
namespace my\stuff;
class MyClass {}

another.php

<?php
namespace another;
class thing {}

file2.php

<?php
namespace my\stuff;
include 'file1.php';
include 'another.php';

use another\thing as MyClass;
$a = new MyClass; // instantiates class "thing" from namespace another

클래스 MyClassmy\stuff 네임스페이스 안에 존재함에도 불구하고 이름 충돌이 발생하지 않습니다. MyClass 정의가 별도의 파일(file1.php)에 있기 때문입니다. 하지만 다음 예제는 use 문과 같은 파일에 MyClass가 정의되어 있어 이름 충돌로 치명적 오류(fatal error)가 발생합니다.

<?php
namespace my\stuff;
use another\thing as MyClass;
class MyClass {} // fatal error: MyClass conflicts with import statement
$a = new MyClass;

중첩 네임스페이스는 허용되지 않습니다.

PHP는 네임스페이스의 중첩을 허용하지 않습니다.

<?php
namespace my\stuff {
    namespace nested {
        class foo {}
    }
}

하지만 다음과 같이 중첩 네임스페이스를 손쉽게 흉내 낼 수 있습니다.

<?php
namespace my\stuff\nested {
    class foo {}
}

동적 네임스페이스 이름(따옴표로 감싼 식별자)은 백슬래시를 이스케이프해야 합니다.

백슬래시는 문자열 안에서 이스케이프 문자로 사용되기 때문에, 문자열 안에 쓸 때는 항상 두 번 써야 한다는 점을 꼭 알아두어야 합니다. 그렇지 않으면 의도하지 않은 결과가 발생할 위험이 있습니다.

예제 #9 이중 따옴표 문자열 안에 네임스페이스 이름을 쓰는 위험 (Dangers of using namespaced names inside a double-quoted string)

<?php
$a = "dangerous\name"; // \n is a newline inside double quoted strings!
$obj = new $a;

$a = 'not\at\all\dangerous'; // no problems here.
$obj = new $a;

단일 따옴표 문자열 안에서는 백슬래시 이스케이프 시퀀스를 훨씬 안전하게 사용할 수 있지만, 모범 사례로 모든 문자열에서 백슬래시를 이스케이프하는 것이 여전히 권장됩니다.

백슬래시를 포함해 참조하는 정의되지 않은 상수는 치명적 오류로 끝납니다.

FOO처럼 비정규화된 정의되지 않은 상수는 PHP가 FOO를 상수 값으로 가정했다는 내용의 notice를 만들어냅니다. 하지만 백슬래시를 포함하는 정규화되거나 완전 정규화된 상수는 찾을 수 없으면 치명적 오류(fatal error)를 만듭니다.

예제 #10 정의되지 않은 상수 (Undefined constants)

<?php
namespace bar;
$a = FOO; // produces notice - undefined constants "FOO" assumed "FOO";
$a = \FOO; // fatal error, undefined namespace constant FOO
$a = Bar\FOO; // fatal error, undefined namespace constant bar\Bar\FOO
$a = \Bar\FOO; // fatal error, undefined namespace constant Bar\FOO

특수 상수 null, true, false는 재정의할 수 없습니다.

특수 내장 상수인 네임스페이스 상수를 정의하려는 모든 시도는 치명적 오류(fatal error)로 이어집니다.

예제 #11 정의되지 않은 상수 (Undefined constants)

<?php
namespace bar;
const NULL = 0; // fatal error;
const true = 'stupid'; // also fatal error;
// etc.

더 알아보기