SymfonyWorld Online 2022 Winter Edition

名前空間の使用法: 基本編

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

名前空間の使い方についてあれこれ言う前に、まずは PHP がどのようにしてコード中の要素の名前空間を知るのかを理解しておくことが重要です。 PHP の名前空間は、ファイルシステムにたとえて考えることができます。 たとえば、ファイルシステム内のファイルにアクセスするには次の 3 つの方法があります。

  1. foo.txt のような相対ファイル名を使う。これは currentdirectory/foo.txt と解釈されます。ここで、 currentdirectory は現在いるディレクトリを表します。したがって、カレントディレクトリが /home/foo であった場合はこれは /home/foo/foo.txt となります。
  2. subdirectory/foo.txt のような相対パス名を使う。これは currentdirectory/subdirectory/foo.txt と解釈されます。
  3. /main/foo.txt のような絶対パス名を使う。これは /main/foo.txt と解釈されます。
PHP の名前空間内の要素についても同じ理屈があてはまります。 たとえば、クラス名を参照するには次の 3 つの方法があります。
  1. $a = new foo(); あるいは foo::staticmethod(); のような非修飾名 あるいはプレフィックスなしのクラス名。 現在の名前空間が currentnamespace である場合、これは currentnamespace\foo と解釈されます。 名前空間に属さないグローバルなコードにおいては、これは foo と解釈されます。 注意: 修飾されていない関数や定数は、名前空間内にその関数や定数がなければ グローバルな関数あるいは変数とみなされます。詳細は 名前空間の使用法: グローバルな関数/定数への移行 を参照ください。
  2. $a = new subnamespace\foo(); あるいは subnamespace\foo::staticmethod(); のような修飾名 あるいはプレフィックスつきクラス名。 現在の名前空間が currentnamespace である場合、これは currentnamespace\subnamespace\foo と解釈されます。 名前空間に属さないグローバルなコードにおいては、これは subnamespace\foo と解釈されます。
  3. $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 6 notes

up
199
richard at richard-sumilang dot com
14 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
up
102
Anonymous
7 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
}
?>
up
47
Lukas Z
10 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
up
40
tom at tomwardrop dot com
10 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.
up
14
philip dot preisser at arcor dot de
11 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
   
}

?>
up
-51
Franois Vespa
11 years ago
It seems you cannot nest a constant declaration within a if statement

<?php

namespace FOO;

if(eval)
const
BAR=true;

// will throw the following error:
// PHP Parse error:  syntax error, unexpected T_CONST

// instead use:

if(eval)
define('FOO\BAR',true);

?>
To Top