Использование пространства имён: основы

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

До обсуждения использования пространств имён важно понять как PHP узнает какие элементы из пространства имён запрашиваются в вашем коде. Можно провести аналогию между пространствами имён PHP и файловой системой. Есть три способа обратиться к файлу в файловой системе:

  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. Например, имя класса может быть указано тремя способами:
  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.

Ниже приведён пример трёх вариантов синтаксиса в реальном коде:

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
                                  // c методом 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 add a note

User Contributed Notes 6 notes

up
184
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
up
86
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
}
?>
up
35
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
up
27
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.
up
6
philip dot preisser at arcor dot de
12 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
-47
Franois Vespa
13 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