mirror of
https://github.com/php/doc-ru.git
synced 2026-03-24 07:42:22 +01:00
1611 lines
70 KiB
XML
1611 lines
70 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: 1651836ff309efd14a795eff44ee51455f66c7d3 Maintainer: mch Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<chapter xml:id="language.namespaces" xmlns="http://docbook.org/ns/docbook"
|
||
version="1.1">
|
||
<title>Пространства имён</title>
|
||
|
||
<sect1 xml:id="language.namespaces.rationale">
|
||
<title>Обзор пространств имён</title>
|
||
<titleabbrev>Обзор</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<simpara>
|
||
Пространства имён, в широком смысле, — способ инкапсуляции
|
||
элементов. Такое абстрактное понятие встречается часто. Например, в каждой
|
||
операционной системе директории группируют связанные файлы и выступают
|
||
в роли пространства имён для находящихся в них файлов. Конкретный пример,
|
||
разрешается размещать файл <literal>foo.txt</literal> сразу в обоих каталогах:
|
||
<literal>/home/greg</literal> и <literal>/home/other</literal>, но двум копиям
|
||
файла <literal>foo.txt</literal> нельзя сосуществовать в одной директории. Кроме сказанного, для доступа
|
||
к файлу <literal>foo.txt</literal> извне каталога <literal>/home/greg</literal> надо
|
||
через разделитель добавить перед именем файла имя директории, чтобы получить
|
||
путь <literal>/home/greg/foo.txt</literal>. Этот же принцип распространяется и на пространства
|
||
имён в программировании.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В PHP пространства имён решают две проблемы, с которыми
|
||
сталкиваются авторы библиотек и приложений, когда создают переиспользуемые
|
||
элементы кода, например классы и функции:
|
||
</simpara>
|
||
<para>
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Устраняют конфликт имён между кодом разработчика
|
||
и внутренними или внешними классами, функциями, константами PHP.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Создают псевдонимы (или сокращения) для Ну_Очень_Длинных_Имён, чтобы сгладить
|
||
первую проблему и улучшить читаемость исходного кода.
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
</para>
|
||
<simpara>
|
||
Пространства имён в PHP помогают группировать логически связанные
|
||
классы, интерфейсы, функции и константы.
|
||
</simpara>
|
||
<example>
|
||
<title>Пример синтаксиса с пространством имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace my\name; // Смотрите раздел «Определение пространств имён»
|
||
|
||
class MyClass {}
|
||
function myfunction() {}
|
||
const MYCONST = 1;
|
||
|
||
$a = new MyClass;
|
||
$c = new \my\name\MyClass; // Смотрите раздел «Глобальное пространство»
|
||
|
||
$a = strlen('hi'); // Смотрите раздел «Пространства имён: возврат
|
||
// к глобальному пространству для функций и констант»
|
||
|
||
$d = namespace\MYCONST; // Смотрите раздел «Ключевое слово namespace и магическая константа __NAMESPACE__»
|
||
$d = __NAMESPACE__ . '\MYCONST';
|
||
echo constant($d); // Смотрите раздел «Пространства имён и динамические особенности языка»
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<note>
|
||
<simpara>
|
||
Имена пространств имён регистронезависимы.
|
||
</simpara>
|
||
</note>
|
||
<note>
|
||
<para>
|
||
Название пространства имён «<literal>PHP</literal>» и составные названия,
|
||
которые начинаются с этого слова (например, <literal>PHP\Classes</literal>), зарезервированы
|
||
для внутренних целей языка, их не нужно писать в пользовательском коде.
|
||
</para>
|
||
</note>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.namespaces.definition">
|
||
<title>Определение пространств имён</title>
|
||
<titleabbrev>Пространства имён</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Хотя любой корректный PHP-код разрешается размещать внутри пространства имён, только
|
||
классы (включая абстрактные классы, трейты и перечисления), интерфейсы, функции и константы зависят от пространства имён.
|
||
</para>
|
||
<para>
|
||
Пространства имён объявляют зарезервированным словом <literal>namespace</literal>,
|
||
за которым идёт название пространства имён.
|
||
Пространства имён объявляют в начале файла. Другому коду нельзя идти
|
||
перед объявлением пространства имён, за исключением зарезервированного слова
|
||
<xref linkend="control-structures.declare" />.
|
||
<example>
|
||
<title>Объявление единого пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject;
|
||
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<note>
|
||
<simpara>
|
||
Абсолютные имена, — которые начинаются с обратной косой черты, —
|
||
нельзя включать в объявления пространств имён,
|
||
поскольку языковые конструкции с начальным слешем интерпретируются
|
||
как выражения относительных пространств имён.
|
||
</simpara>
|
||
</note>
|
||
Перед объявлением пространства имён разрешается указывать только инструкцию
|
||
<literal>declare</literal>, чтобы, например, определить кодировку исходного файла. В дополнение,
|
||
никакой код, кроме PHP-кода, нельзя размещать перед объявлением пространства имён, включая лишние пробелы:
|
||
<example>
|
||
<title>Объявление пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<html>
|
||
<?php
|
||
|
||
namespace MyProject; // Фатальная ошибка, поскольку объявление пространства имён идёт не первой инструкцией в скрипте
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
В отличие от остальных PHP-конструкций, разрешается определение одного и того же
|
||
пространства имён в двух или больше файлах для распределения
|
||
содержания пространства имён по файловой системе.
|
||
</para>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.nested">
|
||
<title>Определение подпространств имён</title>
|
||
<titleabbrev>Подпространства имён</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Аналогично каталогам и файлам, пространства имён PHP разрешают указывать
|
||
иерархию названий пространств имён. Поэтому имя пространства разрешается определять
|
||
с подуровнями:
|
||
<example>
|
||
<title>Определение пространства имён с иерархией</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject\Sub\Level;
|
||
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
Приведённый пример создаёт константу <literal>MyProject\Sub\Level\CONNECT_OK</literal>,
|
||
класс <literal>MyProject\Sub\Level\Connection</literal> и функцию
|
||
<literal>MyProject\Sub\Level\connect</literal>.
|
||
</para>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.definitionmultiple">
|
||
<title>Описание нескольких пространств имён в одном файле</title>
|
||
<titleabbrev>Несколько пространств имён в одном файле</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
В одном файле разрешается объявлять больше одного пространства имён.
|
||
Многократные пространства имён в одном файле разрешается определять двумя синтаксисами:
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Объявление набора пространств имён синтаксисом простой комбинации</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject;
|
||
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
|
||
namespace AnotherProject;
|
||
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Этот синтаксис не рекомендуют для комбинирования пространств имён в одном файле.
|
||
Вместо него лучше пользоваться альтернативным синтаксисом со скобками.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Объявление набора пространств имён синтаксисом со скобками</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject {
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
}
|
||
|
||
namespace AnotherProject {
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Практика написания кода настоятельно не рекомендует объединять пространства имён
|
||
в одном файле. Главный сценарий того, когда это потребуется, —
|
||
объединение нескольких PHP-файлов в один файл.
|
||
</para>
|
||
<para>
|
||
Для объединения кода в глобальном пространстве имён с кодом в других пространствах имён
|
||
пользуются только синтаксисом со скобками. Глобальный код должен быть
|
||
помещён в конструкцию описания пространства имён без указания имени:
|
||
<example>
|
||
<title>Описание глобального и обычного пространства имён в одном файле</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject {
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
}
|
||
|
||
namespace { // Глобальный код
|
||
session_start();
|
||
$a = MyProject\connect();
|
||
echo MyProject\Connection::start();
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Никакой PHP-код нельзя размещать за пределами скобок пространства имён, кроме
|
||
начального выражения declare.
|
||
<example>
|
||
<title>Описание глобального и обычного пространства имён в одном файле</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
declare(encoding='UTF-8');
|
||
|
||
namespace MyProject {
|
||
const CONNECT_OK = 1;
|
||
class Connection { /* ... */ }
|
||
function connect() { /* ... */ }
|
||
}
|
||
|
||
namespace { // Глобальный код
|
||
session_start();
|
||
$a = MyProject\connect();
|
||
echo MyProject\Connection::start();
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.basics">
|
||
<title>Основы пространств имён</title>
|
||
<titleabbrev>Основы</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Прежде чем обсуждать работу с пространствами имён, важно понять, как PHP узнаёт,
|
||
какие элементы из пространства имён запрашиваются в коде. Можно провести
|
||
аналогию между пространствами имён PHP и файловой системой. Есть три способа обратиться
|
||
к файлу в файловой системе:
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Относительное имя файла наподобие <literal>foo.txt</literal> разрешится
|
||
в <literal>currentdirectory/foo.txt</literal>, где <literal>currentdirectory</literal> — текущая
|
||
директория, в которой мы находимся. Тогда, если текущая директория —
|
||
<literal>/home/foo</literal>, то имя преобразуется в <literal>/home/foo/foo.txt</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Относительное имя пути наподобие <literal>subdirectory/foo.txt</literal> разрешится
|
||
в <literal>currentdirectory/subdirectory/foo.txt</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Абсолютное имя пути наподобие <literal>/main/foo.txt</literal> останется
|
||
таким же: <literal>/main/foo.txt</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
Тот же принцип сохранится при разрешении элементов из пространств имён PHP.
|
||
Название класса, например, указывают тремя способами:
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Неполное имя, или название класса без префикса, наподобие
|
||
<literal>$a = new foo();</literal>
|
||
или <literal>foo::staticmethod();</literal>. В текущем пространстве имён
|
||
<literal>currentnamespace</literal> такое название разрешится
|
||
в <literal>currentnamespace\foo</literal>. В коде в глобальном
|
||
пространстве имён название останется прежним: <literal>foo</literal>.
|
||
</simpara>
|
||
<simpara>
|
||
Предостережение: неполные названия функций и констант разрешаются
|
||
в глобальные функции и константы, если их не определили в текущем пространстве имён.
|
||
Подробнее об этом рассказывает раздел
|
||
«<link linkend="language.namespaces.fallback">Пространства имён: возврат к глобальному пространству для функций и констант</link>».
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Полное имя, или название класса с префиксами наподобие
|
||
<literal>$a = new subnamespace\foo();</literal>
|
||
или <literal>subnamespace\foo::staticmethod();</literal>. В текущем пространстве имён
|
||
<literal>currentnamespace</literal> такое название разрешится
|
||
в <literal>currentnamespace\subnamespace\foo</literal>. В коде в глобальном
|
||
пространстве имён название разрешится в <literal>subnamespace\foo</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Абсолютное имя, или название с префиксом в начале,
|
||
который указывает на глобальное пространство имён наподобие
|
||
<literal>$a = new \currentnamespace\foo();</literal>
|
||
или <literal>\currentnamespace\foo::staticmethod();</literal>. Такое название разрешается
|
||
в буквальное, — которое указали в коде: <literal>currentnamespace\foo</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
</para>
|
||
<para>
|
||
Вот пример трёх видов синтаксиса в реальном коде:
|
||
<informalexample>
|
||
<simpara>file1.php</simpara>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace Foo\Bar\subnamespace;
|
||
|
||
const FOO = 1;
|
||
|
||
function foo() {}
|
||
|
||
class foo
|
||
{
|
||
static function staticmethod() {}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
<simpara>file2.php</simpara>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace Foo\Bar;
|
||
|
||
include 'file1.php';
|
||
|
||
const FOO = 2;
|
||
function foo() {}
|
||
|
||
class foo
|
||
{
|
||
static function staticmethod() {}
|
||
}
|
||
|
||
/* Неполные имена */
|
||
foo(); // Разрешается в функцию Foo\Bar\foo
|
||
foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\foo
|
||
echo FOO; // Разрешается в константу Foo\Bar\FOO
|
||
|
||
/* Полные имена */
|
||
subnamespace\foo(); // Разрешается в функцию Foo\Bar\subnamespace\foo
|
||
subnamespace\foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\subnamespace\foo
|
||
echo subnamespace\FOO; // Разрешается в константу Foo\Bar\subnamespace\FOO
|
||
|
||
/* Абсолютные имена */
|
||
\Foo\Bar\foo(); // Разрешается в функцию Foo\Bar\foo
|
||
\Foo\Bar\foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\foo
|
||
echo \Foo\Bar\FOO; // Разрешается в константу Foo\Bar\FOO
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
<para>
|
||
Обратите внимание, что для доступа к глобальным
|
||
классам, функциям или константам разрешается указывать абсолютное имя, например,
|
||
<function>\strlen</function>, <classname>\Exception</classname>
|
||
или \<constant>INI_ALL</constant>.
|
||
<example>
|
||
<title>Доступ к глобальным классам, функциям и константам из пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?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
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.dynamic">
|
||
<title>Пространства имён и динамические особенности языка</title>
|
||
<titleabbrev>Пространства имён и динамические особенности языка</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
На реализацию пространств имён в PHP повлияли и динамические свойства языка.
|
||
Поэтому, для преобразования кода наподобие следующего примера в код,
|
||
который сработает внутри пространства имён:…
|
||
<example>
|
||
<title>Динамически доступные элементы</title>
|
||
<simpara>example1.php:</simpara>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class classname
|
||
{
|
||
function __construct()
|
||
{
|
||
echo __METHOD__,"\n";
|
||
}
|
||
}
|
||
|
||
function funcname()
|
||
{
|
||
echo __FUNCTION__,"\n";
|
||
}
|
||
|
||
const constname = "global";
|
||
|
||
$a = 'classname';
|
||
$obj = new $a(); // Выводит classname::__construct
|
||
|
||
$b = 'funcname';
|
||
$b(); // Выводит funcname
|
||
|
||
echo constant('constname'), "\n"; // Выводит global
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
…потребуется указать абсолютное имя — название класса с префиксом пространства имён.
|
||
Обратите внимание, поскольку между полным и абсолютным именем
|
||
внутри динамического названия класса, функции или константы нет разницы,
|
||
начальный обратный слеш не требуется.
|
||
<example>
|
||
<title>Динамически доступные элементы пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace namespacename;
|
||
|
||
class classname
|
||
{
|
||
function __construct()
|
||
{
|
||
echo __METHOD__,"\n";
|
||
}
|
||
}
|
||
|
||
function funcname()
|
||
{
|
||
echo __FUNCTION__,"\n";
|
||
}
|
||
|
||
const constname = "namespaced";
|
||
|
||
include 'example1.php';
|
||
|
||
$a = 'classname';
|
||
$obj = new $a; // Выводит: classname::__construct
|
||
$b = 'funcname';
|
||
$b(); // Выводит: funcname
|
||
echo constant('constname'), "\n"; // Выводит: global
|
||
|
||
/* Обратите внимание, что в двойных кавычках символ обратного слеша потребуется заэкранировать. Например: "\\namespacename\\classname" */
|
||
$a = '\namespacename\classname';
|
||
$obj = new $a; // Выводит: namespacename\classname::__construct
|
||
$a = 'namespacename\classname';
|
||
$obj = new $a; // Тоже выводит: namespacename\classname::__construct
|
||
$b = 'namespacename\funcname';
|
||
$b(); // Выводит: namespacename\funcname
|
||
$b = '\namespacename\funcname';
|
||
$b(); // Тоже выводит: namespacename\funcname
|
||
echo constant('\namespacename\constname'), "\n"; // Выводит: namespaced
|
||
echo constant('namespacename\constname'), "\n"; // Тоже выводит: namespaced
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Обязательно прочитайте <link linkend="language.namespaces.faq.quote">примечание об
|
||
экранировании имён пространства имён в строках</link>.
|
||
</para>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.nsconstants">
|
||
<title>Ключевое слово namespace и магическая константа __NAMESPACE__</title>
|
||
<titleabbrev>Ключевое слово namespace и константа __NAMESPACE__</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
PHP поддерживает два способа абстрактного доступа к элементам в текущем пространстве
|
||
имён: магическая константа <constant>__NAMESPACE__</constant> и ключевое
|
||
слово <literal>namespace</literal>.
|
||
</para>
|
||
<para>
|
||
Значение константы <constant>__NAMESPACE__</constant> — строка, которая содержит
|
||
название текущего пространства имён. В глобальном пространстве, вне пространства имён,
|
||
константа содержит пустую строку.
|
||
<example>
|
||
<title>Пример записи константы __NAMESPACE__ в коде с пространством имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject;
|
||
|
||
echo '"', __NAMESPACE__, '"'; // Выводит: MyProject
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<example>
|
||
<title>Пример записи константы __NAMESPACE__ в глобальном пространстве</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo '"', __NAMESPACE__, '"'; // Выводит: ""
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
Константа <constant>__NAMESPACE__</constant> полезна для динамически конструируемых
|
||
имён, например:
|
||
<example>
|
||
<title>Константа __NAMESPACE__ и динамическое конструирование имени</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject;
|
||
|
||
function get($classname)
|
||
{
|
||
$a = __NAMESPACE__ . '\\' . $classname;
|
||
return new $a;
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Ключевое слово <literal>namespace</literal> разрешается указывать
|
||
для явного запроса элемента из текущего пространства имён или из подпространства.
|
||
Это эквивалент ключевого слова <literal>self</literal> для классов в пространстве имён.
|
||
<example>
|
||
<title>Ключевое слово namespace внутри пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace MyProject;
|
||
|
||
use blah\blah as mine; // Смотрите «Пространства имён: псевдонимирование и импорт»
|
||
|
||
blah\mine(); // Вызывает функцию MyProject\blah\mine()
|
||
namespace\blah\mine(); // Вызывает функцию MyProject\blah\mine()
|
||
|
||
namespace\func(); // Вызывает функцию MyProject\func()
|
||
namespace\sub\func(); // Вызывает функцию MyProject\sub\func()
|
||
namespace\cname::method(); // Вызывает статический метод method класса MyProject\cname
|
||
$a = new namespace\sub\cname(); // Создаёт экземпляр класса MyProject\sub\cname
|
||
$b = namespace\CONSTANT; // Присваивает значение константы MyProject\CONSTANT переменной $b
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<example>
|
||
<title>Ключевое слово namespace в глобальном коде</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace\func(); // Вызывает функцию func()
|
||
namespace\sub\func(); // Вызывает функцию sub\func()
|
||
namespace\cname::method(); // Вызывает статический метод method класса cname
|
||
$a = new namespace\sub\cname(); // Создаёт экземпляр класса sub\cname
|
||
$b = namespace\CONSTANT; // Присваивает значение константы CONSTANT переменной $b
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.namespaces.importing">
|
||
<title>Пространства имён: псевдонимирование и импорт</title>
|
||
<titleabbrev>Псевдонимирование и импорт</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Способность ссылаться на внешнее абсолютное имя по псевдониму
|
||
или импортировать внешние абсолютные имена —
|
||
важное свойство пространств имён. Это похоже на способность
|
||
файловых систем на основе Unix создавать символические ссылки на файл или директорию.
|
||
</para>
|
||
<para>
|
||
PHP умеет создавать псевдонимы или импортировать константы,
|
||
функции, классы, интерфейсы, трейты, перечисления и пространства имён.
|
||
</para>
|
||
<para>
|
||
Псевдоним имени создают через ключевое слово <literal>use</literal>.
|
||
Вот пример, который показывает 5 типов импорта:
|
||
<example>
|
||
<title>Импорт или псевдонимирование через ключевое слово use</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
use My\Full\Classname as Another;
|
||
|
||
// Это то же, что и My\Full\NSname as NSname
|
||
use My\Full\NSname;
|
||
|
||
// Импортирование глобального класса
|
||
use ArrayObject;
|
||
|
||
// Импортирование функции
|
||
use function My\Full\functionName;
|
||
|
||
// Создание псевдонима функции
|
||
use function My\Full\functionName as func;
|
||
|
||
// Импортирование константы
|
||
use const My\Full\CONSTANT;
|
||
|
||
$obj = new namespace\Another; // Создаёт экземпляр класса foo\Another
|
||
$obj = new Another; // Создаёт объект класса My\Full\Classname
|
||
NSname\subns\func(); // Вызывает функцию My\Full\NSname\subns\func
|
||
|
||
$a = new ArrayObject(array(1)); // Создаёт объект класса ArrayObject
|
||
// без выражения use ArrayObject был бы создан объект класса foo\ArrayObject
|
||
|
||
func(); // вызывает функцию My\Full\functionName
|
||
echo CONSTANT; // выводит содержимое константы My\Full\CONSTANT
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
Обратите внимание, что именам внутри пространства имён (абсолютным именам пространств имён,
|
||
которые содержат разделитель пространств имён, например <literal>Foo\Bar</literal>,
|
||
в отличие от глобальных имён, которые его не содержат, например <literal>FooBar</literal>)
|
||
начальный обратный слеш (\) не нужен и не рекомендован,
|
||
поскольку импортируемые имена должны быть абсолютными и не обрабатываются
|
||
относительно текущего пространства имён.
|
||
</para>
|
||
<para>
|
||
PHP дополнительно поддерживает удобное сокращение для задания нескольких операторов
|
||
use в одной и той же строке
|
||
<example>
|
||
<title>Импорт или создание псевдонима через ключевое слово use, комбинирование нескольких выражений</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use My\Full\Classname as Another, My\Full\NSname;
|
||
|
||
$obj = new Another; // Создаёт объект класса My\Full\Classname
|
||
NSname\subns\func(); // Вызывает функцию My\Full\NSname\subns\func
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Импорт выполняется во время компиляции поэтому не влияет на имена динамических классов,
|
||
функций или констант.
|
||
<example>
|
||
<title>Импорт и динамические имена</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use My\Full\Classname as Another, My\Full\NSname;
|
||
|
||
$obj = new Another; // Создаёт объект класса My\Full\Classname
|
||
$a = 'Another';
|
||
$obj = new $a; // Создаёт объект класса Another
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
В дополнение, импорт распространяется только на неполные и полные имена. На абсолютные
|
||
имена операция импорта не влияет.
|
||
<example>
|
||
<title>Импортирование и абсолютные имена</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use My\Full\Classname as Another, My\Full\NSname;
|
||
|
||
$obj = new Another; // Создаёт объект класса My\Full\Classname
|
||
$obj = new \Another; // Создаёт объект класса Another
|
||
$obj = new Another\thing; // Создаёт объект класса My\Full\Classname\thing
|
||
$obj = new \Another\thing; // Создаёт объект класса Another\thing
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<sect2 xml:id="language.namespaces.importing.scope">
|
||
<title>Обзор правил для импорта</title>
|
||
<para>
|
||
Ключевое слово <literal>use</literal> должно быть указано в самом начале файла (в
|
||
глобальной области) или внутри объявления пространства имён. Это нужно, потому что
|
||
импорт выполняется во время компиляции, а не во время исполнения, поэтому его
|
||
нельзя ограничить блоком кода. Следующий пример показывает недопустимое указание
|
||
ключевого слова <literal>use</literal>:
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Недопустимое правило импорта</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace Languages;
|
||
|
||
function toGreenlandic()
|
||
{
|
||
use Languages\Danish;
|
||
|
||
//...
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<note>
|
||
<para>
|
||
Правила импорта задают на каждый файл отдельно. Поэтому
|
||
присоединяемые файлы <emphasis>НЕ</emphasis> будут наследовать правила импорта
|
||
из родительского файла.
|
||
</para>
|
||
</note>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.importing.group">
|
||
<title>Групповые объявления через ключевое слово <literal>use</literal></title>
|
||
<para>
|
||
Классы, функции и константы, импортируемые из одного и того же
|
||
пространства имён (&namespace;), разрешается группировать в одном
|
||
выражении с ключевым словом &use.namespace;.
|
||
</para>
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
use some\namespace\ClassA;
|
||
use some\namespace\ClassB;
|
||
use some\namespace\ClassC as C;
|
||
|
||
use function some\namespace\fn_a;
|
||
use function some\namespace\fn_b;
|
||
use function some\namespace\fn_c;
|
||
|
||
use const some\namespace\ConstA;
|
||
use const some\namespace\ConstB;
|
||
use const some\namespace\ConstC;
|
||
|
||
// Эквивалентно следующему групповому объявлению с ключевым словом use
|
||
use some\namespace\{ClassA, ClassB, ClassC as C};
|
||
use function some\namespace\{fn_a, fn_b, fn_c};
|
||
use const some\namespace\{ConstA, ConstB, ConstC};
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</sect2>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.global">
|
||
<title>Глобальное пространство</title>
|
||
<titleabbrev>Глобальное пространство</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Без определения пространства имён определения классов и функций
|
||
помещаются в глобальном пространстве — так же, как это было в PHP до введения
|
||
пространств имён. Добавление префикса <literal>\</literal> к именам указывает, что
|
||
требуется имя из глобального пространства, даже в контексте пространства имён.
|
||
<example>
|
||
<title>Спецификация глобального пространства</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace A\B\C;
|
||
|
||
/* Функция — A\B\C\fopen */
|
||
function fopen() {
|
||
/* ... */
|
||
$f = \fopen(...); // Вызов глобальной функции fopen
|
||
return $f;
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.fallback">
|
||
<title>Пространства имён: возврат к глобальному пространству для функций и констант</title>
|
||
<titleabbrev>Возврат к глобальному пространству</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Когда внутри пространства имён PHP встречает неполное имя класса, функции или
|
||
контекст константы, он разрешает эти имена с разными приоритетами. Имена классов
|
||
разрешаются в текущее имя пространства имён. Поэтому, чтобы получить доступ
|
||
ко внутреннему классу или пользовательскому классу вне пространства имён, необходимо
|
||
обращаться к ним по абсолютному имени. Например:
|
||
<example>
|
||
<title>Доступ к глобальным классам внутри пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace A\B\C;
|
||
|
||
class Exception extends \Exception {}
|
||
|
||
$a = new Exception('hi'); // Переменная $a — объект класса A\B\C\Exception
|
||
$b = new \Exception('hi'); // Переменная $b — объект класса Exception
|
||
|
||
$c = new ArrayObject; // Фатальная ошибка, класс A\B\C\ArrayObject не найден
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
PHP будет обращаться к глобальным функциям или константам,
|
||
если функция или константа не существует в текущем пространстве имён.
|
||
<example>
|
||
<title>Возврат к глобальным функциям или константам внутри пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace A\B\C;
|
||
|
||
const E_ERROR = 45;
|
||
function strlen($str)
|
||
{
|
||
return \strlen($str) - 1;
|
||
}
|
||
|
||
echo E_ERROR, "\n"; // Выводит 45
|
||
echo INI_ALL, "\n"; // Выводит «7» — возвращается к глобальной константе INI_ALL
|
||
|
||
echo strlen('hi'), "\n"; // Выводит «1»
|
||
if (is_array('hi')) { // Выводит строку «это не массив»
|
||
echo "Это массив\n";
|
||
} else {
|
||
echo "Это не массив\n";
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect1>
|
||
|
||
<sect1 xml:id="language.namespaces.rules">
|
||
<title>Правила разрешения имён</title>
|
||
<titleabbrev>Правила разрешения имён</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Для целей этих правил разрешения приведём важные определения:
|
||
<variablelist>
|
||
<title>Определения имени пространства имён</title>
|
||
<varlistentry>
|
||
<term>Неполное имя</term>
|
||
<listitem>
|
||
<para>
|
||
Идентификатор без разделителя пространств имён, например <literal>Foo</literal>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Полное имя</term>
|
||
<listitem>
|
||
<para>
|
||
Идентификатор с разделителем пространств имён, например <literal>Foo\Bar</literal>
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Абсолютное имя</term>
|
||
<listitem>
|
||
<para>
|
||
Идентификатор с разделителем пространств имён, который начинается с разделителя пространств имён,
|
||
например <literal>\Foo\Bar</literal>. Пространство имён <literal>\Foo</literal> —
|
||
также абсолютное имя.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term>Относительное имя</term>
|
||
<listitem>
|
||
<para>
|
||
Идентификатор, который начинается с ключевого слова <literal>namespace</literal>,
|
||
например <literal>namespace\Foo\Bar</literal>.
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
<para>
|
||
Имена разрешаются по следующим правилам:
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Абсолютные имена разрешаются в имя без ведущего разделителя пространства имён.
|
||
Например, <literal>\A\B</literal> разрешается в <literal>A\B</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Относительные имена разрешаются в имя с заменой ключевого слова <literal>namespace</literal>
|
||
текущим пространством имён. Префикс <literal>namespace\</literal> удаляется,
|
||
если имя встречается в глобальном пространстве имён. Например,
|
||
имя <literal>namespace\A</literal> внутри пространства имён <literal>X\Y</literal> разрешается
|
||
в <literal>X\Y\A</literal>. То же имя в глобальном пространстве имён разрешается
|
||
в <literal>A</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
В полных именах первый сегмент имени преобразовывается с учётом текущей таблицы
|
||
импорта класса или пространства имён. Например, если пространство имён <literal>A\B\C</literal>
|
||
импортировано как <literal>C</literal>, то имя <literal>C\D\E</literal> преобразуется
|
||
в <literal>A\B\C\D\E</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
В полных именах, если не применялось правило импорта, текущее пространство имён добавляется к имени.
|
||
Например, имя <literal>C\D\E</literal> внутри пространства имён <literal>A\B</literal>
|
||
разрешится в <literal>A\B\C\D\E</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Неполные имена преобразовываются с учётом текущей таблицы импорта
|
||
и типа элемента. То есть имена как у классов преобразовываются с учётом таблицы импорта классов или пространств имён,
|
||
имена функций — с учётом таблицы импорта функций, а константы — таблицы импорта
|
||
констант. Например, при записи <literal>use A\B\C;</literal>, вызов <literal>new C()
|
||
</literal> разрешается в <literal>A\B\C()</literal>. Аналогично, при
|
||
записи <literal>use function A\B\foo;</literal> вызов <literal>foo()</literal> разрешается
|
||
в <literal>A\B\foo</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
В начало неполных имён, если не применялось правило импорта и имя относится к элементу
|
||
с именем как у класса, добавляется текущее пространство имён. Например,
|
||
имя класса в выражении <literal>new C()</literal> внутри пространства имён <literal>A\B</literal> разрешится
|
||
в имя <literal>A\B\C</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
В неполных именах, если не применялось правило импорта и имя относится к функции или константе,
|
||
а код лежит за пределами глобального пространства имён,
|
||
имя разрешается при выполнении. Вот как разрешится вызов функции <literal>foo()</literal>
|
||
в коде в пространстве имён <literal>A\B</literal>:
|
||
</simpara>
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Выполняется поиск функции из текущего пространства имён:
|
||
<literal>A\B\foo()</literal>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
PHP пытается найти и вызвать функцию <literal>foo()</literal>
|
||
из <emphasis>глобального пространства имён</emphasis>.
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
</listitem>
|
||
</orderedlist>
|
||
</para>
|
||
<example>
|
||
<title>Примеры разрешения имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace A;
|
||
|
||
use B\D, C\E as F;
|
||
|
||
// Вызовы функций
|
||
|
||
foo(); // Сперва пытается вызвать функцию foo, которую определили в пространстве имён A,
|
||
// затем вызывает глобальную функцию foo
|
||
|
||
\foo(); // Вызывает функцию foo, которую определили в глобальном пространстве
|
||
|
||
my\foo(); // Вызывает функцию foo, которую определили в пространстве имён A\my
|
||
|
||
F(); // Сперва пытается вызвать функцию F, которую определили в пространстве имён A,
|
||
// затем вызывает глобальную функцию F
|
||
|
||
// Ссылки на классы
|
||
|
||
new B(); // Создаёт объект класса B, который определили в пространстве имён A.
|
||
// Если класс не найден, то пытается автоматически загрузить класс A\B
|
||
|
||
new D(); // Следуя правилам импорта, создаёт объект класса D, который определили в пространстве имён B,
|
||
// если класс не найден, то пытается автоматически загрузить класс B\D
|
||
|
||
new F(); // Следуя правилам импорта, создаёт объект класса E, который определили в пространстве имён C,
|
||
// если класс не найден, то пытается автоматически загрузить класс класса C\E
|
||
|
||
new \B(); // Создаёт объект класса B, который определили в глобальном пространстве,
|
||
// если класс не найден, то пытается автоматически загрузить класс B
|
||
|
||
new \D(); // Создаёт объект класса D, который определили в глобальном пространстве,
|
||
// если класс не найден, то пытается автоматически загрузить класс D
|
||
|
||
new \F(); // Создаёт объект класса F, который определили в глобальном пространстве,
|
||
// если класс не найден, то пытается автоматически загрузить класс F
|
||
|
||
// Статические методы и функции пространства имён из другого пространства имён
|
||
|
||
B\foo(); // Вызывает функцию foo из пространства имён A\B
|
||
|
||
B::foo(); // Вызывает метод foo из класса B, который определили в пространстве имён A,
|
||
// если класс A\B не найден, то пытается автоматически загрузить класс A\B
|
||
|
||
D::foo(); // Следуя правилам импорта, вызывает метод foo класса D, который определили в пространстве имён B,
|
||
// если класс B\D не найден, то пытается автоматически загрузить класс B\D
|
||
|
||
\B\foo(); // Вызывает функцию foo из пространства имён B
|
||
|
||
\B::foo(); // Вызывает метод foo класса B из глобального пространства,
|
||
// если класс B не найден, то пытается автоматически загрузить класс B
|
||
|
||
// Статические методы и функции пространства имён из текущего пространства имён
|
||
|
||
A\B::foo(); // Вызывает метод foo класса B из пространства имён A\A,
|
||
// если класс A\A\B не найден, то пытается автоматически загрузить класс A\A\B
|
||
|
||
\A\B::foo(); // Вызывает метод foo класса B из пространства имён A,
|
||
// если класс A\B не найден, то пытается автоматически загрузить класс A\B
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</sect1>
|
||
<sect1 xml:id="language.namespaces.faq">
|
||
<title>Часто задаваемые вопросы (FAQ): что нужно знать о пространствах имён</title>
|
||
<titleabbrev>FAQ</titleabbrev>
|
||
<?phpdoc print-version-for="namespaces"?>
|
||
<para>
|
||
Этот список вопросов разделён на две части: общие вопросы и некоторые особенности
|
||
реализации, которые полезны для полного понимания.
|
||
</para>
|
||
<para>
|
||
Вначале общие вопросы.
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.shouldicare">Если в коде не указаны пространства имён, нужно
|
||
ли считать что-либо из этого важным?</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.globalclass">Как обращаться к внутренним или глобальным
|
||
классам в пространстве имён?</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.innamespace">Как обращаться к функциям классов в
|
||
пространствах имён, или константам в их пространстве имён?</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.full">
|
||
Как разрешаются имена <literal>\my\name</literal> или <literal>\name</literal>?
|
||
</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.qualified">Как разрешается имя <literal>my\name</literal>?</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.shortname1">Как разрешается неполное имя класса <literal>name</literal>?</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.shortname2">Как разрешается неполное имя функции
|
||
или неполное имя константы наподобие <literal>name</literal>?</link>
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
</para>
|
||
<para>
|
||
Некоторые детали реализации пространств имён, которые
|
||
полезно понимать.
|
||
<orderedlist>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.conflict">Импортируемые имена не должны конфликтовать с
|
||
классами, определёнными в том же файле.</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.nested">Вложенные пространства имён недопустимы.
|
||
</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.quote">Динамические имена пространств имён (идентификаторы,
|
||
взятые в кавычки) должны экранировать символ обратного слеша.</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.constants">Ссылаться на неопределённые константы,
|
||
используя обратный слеш, нельзя. Выводится фатальная ошибка</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.namespaces.faq.builtinconst">Невозможно переопределить специальные
|
||
константы &null;, &true; или &false;</link>
|
||
</simpara>
|
||
</listitem>
|
||
</orderedlist>
|
||
</para>
|
||
<sect2 xml:id="language.namespaces.faq.shouldicare">
|
||
<title>Если в коде не указаны пространства имён, нужно ли считать что-либо из этого важным?</title>
|
||
<para>
|
||
Нет, пространства имён не влияют ни на тот код, который уже написали,
|
||
ни на ещё ненаписанный код без пространств имён. Разрешается писать
|
||
такой код, если нужно:
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Доступ к глобальным классам вне пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = new \stdClass;
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
<para>
|
||
Функционально это эквивалентно следующему:
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Доступ к глобальным классам вне пространства имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = new stdClass();
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.globalclass">
|
||
<title>Как обращаться к внутренним или глобальным классам в пространстве имён?</title>
|
||
<para>
|
||
<example>
|
||
<title>Доступ ко внутренним классам в пространствах имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
$a = new \stdClass();
|
||
|
||
function test(\ArrayObject $parameter_type_example = null) {}
|
||
|
||
$a = \DirectoryIterator::CURRENT_AS_FILEINFO;
|
||
|
||
// Расширение внутреннего или глобального класса
|
||
class MyException extends \Exception {}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.innamespace">
|
||
<title>
|
||
Как использовать функции классов в пространствах имён или
|
||
константы в их собственном пространстве имён?
|
||
</title>
|
||
<para>
|
||
<example>
|
||
<title>Доступ ко внутренним классам, функциям или константам в пространствах имён</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
class MyClass {}
|
||
|
||
// Определение класса текущего пространства имён в качестве типа параметра
|
||
function test(MyClass $parameter_type_example = null) {}
|
||
|
||
// Другой способ определить класс из текущего пространства имён в качестве типа параметра
|
||
function test(\foo\MyClass $parameter_type_example = null) {}
|
||
|
||
// Расширение класса из текущего пространства имён
|
||
class Extended extends MyClass {}
|
||
|
||
// Доступ к глобальной функции
|
||
$a = \globalfunc();
|
||
|
||
// Доступ к глобальной константе
|
||
$b = \INI_ALL;
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.full">
|
||
<title>
|
||
Как разрешаются имена наподобие <literal>\my\name</literal>
|
||
или <literal>\name</literal>?
|
||
</title>
|
||
<para>
|
||
Имена, которые начинаются с обратного слеша <literal>\</literal>, разрешаются в названия,
|
||
на которые сами похожи, поэтому имя <literal>\my\name</literal> разрешается в название <literal>my\name</literal>,
|
||
а имя <literal>\Exception</literal> — в <literal>Exception</literal>.
|
||
<example>
|
||
<title>Абсолютные имена</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
$a = new \my\name(); // Создаёт экземпляр класса my\name
|
||
echo \strlen('hi'); // Вызывает функцию strlen
|
||
$a = \INI_ALL; // Переменной $a присваивается значение константы INI_ALL
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.qualified">
|
||
<title>Как разрешается имя <literal>my\name</literal>?</title>
|
||
<para>
|
||
Имена наподобие <literal>my\name</literal>, — которые содержат обратный слеш,
|
||
но не начинаются с него, — разрешаются двумя способами.
|
||
</para>
|
||
<para>
|
||
Уровень <literal>my</literal> в имени <literal>my\name</literal> заменяется псевдонимом,
|
||
если уровню <literal>my</literal> присвоили псевдоним с другим именем, которое импортировали инструкцией use.
|
||
</para>
|
||
<para>
|
||
В остальных случаях перед именем <literal>my\name</literal> добавляется название текущего пространства имён.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Полные имена</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
use blah\blah as foo;
|
||
|
||
$a = new my\name(); // Создаёт экземпляр класса foo\my\name
|
||
foo\bar::name(); // Вызывает статический метод name, который определили в классе blah\blah\bar
|
||
my\bar(); // Вызывает функцию foo\my\bar
|
||
$a = my\BAR; // Присваивает переменной $a значение константы foo\my\BAR
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.shortname1">
|
||
<title>Как разрешается неполное имя класса вроде <literal>name</literal>?</title>
|
||
<para>
|
||
Названия классов наподобие <literal>name</literal>, — которые не содержат обратного слеша, —
|
||
разрешаются двумя способами.
|
||
</para>
|
||
<para>
|
||
Название класса заменяется псевдонимом,
|
||
если имени <literal>name</literal> присвоили псевдоним с другим именем, которое импортировали инструкцией use.
|
||
</para>
|
||
<para>
|
||
В остальных случаях к имени <literal>name</literal> добавляется текущее название пространства имён.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Неполные имена классов</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
use blah\blah as foo;
|
||
|
||
$a = new name(); // Создаёт экземпляр класса foo\name
|
||
foo::name(); // Вызывает статический метод name, который определили в классе blah\blah
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.shortname2">
|
||
<title>
|
||
Как разрешается неполное название функции или неполное имя константы вроде <literal>name</literal>?
|
||
</title>
|
||
<para>
|
||
Названия функций или констант наподобие <literal>name</literal>, —
|
||
которые не содержат обратного слеша, — разрешаются двумя способами.
|
||
</para>
|
||
<para>
|
||
Вначале перед именем <literal>name</literal> добавляется текущее название пространства имён.
|
||
</para>
|
||
<para>
|
||
Затем, если текущее пространство имён не содержит названия константы
|
||
или функции с именем <literal>name</literal>, вызывается
|
||
глобальная константа или функция с названием <literal>name</literal>,
|
||
если константу или функцию с таким названием определили в глобальном пространстве имён.
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>Неполные имена функций или констант</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace foo;
|
||
|
||
use blah\blah as foo;
|
||
|
||
const FOO = 1;
|
||
|
||
function my() {}
|
||
function foo() {}
|
||
|
||
function sort(&$a)
|
||
{
|
||
\sort($a); // Вызывает глобальную функцию sort
|
||
$a = array_flip($a);
|
||
return $a;
|
||
}
|
||
|
||
my(); // вызывает функцию foo\my
|
||
$a = strlen('hi'); // Вызывает глобальную функцию strlen, потому что функцию foo\strlen не определили
|
||
|
||
$arr = [1, 3, 2,];
|
||
$b = sort($arr); // Вызывает функцию foo\sort
|
||
|
||
$c = foo(); // Вызывает функцию foo\foo, без импорта
|
||
|
||
$a = FOO; // Присваивает переменной $a значение константы foo\FOO, без импорта
|
||
$b = INI_ALL; // Присваивает переменной $b значение глобальной константы INI_ALL
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.conflict">
|
||
<title>Импортируемым именам нельзя конфликтовать с классами, которые определили в том же файле</title>
|
||
<para>
|
||
Следующие комбинации скриптов допустимы:
|
||
<informalexample>
|
||
<simpara>file1.php</simpara>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace my\stuff;
|
||
|
||
class MyClass {}
|
||
]]>
|
||
</programlisting>
|
||
<simpara>another.php</simpara>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace another;
|
||
|
||
class thing {}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
<simpara>file2.php</simpara>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace my\stuff;
|
||
|
||
include 'file1.php';
|
||
include 'another.php';
|
||
|
||
use another\thing as MyClass;
|
||
$a = new MyClass; // Создаёт экземпляр класса thing из пространства имён another
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
<para>
|
||
Конфликт имён отсутствует, даже несмотря на то что класс <literal>MyClass</literal> существует
|
||
внутри пространства имён <literal>my\stuff</literal>, потому что определение MyClass
|
||
находится в отдельном файле. Однако следующий пример приводит к фатальной ошибке с конфликтом
|
||
имён, потому что класс MyClass определён в том же файле, в котором указано ключевое слово use.
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace my\stuff;
|
||
|
||
use another\thing as MyClass;
|
||
|
||
class MyClass {} // Фатальная ошибка: MyClass конфликтует с выражением импорта
|
||
$a = new MyClass();
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.nested">
|
||
<title>Вложенные пространства имён недопустимы.</title>
|
||
<para>
|
||
PHP не разрешает вложение пространств имён
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace my\stuff {
|
||
namespace nested {
|
||
class foo {}
|
||
}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
Однако сымитировать вложенные пространства имён можно так:
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace my\stuff\nested {
|
||
class foo {}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.quote">
|
||
<title>
|
||
Динамические имена пространств имён (идентификаторы, взятые в кавычки)
|
||
должны экранировать символ обратного слеша.
|
||
</title>
|
||
<para>
|
||
Важно понимать это, потому что обратный слеш внутри строк работает как экранирующий символ.
|
||
Он должен быть продублирован, когда указан внутри строки, иначе
|
||
появляется риск неумышленных последствий:
|
||
<example>
|
||
<title>
|
||
Подводные камни при указании имени пространства имён
|
||
внутри строки с двойными кавычками
|
||
</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$a = "dangerous\name"; // Символ \n — переход на новую строку внутри строки с двойными кавычками!
|
||
$obj = new $a;
|
||
|
||
$a = 'not\at\all\dangerous'; // А тут нет проблем.
|
||
$obj = new $a();
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
Внутри строк, заключённых в одинарные кавычки, обратный слеш в качестве разделителя более безопасен, но
|
||
по-прежнему лучше рекомендуемая практика экранирования обратного слеша во всех строках.
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.constants">
|
||
<title>Ссылаться на неопределённые константы, используя обратный слеш, нельзя. Выводится фатальная ошибка</title>
|
||
<para>
|
||
Любая неопределённая константа — неполное имя наподобие <literal>FOO</literal> — будет
|
||
приводить к выводу сообщения о том, что PHP предположил, что <literal>FOO</literal> было значением
|
||
константы. Любая константа, с полным или абсолютным именем, которая содержит
|
||
символ обратного слеша, будет приводить к фатальной ошибке, если не будет найдена.
|
||
<example>
|
||
<title>Неопределённые константы</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace bar;
|
||
|
||
$a = FOO; // Выводит предупреждение: undefined constants "FOO" assumed "FOO";
|
||
$a = \FOO; // Фатальная ошибка: undefined namespace constant FOO
|
||
$a = Bar\FOO; // Фатальная ошибка: undefined namespace constant bar\Bar\FOO
|
||
$a = \Bar\FOO; // Фатальная ошибка: undefined namespace constant Bar\FOO
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
<sect2 xml:id="language.namespaces.faq.builtinconst">
|
||
<title>Невозможно переопределить специальные константы &null;, &true; или &false;</title>
|
||
<para>
|
||
Любая попытка определить константу пространства имён,
|
||
которая совпадает с названиями специальных встроенных констант,
|
||
приведёт к фатальной ошибке.
|
||
<example>
|
||
<title>Неопределённые константы</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
namespace bar;
|
||
|
||
const NULL = 0; // Фатальная ошибка;
|
||
const true = 'stupid'; // Тоже фатальная ошибка;
|
||
// и т. д.
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</sect2>
|
||
</sect1>
|
||
</chapter>
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|