Dennis' note is irrelevant as of today : with last 5.3 builds it is possible to use class names which coincide with PHP's internal class names within your namespaces. His example using PDO now works correctly.
Правила разбора имён
Разбор имён происходит по следующим правилам:
-
Все квалифицированные имена транслируются во время компиляции в
соответствии с текущими импортированными пространствами имён.
К примеру, если импортировано постранство имён A::B::C, вызов
C::D::e()будет транслирован какA::B::C::D::e(). -
Неквалифицированные имена классов транслируются во время компиляции
в соответствии с текущими импортированными пространствами имён
(полные имена заменяют короткие импортированные имена). К примеру,
если пространство имён A::B::C импортировано,
new C()будет транслировано какnew A::B::C(). - Внутри пространства имён вызов неквалифицированных функций, определенных в этом же пространстве имён интерпертируется как вызов в данном пространстве имён во время компиляции.
-
Внутри пространства имён (например A::B) вызов
неквалифицированных функций, не определенных в этом пространстве имён
будет разрешаться во время выполнения.
Вызов функции foo() будет разрешаться следующим образом:
- Поиск в текущем пространстве имён: A::B::foo().
- Поиск внутренней PHP функции foo().
-
Внутри пространства имён (например A::B), вызов
неквалифицированных классов разрешается во время выполнения. Например
вызов
new C()будет разрешаться следующим образом:- Поиск класса в текущем пространстве имён: A::B::C.
- Попытка вызова внутреннего PHP-класса C.
- Попытка автозагрузки A::B::C.
new ::C(). -
Вызов квалифицированных функций разрешается во время выполнения.
Например вызов A::B::foo() будет разрешаться следующим образом :
- Поиск функции foo() в пространстве имён A::B.
- Поиск класса A::B и вызов его статического метода foo(). Будет сделана автозагрузка класса, если необходимо.
-
Квалифицированные имена классов разрешаются во время компиляции, как
классы соответствующего пространства имён. К примеру
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" из глобального пространства имён
?>
Правила разбора имён
Raphael
26-Mar-2008 07:01
26-Mar-2008 07:01
Will
21-Feb-2008 12:08
21-Feb-2008 12:08
Agreed. Dennis is right on with this. To add on, requiring each file that includes a namespace also defeats the purpose of namespacing. It makes more sense if you have a repository for namespaces and just use those.
Example:
/some/path/to/namespaces/
<?php
use Some::Namespace;
// Test is withing Namespace.
$t = new Test();
// Test2 is not, so it checks includes, etc.
$t = new Test2();
?>
Dennis
04-Jan-2008 03:18
04-Jan-2008 03:18
Sadly enough, the latest class name resolution rules render PHP namespaces quite useless. It is impossible to use class names which coincide with PHP's internal class names within your namespaces unless you _explicitly_ use them and alias them!
The worst thing is that PHP internal class names _always_ will take precedence over your class names. This means that you start developing a toolkit and take good care to use and alias your class names (eg, Exception or DateTime or PDO). You also create classes with names that don't have names that would conflict with PHP's internal classes. However, after you have done lots of work on your toolkit you find out that there's been another extension added to PHP and it has a class that coincides with your class name. Your code becomes useless.
A quick example:
<?php
/*
* (PDO.php)
*/
namespace my::name::space;
class PDO {}
?>
<?php
/*
* (Test.php)
*/
namespace my:name::space;
class Test {
static function doSmth() {
$pdo = new PDO();
}
}
?>
and this code:
<?php
include('PDO.php');
include('Test.php');
use my::name::space::Test;
Test::doSmth();
?>
This of course will emit a warning that PDO constructor expects at least one parameter (which is perfectly correct for PHP Data Objects). Now go to your php.ini and disable lines
extension=php_dll.php
or
extension=pdo.so
as well as all other PDO drivers. Now run the example and it will produce no warnings!
I have used PDO class name here as it can be easily disabled to demonstrate the problem. Now imagine that PDO was not an internal class and you were using it in your code for some time already. Suddenly an extension author choses to use this name. And all your code is broken. You will have to go into every file that references that class and explicitly use it with an alias and rename all occurences of this class name to an alias.
As to me this is too far from solving the name collision issues!
