PHP

индекс
206,76

Как использовать пространства имён в PHP, Часть 3: Ключевые слова и автозагрузка

image
В части 1 и 2 нашей серии статей мы рассмотрели основы пространства имён, а также импортирование, псевдонимы и правила разбора имён. В данной, заключительной, статье мы обговорим некоторые более продвинутые опции пространства имён.

Константа __NAMESPACE__


__NAMESPACE__ это строка PHP, которая всегда возвращает текущее имя пространства имён. В глобальном пространстве она будет всегда пустой строкой.
  1. <?php
  2. namespace App\Lib1;
  3. echo __NAMESPACE__; // outputs: App\Lib1
  4. ?>

Её значение имеет очевидную выгоду во время отладки. Её также можно использовать чтобы динамически генерировать полные квалифицированные имена классов, например:
  1. <?php
  2. namespace App\Lib1;
  3.  
  4. class MyClass {
  5.   public function WhoAmI() {
  6.     return __METHOD__;
  7.   }
  8. }
  9.  
  10. $c = __NAMESPACE__ . '\\MyClass';
  11. $m = new $c;
  12. echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
  13. ?>

Ключевое слово namespace


Ключевое слово namespace может использоваться для того чтобы явно указать источник позиции (дать на него ссылку) в пределах текущего пространства имён или подпространства имён. Эквивалент namespace — ключевое слово self для классов:
  1. <?php
  2. namespace App\Lib1;
  3.  
  4. class MyClass {
  5.   public function WhoAmI() {
  6.     return __METHOD__;
  7.   }
  8. }
  9.  
  10. $m = new namespace\MyClass;
  11. echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
  12. ?>

Автозагрузка классов пространств имен


Одна из наилучших возможностей экономящих время в PHP 5 это автозагрузка. В глобальном (не отнесенном к какому-либо пространству имен) PHP коде, стандартная функция автозагрузки может быть записана следующим образом:
  1. <?php
  2. $obj1 = new MyClass1(); // classes/MyClass1.php is auto-loaded
  3. $obj2 = new MyClass2(); // classes/MyClass2.php is auto-loaded
  4.  
  5. // autoload function
  6. function __autoload($class_name) {
  7.   require_once("classes/$class_name.php");
  8. }
  9. ?>

В PHP 5.3 Вы можете создать экземпляр класса пространства имен. В этой ситуации, полные квалифицированные имена пространств имён и имена классов передаются функции __autoload, например, значением $class_name может быть "App\Lib1\MyClass". Вы можете продолжить размещать Ваши файлы PHP классов в одной и той же папке и отбирать пространства имён из строки, однако, это может привести к конфликту файловых имен.

В качестве альтернативы, файловая иерархия Ваших классов может быть организована таким же образом как и структура Ваших пространств имен. Например, файл MyClass.php может быть создан в папке /classes/App/Lib1:

/classes/App/Lib1/MyClass.php:

  1. <?php
  2. namespace App\Lib1;
  3.  
  4. class MyClass {
  5.   public function WhoAmI() {
  6.     return __METHOD__;
  7.   }
  8. }
  9. ?>

Файл, находящийся в корневой директории может его использовать с помощью следующего кода:

myapp.php:

  1. <?php
  2. use App\Lib1\MyClass as MC;
  3.  
  4. $obj = new MC();
  5. echo $obj->WhoAmI();
  6.  
  7. // autoload function
  8. function __autoload($class) {
  9.  
  10.   // convert namespace to full file path
  11.   $class = 'classes/' . str_replace('\\', '/', $class) . '.php';
  12.   require_once($class);
  13.  
  14. }
  15. ?>

Пояснение:

  1. Используем псевдоним MC для класса App\Lib1\MyClass
  2. Во время компиляции new MC() транслируется в new App\Lib1\MyClass().
  3. Строка "App\Lib1\MyClass" передается функции __autoload. Это заменяет все обратные слэши пространств имён на прямые слэши пути файла, и видоизменяет строку таким образом, что загружается файл "classes\App\Lib1\MyClass.php".


Я надеюсь что Вам пригодится эта серия статей о пространствах имён PHP. Будете ли Вы использовать пространства имён в своем PHP коде?

Читайте также:


Как использовать пространства имен в PHP, Часть 1: Основы
Как использовать пространства имён в PHP, Часть 2: Импортирование, псевдонимы и правила разбора имён

Примечания:


A/ Во время работы над переводом, когда искал очередной термин, нашел здесь эту же третью часть, но уже переведенную. На мой взгляд, в том переводе содержатся достаточно грубые ошибки, сравните:
Ключевое словов namespace может быть использован для четкой связи между текущим пространством имени и подпространствами на подобии self в классах

Мой перевод:
Ключевое слово namespace может использоваться для того чтобы явно указать источник позиции (дать на него ссылку) в пределах текущего пространства имён или подпространства имён. Эквивалент namespace — ключевое слово self для классов


B/ Замечания, поправки, указания на неточности и проч. — приветствуются!

C/ Код подсвечен с помощью Source Code Highlighter.
+41
12 октября 2009, 08:23
99

комментарии (10)

+1
Joka #
прекрасно, спасибо. интересный материал. мне ваш перевод понравился больше, чем тот, который по ссылке.
+1
KeJSaR #
Спасибо и Вам! Буду трудиться дальше! :-)
0
KeJSaR #
Хочу немного дополнить по функции __autoload. Она позволяет нам пользоваться классами, не включая их код явно. Она имеет смыл в контексте объектно-ориентированного программирования. Её основное отличие в том, что она не является частью определения класса, а добавляется в программу как обычная процедурная функция. Например, вместо:
  1. require "MySQLResult.php";
  2. require "MySQLConnect.php";
  3. require "PageNavigator.php";
  4. require "Directory Items.php";
  5. require "Documenter.php";

Можно легко записать:
  1. function __autoload ($class) {
  2.     require $class ".php";
  3. }

Функция __autoload вызывается при попытке использовать класс, который не был включен явно. В качестве аргумента ей передается имя класса, который можно включить, сконструировав имя соответствующего файла. Конечно, для такого использования __autoload файл, содержащий определение класса, должен находиться в текущем каталоге или в одном из каталогов, указанных в списке путей для require.
+3
crocodile2u #
Могу чуть добавить про ключевое слово use.

Когда не было __autoload() и spl_autoload_register() — мы с вами подключали вверху файла все его зависимости:

require_once('xxx/yyy.php');

Когда появился __autoload() — жить стало проще и веселей, такие блоки стали исчезать из исходников. В принципе это хорошо: такое поведение более оптимально, это экономия на вызовах, на файловых операциях. Одно но — из исходников исчезли их зависимости и иногда стало несколько сложнее их отследить. Так вот, в PHP-5.3 ключевое слово use c одной стороны явно указывает нам, какие классы/интерфейсы/библиотеки используются в данном файле, а с другой стороны не приводит к оверхеду, который возникал при подключении нужных файлов.

Go namespaces, go PHP-5.3! ;)
0
habraname #
самая грубая ошибка: «на подобии», тогда как необходим предлог «наподобие» :))

прочитал три статьи, не нашёл ответа на вопрос: где заканчивается действие неймспейс? я подозреваю, что вместе с файлом, но всё-таки?
и второй, на ту же тему: если сделаеть include, пространство имён импортнётся в подключаемый файл или нет?
+1
KeJSaR #
Спасибо! Но «на подобии» — написано не мной, это, если обратите внимание, цитата из аналогичного перевода. Кроме того там еще и грубая ошибка в программировании…

Вопрос первый: Действие пространства имён распространяется на весь файл. Если же хотите ограничить его, можно сделать так:
  1. <?php
  2. namespace MyProject {
  3. 
  4. const CONNECT_OK = 1;
  5. class Connection { /* ... */ }
  6. function connect() { /* ... */ }
  7. }
  8. 
  9. namespace { // global code
 10. session_start();
 11. $a = MyProject\connect();
 12. echo MyProject\Connection::start();
 13. }
 14. ?>


* This source code was highlighted with Source Code Highlighter.

А если пожелаете определить два и более, то так:
  1. <?php
  2. namespace MyProject {
  3. 
  4. const CONNECT_OK = 1;
  5. class Connection { /* ... */ }
  6. function connect() { /* ... */ }
  7. }
  8. 
  9. namespace AnotherProject {
 10. 
 11. const CONNECT_OK = 1;
 12. class Connection { /* ... */ }
 13. function connect() { /* ... */ }
 14. }
 15. ?>


* This source code was highlighted with Source Code Highlighter.


Вопрос второй. Что непонятно, смотри на примерах:

Пример 1.

file1.php
<?php
namespace my\stuff;
class MyClass {}
?>

another.php
<?php
namespace another;
class thing {}
?>

file2.php
<?php
namespace my\stuff;
include 'file1.php';
include 'another.php';

use another\thing as MyClass;
$a = new MyClass; // instantiates class "thing" from namespace another
?>

В данном случае не будет конфликта имён, даже не смотря на то, что класс MyClass существует в пределах пространства имён my\stuff, так как описание MyClass находится в отдельном файле. Импорт имён не конфликтует с классами, определёнными в этом же файле.

Пример 2.

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, method staticmethod
echo \Foo\Bar\FOO; // разрешается в константу Foo\Bar\FOO
?>
0
Goodkat #
получаются пакеты или библиотеки :)
0
funca #
A.php:
<?php
namespace foo
class A {}
?>

B.php:
<?php
class B {}
?>

<?php
include "A.php";
include "B.php"; # В каком нейспейсе class B: 'foo' или 'global' ?
?>
+1
Ueasley #
__NAMESPACE__ скорее уж альтернатива __CLASS__, а не self, но это уже не к вам.
0
lukdiman #
Вообще-то о том что __NAMESPACE__ тоже что и self речи не шло. Речь шла о том что ключевое слово namespace тоже что и self

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.