名前空間の使用法: 基本編
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
名前空間の使い方についてあれこれ言う前に、まずは PHP がどのようにしてコード中の要素の名前空間を知るのかを理解しておくことが重要です。 PHP の名前空間は、ファイルシステムにたとえて考えることができます。 たとえば、ファイルシステム内のファイルにアクセスするには次の 3 つの方法があります。
-
foo.txt
のような相対ファイル名を使う。これはcurrentdirectory/foo.txt
と解釈されます。ここで、currentdirectory
は現在いるディレクトリを表します。したがって、カレントディレクトリが/home/foo
であった場合はこれは/home/foo/foo.txt
となります。 -
subdirectory/foo.txt
のような相対パス名を使う。これはcurrentdirectory/subdirectory/foo.txt
と解釈されます。 -
/main/foo.txt
のような絶対パス名を使う。これは/main/foo.txt
と解釈されます。
-
$a = new foo();
あるいはfoo::staticmethod();
のような非修飾名 あるいはプレフィックスなしのクラス名。 現在の名前空間がcurrentnamespace
である場合、これはcurrentnamespace\foo
と解釈されます。 名前空間に属さないグローバルなコードにおいては、これはfoo
と解釈されます。 注意: 修飾されていない関数や定数は、名前空間内にその関数や定数がなければ グローバルな関数あるいは変数とみなされます。詳細は 名前空間の使用法: グローバルな関数/定数への移行 を参照ください。 -
$a = new subnamespace\foo();
あるいはsubnamespace\foo::staticmethod();
のような修飾名 あるいはプレフィックスつきクラス名。 現在の名前空間がcurrentnamespace
である場合、これはcurrentnamespace\subnamespace\foo
と解釈されます。 名前空間に属さないグローバルなコードにおいては、これはsubnamespace\foo
と解釈されます。 -
$a = new \currentnamespace\foo();
あるいは\currentnamespace\foo::staticmethod();
のような完全修飾名 あるいはグローバルプレフィックス演算子つきのクラス名。 これは、常にコードで記述されたとおりの名前であるcurrentnamespace\foo
と解釈されます。
これら 3 つの構文を実際のコードで使う例を次に示します。
file1.php
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
file2.php
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* 非修飾名 */
foo(); // Foo\Bar\foo 関数と解釈されます
foo::staticmethod(); // Foo\Bar\foo クラスの staticmethod メソッドと解釈されます
echo FOO; // 定数 Foo\Bar\FOO と解釈されます
/* 修飾名 */
subnamespace\foo(); // Foo\Bar\subnamespace\foo 関数と解釈されます
subnamespace\foo::staticmethod(); // Foo\Bar\subnamespace\foo クラスの
// staticmethod メソッドと解釈されます
echo subnamespace\FOO; // 定数 Foo\Bar\subnamespace\FOO と解釈されます
/* 完全修飾名 */
\Foo\Bar\foo(); // Foo\Bar\foo 関数と解釈されます
\Foo\Bar\foo::staticmethod(); // Foo\Bar\foo クラスの staticmethod メソッドと解釈されます
echo \Foo\Bar\FOO; // 定数 Foo\Bar\FOO と解釈されます
?>
グローバルなクラス、関数あるいは定数にアクセスするには、完全修飾名を使用して
\strlen()、\Exception あるいは
\INI_ALL
などとすることができます。
例1 グローバルなクラス、関数および定数への名前空間内からのアクセス
<?php
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // グローバル関数 strlen をコールします
$b = \INI_ALL; // グローバル定数 INI_ALL にアクセスします
$c = new \Exception('error'); // グローバルクラス Exception のインスタンスを作成します
?>
+add a note
User Contributed Notes 5 notes
richard at richard-sumilang dot com ¶
16 years ago
Syntax for extending classes in namespaces is still the same.
Lets call this Object.php:
<?php
namespace com\rsumilang\common;
class Object{
// ... code ...
}
?>
And now lets create a class called String that extends object in String.php:
<?php
class String extends com\rsumilang\common\Object{
// ... code ...
}
?>
Now if you class String was defined in the same namespace as Object then you don't have to specify a full namespace path:
<?php
namespace com\rsumilang\common;
class String extends Object
{
// ... code ...
}
?>
Lastly, you can also alias a namespace name to use a shorter name for the class you are extending incase your class is in seperate namespace:
<?php
namespace com\rsumilang\util;
use com\rsumlang\common as Common;
class String extends Common\Object
{
// ... code ...
}
?>
- Richard Sumilang
Anonymous ¶
9 years ago
<?php
namespace Foo;
try {
// Something awful here
// That will throw a new exception from SPL
}
catch (Exception as $ex) {
// We will never get here
// This is because we are catchin Foo\Exception
}
?>
Instead use fully qualified name for the exception to catch it
<?php
namespace Foo;
try {
// something awful here
// That will throw a new exception from SPL
}
catch (\Exception as $ex) {
// Now we can get here at last
}
?>
Lukas Z ¶
12 years ago
Well variables inside namespaces do not override others since variables are never affected by namespace but always global:
"Although any valid PHP code can be contained within a namespace, only four types of code are affected by namespaces: classes, interfaces, functions and constants. "
Source: "Defining Namespaces"
http://www.php.net/manual/en/language.namespaces.definition.php
tom at tomwardrop dot com ¶
12 years ago
It seems the file system analogy only goes so far. One thing that's missing that would be very useful is relative navigation up the namespace chain, e.g.
<?php
namespace MyProject {
class Person {}
}
namespace MyProject\People {
class Adult extends ..\Person {}
}
?>
That would be really nice, especially if you had really deep namespaces. It would save you having to type out the full namespace just to reference a resource one level up.
philip dot preisser at arcor dot de ¶
13 years ago
Working with variables can overwrite equal variables in other namespaces
<?php // php5 - package-version : 5.3.5-1ubuntu7.2
namespace
main
{}
namespace
main\sub1
{
$data = 1;
}
namespace
main\sub2
{
echo $data;// 1
$data = 2;
}
namespace
main\sub1
{
echo $data;// 2
$data = 1;
}
namespace
{
echo $data;// 1
}
?>
![To Top](/images/to-top@2x.png)