Пространства имен в php
Стандарты PSR-4
Эти рекомендации называются "Стандартными рекомендациями по PHP", также известными как PSR.
Они доступны по этой ссылке: http://www.php-fig.org/psr
Существует 5 категорий стандартов кодирования :
PSR-0 : Стандарт автозагрузки, цель которого - упростить использование пространств имен, чтобы преобразовать пространство имен в путь к файлу.
PSR-1 : Базовый стандарт кодирования, по сути, стандарты :)
PSR-2: Руководство по стилю программирования, где ставить фигурные скобки, как написать класс и т.д.
PSR-3: Интерфейс логгера, как написать стандартный логгер
PSR-4: Улучшена автозагрузка, чтобы преобразовать больше пространств имен в пути.
Только классы (включая абстрактные классы, трейты и перечисления), интерфейсы, функции и константы зависят от пространства имён
Другому коду нельзя идти перед объявлением пространства имён, за исключением зарезервированного слова declare
Абсолютные имена, — которые начинаются с обратной косой черты, — нельзя включать в объявления пространств имён, поскольку языковые конструкции с начальным слешем интерпретируются как выражения относительных пространств имён.
Имя пространства разрешается определять с подуровнями
namespace MyProject\Sub\Level;
Для объединения кода в глобальном пространстве имён с кодом в других пространствах имён пользуются только синтаксисом со скобками. Глобальный код должен быть помещён в конструкцию описания пространства имён без указания имени:
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // Глобальный код
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
Никакой PHP-код нельзя размещать за пределами скобок пространства имён, кроме начального выражения declare.
declare(encoding='UTF-8');
namespace MyProject {
....
Для доступа к глобальным классам, функциям или константам может использоваться абсолютное имя — имя с предшествующим префиксом, обозначающим глобальное пространство. Например, \strlen(), \Exception или \INI_ALL
Если конструкции одного пространства имён используются в другом пространстве имён (в том числе в глобальном), то перед названием конструкции указывается название её пространства имён.
Название класса, указывают тремя способами:
Неполное имя, или название класса без префикса, наподобие $a = new foo(); или foo::staticmethod();. В текущем пространстве имён currentnamespace такое название разрешится в currentnamespace\foo. В коде в глобальном пространстве имён название останется прежним: foo. Предостережение: неполные названия функций и констант разрешаются в глобальные функции и константы, если их не определили в текущем пространстве имён.
Полное имя, или название класса с префиксами наподобие $a = new subnamespace\foo(); или subnamespace\foo::staticmethod();. В текущем пространстве имён currentnamespace такое название разрешится в currentnamespace\subnamespace\foo. В коде в глобальном пространстве имён название разрешится в subnamespace\foo.
Абсолютное имя, или название с префиксом в начале, который указывает на глобальное пространство имён наподобие $a = new \currentnamespace\foo(); или \currentnamespace\foo::staticmethod();. Такое название разрешается в буквальное, — которое указали в коде: currentnamespace\foo.
Пример трёх видов синтаксиса в реальном коде:
#file1.php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo()
{
echo "file1.php foo()\n";
}
class foo
{
static function staticmethod()
{
echo "file1.php foo::staticmethod()\n";
}
}
#file2.php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {
echo "file2.php foo()\n";
}
class foo
{
static function staticmethod() {
echo "file2.php foo::staticmethod()\n";
}
}
/* Неполные имена */
foo(); // Разрешается в функцию Foo\Bar\foo
foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\foo
echo "Константа FOO in file2.php \n";
echo FOO . "\n"; // Разрешается в константу Foo\Bar\FOO
/* Полные имена */
subnamespace\foo(); // Разрешается в функцию Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\subnamespace\foo
echo subnamespace\FOO . "\n"; // Разрешается в константу Foo\Bar\subnamespace\FOOecho "Константа FOO in file1.php \n";
/* Абсолютные имена */
\Foo\Bar\foo(); // Разрешается в функцию Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\foo
echo \Foo\Bar\FOO . "\n"; // Разрешается в константу Foo\Bar\FOO
\Foo\Bar\subnamespace\foo(); // Разрешается в функцию Foo\Bar\subnamespace\foo
\Foo\Bar\subnamespace\foo::staticmethod(); // Разрешается в метод staticmethod класса Foo\Bar\subnamespace\foo
~
Расширение классов
namespace com\rsumilang\common;
class Object{
// ... code ...
}
class String extends com\rsumilang\common\Object{
// ... code ...
}
Наконец, вы также можете псевдонимизировать имя пространства имен, чтобы использовать более короткое имя для расширяемого класса, если ваш класс находится в отдельном пространстве имен:
namespace com\rsumilang\util;
use com\rsumlang\common as Common;
class String extends Common\Object
{
// ... code ...
}
Динамические особенности языка
#example1.php
class classname
{
function __construct()
{
echo __METHOD__," example1.php \n";
}
}
function funcname()
{
echo __FUNCTION__," example1.php \n";
}
const constname = "global example1.php";
$a = 'classname';
$obj = new $a(); // Выводит classname::__construct
$b = 'funcname';
$b(); // Выводит funcname
echo constant('constname'), "\n"; // Выводит global
~
#example2.php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__," example2.php\n";
}
}
function funcname()
{
echo __FUNCTION__," example2.php \n";
}
const constname = "namespaced";
include 'example1.php';
echo "\n\n";
$a = 'classname';
$obj = new $a; // Выводит: classname::__construct
$b = 'funcname';
$b(); // Выводит: funcname
echo constant('constname'), "\n"; // Выводит: global
echo "\n\n";
/* Обратите внимание, что в двойных кавычках символ обратного слеша потребуется заэкранировать. Например: "\\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
echo "\n\n";
Источник: https://www.php.net/manual/ru/language.namespaces.dynamic.php
При расширении класса из другого пространства имен, которое должно создать экземпляр класса из текущего пространства имен, вам необходимо передать это пространство имен.
...
namespace bar;
class B extends \foo\A {}
...
Ключевое слово namespace и магическая константа __NAMESPACE__
PHP поддерживает два способа абстрактного доступа к элементам в текущем пространстве имён: магическая константа __NAMESPACE__ и ключевое слово namespace.
Значение константы __NAMESPACE__ — строка, которая содержит название текущего пространства имён. В глобальном пространстве, вне пространства имён, константа содержит пустую строку.
Константа __NAMESPACE__ полезна для динамически конструируемых имён, например
Ключевое слово namespace разрешается указывать для явного запроса элемента из текущего пространства имён или из подпространства. Это эквивалент ключевого слова self для классов в пространстве имён.
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // Выводит: MyProject
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
# Ключевое слово namespace в глобальном коде
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
Способность ссылаться на внешнее абсолютное имя по псевдониму или импортировать внешние абсолютные имена — важное свойство пространств имён. Это похоже на способность файловых систем на основе Unix создавать символические ссылки на файл или директорию.
Псевдоним имени создают через ключевое слово use
namespace foo;
use My\Full\Classname as Another;
use My\Full\NSname; // Это то же, что и My\Full\NSname as 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
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // Создаёт объект класса My\Full\Classname
NSname\subns\func(); // Вызывает функцию My\Full\NSname\subns\func
#Импортирование и абсолютные имена
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
Ключевое слово use должно быть указано в самом начале файла (в глобальной области) или внутри объявления пространства имён. Это нужно, потому что импорт выполняется во время компиляции, а не во время исполнения, поэтому его нельзя ограничить блоком кода. Следующий пример показывает недопустимое указание ключевого слова use:
namespace Languages;
function toGreenlandic()
{
use Languages\Danish;
//...
}
Правила импорта задают на каждый файл отдельно. Поэтому присоединяемые файлы НЕ будут наследовать правила импорта из родительского файла.
Классы, функции и константы, импортируемые из одного и того же пространства имён (namespace), разрешается группировать в одном выражении с ключевым словом use.
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};
Инструкция use не загружает файл класса. Это необходимо сделать с помощью инструкции require или с помощью функции автозагрузки.
способ импорта классов, функций и продолжения с помощью одноразового ключевого слова:
use Mizo\Web\ {
Php\WebSite,
Php\KeyWord,
Php\UnicodePrint,
JS\JavaScript,
function JS\printTotal,
function JS\printList,
const JS\BUAIKUM,
const JS\MAUTAM
};
Псевдонимы разрешаются только во время компиляции, тогда как CLI просто вычисляет инструкции; поэтому инструкции use неэффективны в CLI.
Вам разрешается "использовать" один и тот же ресурс несколько раз, если при каждом вызове он импортируется под другим псевдонимом.
Пространства имён: возврат к глобальному пространству для функций и констант
Когда внутри пространства имён PHP встречает неполное имя класса, функции или контекст константы, он разрешает эти имена с разными приоритетами. Имена классов разрешаются в текущее имя пространства имён. Поэтому, чтобы получить доступ ко внутреннему классу или пользовательскому классу вне пространства имён, необходимо обращаться к ним по абсолютному имени. Например:
namespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // Переменная $a — объект класса A\B\C\Exception
$b = new \Exception('hi'); // Переменная $b — объект класса Exception
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
Неполное имя - Идентификатор без разделителя пространств имён, например Foo
Полное имя - Идентификатор с разделителем пространств имён, например Foo\Bar
Абсолютное имя - Идентификатор с разделителем пространств имён, который начинается с разделителя пространств имён, например \Foo\Bar. Пространство имён \Foo — также абсолютное имя.
Относительное имя - Идентификатор, который начинается с ключевого слова namespace, например namespace\Foo\Bar.
Абсолютные имена разрешаются в имя без ведущего разделителя пространства имён. Например, \A\B разрешается в A\B.
Относительные имена разрешаются в имя с заменой ключевого слова namespace текущим пространством имён. Префикс namespace\ удаляется, если имя встречается в глобальном пространстве имён. Например, имя namespace\A внутри пространства имён X\Y разрешается в X\Y\A. То же имя в глобальном пространстве имён разрешается в A
В полных именах первый сегмент имени преобразовывается с учётом текущей таблицы импорта класса или пространства имён. Например, если пространство имён A\B\C импортировано как C, то имя C\D\E преобразуется в A\B\C\D\E.
В полных именах, если не применялось правило импорта, текущее пространство имён добавляется к имени. Например, имя C\D\E внутри пространства имён A\B разрешится в A\B\C\D\E.
Неполные имена преобразовываются с учётом текущей таблицы импорта и типа элемента. То есть имена как у классов преобразовываются с учётом таблицы импорта классов или пространств имён, имена функций — с учётом таблицы импорта функций, а константы — таблицы импорта констант. Например, при записи use A\B\C;, вызов new C() разрешается в A\B\C(). Аналогично, при записи use function A\B\foo; вызов foo() разрешается в A\B\foo.
В начало неполных имён, если не применялось правило импорта и имя относится к элементу с именем как у класса, добавляется текущее пространство имён. Например, имя класса в выражении new C() внутри пространства имён A\B разрешится в имя A\B\C
В неполных именах, если не применялось правило импорта и имя относится к функции или константе, а код лежит за пределами глобального пространства имён, имя разрешается при выполнении. Вот как разрешится вызов функции foo() в коде в пространстве имён A\B:
Выполняется поиск функции из текущего пространства имён: A\B\foo().
PHP пытается найти и вызвать функцию foo() из глобального пространства имён.
#Примеры разрешения имён
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
Источники
Связанные темы
Оператор разрешения видимости в php
Позднее статическое связывание
Методы создания экземпляра класса в php
Автоматическая загрузка классов
Наследование с помощью extends в php
Конструкторы и деструкторы в php






