Правила разбора имён

Разбор имён происходит по следующим правилам:

  1. Все квалифицированные имена транслируются во время компиляции в соответствии с текущими импортированными пространствами имён. К примеру, если импортировано постранство имён A::B::C, вызов C::D::e() будет транслирован как A::B::C::D::e().
  2. Неквалифицированные имена классов транслируются во время компиляции в соответствии с текущими импортированными пространствами имён (полные имена заменяют короткие импортированные имена). К примеру, если пространство имён A::B::C импортировано, new C() будет транслировано как new A::B::C().
  3. Внутри пространства имён вызов неквалифицированных функций, определенных в этом же пространстве имён интерпертируется как вызов в данном пространстве имён во время компиляции.
  4. Внутри пространства имён (например A::B) вызов неквалифицированных функций, не определенных в этом пространстве имён будет разрешаться во время выполнения. Вызов функции foo() будет разрешаться следующим образом:
    1. Поиск в текущем пространстве имён: A::B::foo().
    2. Поиск внутренней PHP функции foo().
    В случае неудачи всех предыдущих попыток будет использован вызов определенной в глобальном пространстве имён функции ::foo().
  5. Внутри пространства имён (например A::B), вызов неквалифицированных классов разрешается во время выполнения. Например вызов new C() будет разрешаться следующим образом:
    1. Поиск класса в текущем пространстве имён: A::B::C.
    2. Попытка вызова внутреннего PHP-класса C.
    3. Попытка автозагрузки A::B::C.
    В случае неудачи всех предыдущих, будет использован вызов new ::C().
  6. Вызов квалифицированных функций разрешается во время выполнения. Например вызов A::B::foo() будет разрешаться следующим образом :
    1. Поиск функции foo() в пространстве имён A::B.
    2. Поиск класса A::B и вызов его статического метода foo(). Будет сделана автозагрузка класса, если необходимо.
  7. Квалифицированные имена классов разрешаются во время компиляции, как классы соответствующего пространства имён. К примеру new A::B::C() будет ссылаться на класс C пространства имён A::B.

Пример #1 Примеры разбора имён

<?php
    namespace A
;

    
// вызовы функций

    
foo();      // сначала попытка вызвать "foo" определенную в пространстве имён "A"
    // затем вызов внутренней функции "foo"

    
::foo();    // вызоы функции "foo" определенной глобально

    // class references

    
new B();    // сначала попытка создать объект класса "B" определенного в пространстве имён "A"
    // затем создание объекта внутреннего класса "B"

    
new ::B();  //  создать объект класса "B" определенного глобально

    // статические методы/функции пространства имён из других (не текущих) пространств имён

    
B::foo();   // сначала попытка вызвать функцию "foo" из пространства имён "A::B"
    // затем вызов метода "foo" внутреннего класса "B"

    
::B::foo(); // сначала попытка вызова функции "foo" из пространства имён  "B"
    // затем вызов метода  "foo" класса "B" из глобального пространства имён

    // статические методы/функции пространства имён из текущего пространства имён

    
A::foo();   // сначала попытка вызова функции "foo" пространства имён "A::A"
    // затем попытка вызова метода "foo" класса "A" из пространства имён "A"
    // затем попытка вызова функции "foo" пространства имён "A"
    // затем вызов метода "foo" внутреннего класса "A" 

    
::A::foo(); // сначала попытка вызова функции  "foo" пространства имён "A"
    // затем вызов метода "foo" класса "A" из глобального пространства имён
    
?>

Коментарии

Автор:
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:

->Say you have the following directory structure:

- root
      | - loader.php 
      | - ns
             | - foo.php

->foo.php

<?php
namespace ns;
class 
foo
{
    public 
$say;
   
    public function 
__construct()
    {
       
$this->say "bar";
    }
   
}
?>

-> loader.php

<?php
//GLOBAL SPACE <--
function __autoload($c)
{
    require_once 
$c ".php";
}

class 
foo extends ns\foo // ns\foo is loaded here
{
    public function 
__construct()
    {
       
parent::__construct();
        echo 
"<br />foo" $this->say;
    }
}
$a = new ns\foo(); // ns\foo also loads ns/foo.php just fine here.
echo $a->say;   // prints bar as expected.
$b = new foo// prints foobar just fine.
?>

If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors. 
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.

Cheers!
2009-07-31 03:47:51
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html
Автор:
The term "autoload" mentioned here shall not be confused with __autoload function to autoload objects. Regarding the __autoload and namespaces' resolution I'd like to share the following experience:

->Say you have the following directory structure:

- root
      | - loader.php 
      | - ns
             | - foo.php

->foo.php

<?php
namespace ns;
class 
foo
{
    public 
$say;
   
    public function 
__construct()
    {
       
$this->say "bar";
    }
   
}
?>

-> loader.php

<?php
//GLOBAL SPACE <--
function __autoload($c)
{
    require_once 
$c ".php";
}

class 
foo extends ns\foo // ns\foo is loaded here
{
    public function 
__construct()
    {
       
parent::__construct();
        echo 
"<br />foo" $this->say;
    }
}
$a = new ns\foo(); // ns\foo also loads ns/foo.php just fine here.
echo $a->say;   // prints bar as expected.
$b = new foo// prints foobar just fine.
?>

If you keep your directory/file matching namespace/class consistence the object __autoload works fine.
But... if you try to give loader.php a namespace you'll obviously get fatal errors. 
My sample is just 1 level dir, but I've tested with a very complex and deeper structure. Hope anybody finds this useful.

Cheers!
2009-07-31 03:48:15
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html
As working with namespaces and using (custom or basic) autoload structure; magic function __autoload must be defined in global scope, not in a namespace, also not in another function or method.

<?php
namespace Glue {
   
/**
     * Define your custom structure and algorithms
     * for autoloading in this class.
     */
   
class Import
   
{
        public static function 
load ($classname)
        {
            echo 
'Autoloading class '.$classname."\n";
            require_once 
$classname.'.php';
        }
    }
}

/**
 * Define function __autoload in global namespace.
 */
namespace {
   
    function 
__autoload ($classname)
    {
       
\Glue\Import::load($classname);
    }

}
?>
2010-10-22 04:04:19
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html
Автор:
If you like to declare an __autoload function within a namespace or class, use the spl_autoload_register() function to register it and it will work fine.
2010-10-27 21:35:20
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html
Автор:
For point 4, "In example, if the namespace A\B\C is imported as C" should be "In example, if the class A\B\C is imported as C".
2014-01-22 12:25:03
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html
Автор:
The mentioned filesystem analogy fails at an important point:

Namespace resolution *only* works at declaration time. The compiler fixates all namespace/class references as absolute paths, like creating absolute symlinks.

You can't expect relative symlinks, which should be evaluated during access -> during PHP runtime.

In other words, namespaces are evaluated like __CLASS__ or self:: at parse-time. What's *not* happening, is the pendant for late static binding like static:: which resolves to the current class at runtime.

So you can't do the following:

namespace Alpha;
class Helper {
    public static $Value = "ALPHA";
}
class Base {
    public static function Write() { 
        echo Helper::$Value;
    }
}

namespace Beta;
class Helper extends \Alpha\Helper {
    public static $Value = 'BETA';
}   
class Base extends \Alpha\Base {}   

\Beta\Base::Write(); // should write "BETA" as this is the executing namespace context at runtime.

If you copy the write() function into \Beta\Base it works as expected.
2014-12-21 15:05:40
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html
Namespaces may be case-insensitive, but autoloaders most often do.
Do yourself a service, keep your cases consistent with file names, and don't overcomplicate autoloaders beyond necessity.
Something like this should suffice for most times:

<?php

namespace org\example;

function 
spl_autoload($className)
{
 
$file = new \SplFileInfo(__DIR__ substr(strtr("$className.php"'\\''/'), 11));
 
$path $file->getRealPath();
  if(empty(
$path))
  {
    return 
false;
  }
  else
  {
    return include_once 
$path;
  }
}

\spl_autoload_register('\org\example\spl_autoload');
?>
2016-02-13 00:32:45
http://php5.kiev.ua/manual/ru/language.namespaces.rules.html

    Поддержать сайт на родительском проекте КГБ