Простір імен в PHP, роз'яснення. Простір імен у PHP, роз'яснення Просте використання просторів імен

(PHP 5> = 5.3.0, PHP 7)

Перед тим, як розглянути, як використовувати namespaces, це є важливою для того, щоб підтвердити, як PHP знають, що namespaced елемент вашого коду є потребою. На пряму аналогію може бути між PHP namespaces and filesystem. Там є три способи доступу до файлу в файловій системі:

  1. Relative file name like foo.txt. This resolves to currentdirectory/foo.txtДе поточнийресурс є директором поточно включений. So if the current directory is /home/foo, the name resolves to /home/foo/foo.txt.
  2. Relative path name like subdirectory/foo.txt. This resolves to currentdirectory/subdirectory/foo.txt.
  3. Absolute path name like /main/foo.txt. This resolves to /main/foo.txt.
Той самий принцип може бути використаний до namespaced elements в PHP. Для прикладу, class name can referred to in three ways:
  1. Unqualified name, або unprefixed class name like $a = new foo(); or foo::staticmethod(); currentnamespace, це resolves to currentnamespace\foo foo. Один міхур: unqualified names for functions and constants буде відповідати Global functions and constants if the namespaced function or constant is not defined. Використовуйте namespaces: fallback до глобальної функції/постійної інформації.
  2. Qualified name, або prefixed class name like $a = новий subnamespace\foo(); or subnamespace\foo::staticmethod();. If the current namespace is currentnamespace, це resolves to currentnamespace\subnamespace\foo. If the code is global, non-namespaced code, this resolves to subnamespace\foo.
  3. Fully qualified name, або prefixed name with global prefix operator like $a = new \currentnamespace\foo(); or \currentnamespace\foo::staticmethod();. Це завжди resolves to literal name specified in the code, currentnamespace\foo.

Here is an example of the three kinds of syntax in actual code:

namespace Foo \ Bar \ subnamespace ;

const FOO = 1;
function foo () ()
class foo
{
}
?>

namespace Foo \ Bar;
include "file1.php";

const FOO = 2;
function foo () ()
class foo
{
static function staticmethod () ()
}

/* Unqualified name */
foo(); foo:: staticmethod(); echo FOO;

/* Qualified name */
subnamespace \foo(); // resolves to function Foo\Bar\subnamespace\foo
subnamespace \foo::статичнийметод (); // resolves to class Foo\Bar\subnamespace\foo,
// method staticmethod
echo subnamespace \FOO; // resolves to constant Foo\Bar\subnamespace\FOO

/* Fully qualified name */
\foo\bar\foo(); // resolves to function Foo\Bar\foo
\ Foo \ Bar \ foo :: staticmethod (); // resolves to class Foo\Bar\foo, method staticmethod
echo \ Foo \ Bar \ FOO ; // resolves to constant Foo\Bar\FOO
?>

Зверніть увагу, що для користування будь-яким кузовом класу, функцією або постійною, повністю зображений name може бути використаний, так як \strlen() or \Exception or \INI_ALL. ?>

PHP, починаючи з версії 5.3, подарував нам простір імен. З того часу йде десь мляве, а десь бурхливе обговорення, як же це простір імен використовувати?
Деякі фреймворки, такі як Symphony, Laravel, і, звичайно ж, Zend взяли цю технологію на озброєння.
Все це більш менш вписалося в схему MVC. Залишилася одна, напевно вічна, дискусія, якою ж має бути головна шлюбна пара програми - Модель та Контролер?
Одні нам кажуть, що Модель має бути огрядною і товстою і при ній стрункий і тонкий Контролер. Одним словом – матріархат.
Інші, навпаки, вважають, що Контролер повинен усім керувати і наказувати, тому він виходить ґрунтовний, вгодований. І при ньому худенька, струнка Модель, завдання якої зводиться до подай-принеси. Такий патріархат.
То що краще в схемі MVC? Патріархат чи матріархат?
Погляньмо на це з точки зору побудови сімейного осередку на основі демократії. І хай Namespace нам у цьому допоможе.

Нам не подобаються товсті, незграбні Контролери, які, як слон у посудній крамниці, необережно можуть розчавити всі додатки.
Нам не подобаються також товсті моделі. Ну, а кому вони подобаються? Вони повинні бути гідними подіуму!
Давайте спробуємо за допомогою Namespace, як із гарним сватом, створити гармонійну родину.

Спочатку створимо каркас програми. Хоч як це банально, але нехай це буде блог.

Ми створили основну структуру, де:

  • Blog - це сховище нашої програми;
  • Views і Templates - сховище уявлень та шаблонів;
  • Utility – сховище спільних бібліотек;
  • index.php – bootstrap скрипт;
  • Post - ось тут і має відбутися сімейна ідилія Контролера та Моделі.

З index.php все просто:

run(); /* * end of index.php */

Визначаємо потрібні шляхи та створюємо автозавантажувач.
Автозавантажувач завантажує необхідні класи, які розташовані в ієрархії папок згідно з простором імен класу. Наприклад, клас BlogPostServicesView буде розшукуватися у Blog/Post/Services.
А ось і перша зустріч із Namespace.
При старті index.php ми створюємо екземпляр програми Blog, клас якого завантажується з Blog/Blog.php.
Подивимося на нього.

Post = New Post (); ) public function run() ( $this->post->view->all(); ) )//end class Blog

При створенні класу Blog ми впроваджуємо в нього клас Post з Namespace BlogPost та автозавантажувач завантажує його з Blog/Post/Post.php.
Напевно, цей клас і можна назвати Контролером,

view = new View(); ) )//end class Post

Сутність Post включає в себе:
- структуру самого запису даних - BlogPostEntitiesPostEntity.php

Служби, що обслуговують запити Контролера - BlogPostServicesView.php (одна зі служб, наприклад)

db = New DB(); )//end __construct public function all() ( $posts = $this->db->survey(); Contemplate::compose(array("header" => "header", "main" => "main", "footer" => "footer",), array("posts" => $posts, "title" => "Viper site",)); ) )//end class PostView

Система взаємодії з базою даних - BlogPostRepositoriesDB.php - ось вона, наша тонка, витончена Модель,
Тільки подай-принеси, і нічого більше!

dbh = новий PDO("mysql:host=localhost;dbname=test", $user, $pass, array(PDO::ATTR_PERSISTENT => true)); ) catch (PDOException $e) ( echo "Error!: " . $e->getMessage() . "
"; die(); ) )//end __construct public function survey() ( $query_view = $this->dbh->prepare("SELECT * from posts"); $query_view->execute(); return $query_view- >fetchAll(PDO::FETCH_CLASS, "BlogPostEntitiesPostEntity"); )//end survey )//end class Db

В результаті нам вдалося створити структуру програми, де всі компоненти добре пов'язані, при цьому ми досягли чіткого поділу класів, де кожен клас виконує своє завдання. Контролер у нас тонкий і водночас потужний. Модель підходить йому. Ідеальна сім'я!
І все завдяки Namespace.

Не сперечаюся, у багатьох випадках зручний фреймворк. Але подивіться, Namespace вам нічого не нагадує?
Чіткий поділ на класи, строга, і водночас гнучка, повністю підпорядкована розробнику ієрархія каталогів і класів.
Відсутність часом такого вагомого доважування у вигляді сотень файлів та класів у вигляді фреймворку.
Відсутність прокрустового ложа правил взаємодії класів та компонентів.

Стаття навіяна роздумами на цю тему Taylor Otwell, автора фреймворку Laravel, за що йому велике спасибі.
Адреса вихідних прикладів на GitHub.

Нещодавно інкапсулював свій проект у namespace і зіткнувся із проблемою відсутності нормальної документації. Все, що вдалося знайти, датується приблизно 2009 роком, а на дворі майже 2012… У знайденому матеріалі купа неробочих місць, які використовують те, що в нинішній версії php немає. У зв'язку з цим хочу трохи висвітлити це питання.
Отже, що таке Namespace або простір імен? Велика wikipedia визначає їх так:

Простір імен (англ. namespace) - кілька, під яким мається на увазі модель, абстрактне сховище або оточення, створене для логічного угрупування унікальних ідентифікаторів (тобто імен). Ідентифікатор, визначений у просторі імен, асоціюється із цим простором. Один і той самий ідентифікатор може бути незалежно визначений у кількох просторах. Таким чином, значення, пов'язане з ідентифікатором, визначеним в одному просторі імен, може мати (або не мати) таке ж (а скоріше, інше) значення, як і такий самий ідентифікатор, визначений в іншому просторі. Мови з підтримкою просторів імен визначають правила, що вказують, до якого простору імен належить ідентифікатор (тобто його визначення).

Все ясно? Насправді, все просто. До версії 5.3 в php існувало всього два простори - глобальний (в якому виконувався ваш основний код) і локальний (в якому визначалися змінні функції).

З версії 5.3 все змінилося. Тепер можна визначити свій простір імен, в якому будуть існувати ваші класи методи і т.д.


Сподіваюся, стало трохи зрозуміліше.

Я спеціально обізвав класи однаково. Так вони визначені в різних просторах, це два різних класи, незважаючи на однакові імена. Основний скрипт, як і раніше, функціонує в глобальному просторі, тут нічого не змінилося і в ньому, як і раніше, можна визначати класи та функції. То навіщо тоді потрібні простору? Перш за все, для впевненості в тому, що коли ви підключаєте файл з яким-небудь фреймворком або бібліотекою, ваші класи не перевизначать класи фреймворку або навпаки.

Для того, щоб використовувати класи визначені у своєму просторі імен, необхідно в потрібному місці (я зазвичай віддаю перевагу робити це на початку файлу) імпортувати певний вами простір у глобальний для цього використовується ключове слово use

Увага:з якихось своїх підстав php не допускає використання ключового слова useу блоках умов та циклах

Візьмемо приклад із картинок і втілимо його в коді:

Увага:ключове слово namespase має бути розташоване на самому початку файлу відразу після
файл A.php
файл B.php
Можливий альтернативний синтаксис:
Рекомендується оголошувати кожен простір імен окремому файлі. Хоча можна і в одному, але це не рекомендується!
Тепер перемістимося до третього файлу, в якому функціонуватиме наш основний скрипт
index.php
здавалося б у чому перевага, тільки коду додалося, проте це не зовсім так, трохи далі я наведу приклад класу автозавантаження, з яким рядки, що підключають файли з класами, будуть непотрібні.
А тепер звернемося до наших класів

Увага:використання оператора дозволу області видимості (::) у просторах імен php не допускається! Єдине навіщо він годиться - це звернення до статичним методам класу і константам. Спочатку хотіли використовувати для простору імен саме його, але потім через проблеми відмовилися. Тому конструкція виду A:: A:: say (); неприпустима та призведе до помилки.

Для просторів імен необхідно використовувати символ зворотного слішу "\"
Увага:щоб уникнути непорозумінь, необхідно екранувати цей символ при його використанні в рядках: "\\"

Простір імен можна вкладати один в одного, доповнимо наш файл A.php:
а в індексі напишемо таке:

Важливим моментом є використання аліасів для імпортованих просторів. Можна було написати A\subA::say(); погодьтеся, щоразу писати повні шляхи до просторів важко для того, щоб цього уникнути були введені аліаси. При компілюванні відбудеться наступне замість аліасу sub буде підставлено A\subA, таким чином ми отримаємо виклик A\subA::say();

А що ж тоді відбувається при виклику функцій, визначених у глобальному просторі? PHP спочатку шукає функцію всередині того простору, де ви зараз працюєте, і якщо не знаходить, то звертається до глобальної області видимості. Для того, щоб відразу вказати, що ви використовуєте глобальну функцію, необхідно перед нею поставити зворотний сліш.

Для того, щоб не було проблем з автозавантаженням класів з просторів, файлову систему потрібно організувати аналогічно організації просторів. Наприклад, є у нас коренева папка classes, де і зберігатимуться наші класи, тоді наші простори можуть бути організовані таким чином
classes\A\A.php
classes\A\sub\A.php(підпростір sub винесемо в окремий файл)
classes\B\B.php

У php є магічна константа __NAMESPACE__, яка містить ім'я поточного простору.

А тепер про автозавантаження.

Наведений нижче клас не мій, я тільки зробив його робітником і трохи удосконалив узятий звідси.
Увага:Для того, щоб ваші класи завантажувалися, ім'я класу повинно збігатися з ім'ям файлу!

" .$file ." in " .$filepath)); if (file_exists($filepath)) ( if(Autoloader::debug) Autoloader::StPutFile(("підключили " .$filepath)); $flag = FALSE; require_once($filepath); break; ) Autoloader::recursive_autoload($file, $path2, &$flag); /Log/Log.html"; $file = fopen($dir, "a"); flock($file, LOCK_EX); fwrite($file, ("║" .$data ."=>" .date(" d.m.Y H:i:s") ."

" .PHP_EOL)); flock($file, LOCK_UN); fclose ($file); ) ) \spl_autoload_register("yourNameSpace\Autoloader::autoload"); )
Якщо подивитися на імена класів, які приходять для завантаження, то буде видно, що кожен клас передує префіксу з простору імен, що вказано в use. Саме тому рекомендую використовувати розташування файлів у каталогах аналогічно до простору імен, це прискорює пошук до однієї-двох ітерацій.

Тепер наш індекс можна написати так:
тепер всі класи та інтерфейси, які ви будете використовувати будуть завантажені автоматично.

Для демонстрації деяких динамічних можливостей мови з просторами оголосимо ще один клас:
test.php

Index.php
sayName("test"); //а можна так test\sayName("test2"); //або так $obj::sayName("test"); //а можна так test::sayName("test2");

Сподіваюся, що моя стаття буде корисна будь-кому.

Змінна визначає значення, але може бути посиланням на іншу змінну та мати її значення. У процесі виконання алгоритму змінна зазвичай набуває безліч різних значень. Константа зберігає лише одне значення. Об'єкт непередбачуваний: йому властиво мати структуру, зміст та безліч особливостей.

Простір імен - це сукупність змінних, констант, об'єктів, функцій та інших конструкцій, створених розробником, куди можна посилатися через ім'я цього простору імен.

Імена: сфера опису даних та алгоритмів

Імена елементів (змінних, констант, об'єктів, функцій та інших конструкцій розробника) ніколи не перетинаються. Будь-який збіг імен PHP інтерпретує як серйозну помилку, а у випадках, коли він не може однозначно ідентифікувати проблему, розробник отримує код, що працює не так, як було задумано, або біле поле у ​​браузері.

Усі імена всіх даних мають бути унікальними, оскільки простір глобальний. Імена об'єктів та функцій також не повинні повторюватися, але сфера глобальної видимості переривається у тілах методів об'єктів та функцій. Тут функціонує своє, локальне місце імен і ніщо не заважає називати щось усередині так само, як зазначено зовні.

Наведений приклад - класика, якщо не звертати уваги на ключове слово namespace: все, як завжди. Працює другий include. Префікс NameSpaceTwo перед іменами функцій уточнює, з якої вставки береться код.

Якщо з першої функції усунути ключове слово global і операцію $iExt = 1; перенести на рядок вище, то значення змінної 100 нічого очікувати знати ні перша функція, ні друга.

Простір імен: безліч сфер опису

У наведеному прикладі є спільний файл, який використовує дві вставки. Кожна вставка має однакову функцію scCheckName(). Яку їх вибрати, вирішує програміст з допомогою імені простору, яке актуально у потрібний час у потрібному місці коду.

Той факт, що те саме ім'я присутнє в загальному коді (після злиття вставок) не призводить до помилки з тієї простої причини, що кожен файл вставки позначений своїм власним унікальним ім'ям.

У першому файлі все, що буде описано, зв'язується з ім'ям NameSpaceOne. У другому файлі всі описи будуть прив'язані до імені NameSpaceTwo.

Дозволяється будь-яке дублювання імен в обох файлах, але в кожному з них будь-яке ім'я елемента (змінної, константи, об'єкта, функції) має бути унікальним.

У цьому прикладі зміна імені простору імен у виклику функції scCheckName() позбавила змінну $iExt другого простору імен від зміни. Саме тому у прикладі спеціально виділено слово "змінена" - зміна насправді не відбулася. Значення змінної залишилося тим самим.

Тестування та множинне проектування

Ці найпростіші приклади показують: можна легко спростити розробку складних проектів, підвищити ефективність, продуктивність та прискорити роботу. Однозначно відразу з'явилися перші ідеї застосування простору імен:

  • безпечне тестування скриптів – шляхом заміни "робітників" просторів на тестові аналоги;
  • безпечне проектування великими колективами розробників – шляхом надання їм "індивідуальних" просторів опису елементів.

Насправді простір імен має значно важливіше значення. Мова PHP, простір імен і кожен елемент опису (змінна, константа, об'єкт...) вже давно надали розробнику можливість самостійно маніпулювати синтаксисом і семантикою.

Конструкції мови та загальне правило сучасного програмування: "зрозуміло" - виконано - є протиріччя - "білий екран" на професійного розробника "не діє".

Багато програмістів навіть не знають, де шукати повідомлення PHP про помилку, коли в браузері нічого немає (чисте біле поле). На певному етапі свого розвитку програміст мислить синтаксисом та семантикою PHP, «працює» автоматом і результат: власний синтаксис та власна семантика в межах дозволеного.

Білий екран – одразу однозначна реакція професійного програміста та помилка ліквідована. Навіщо витрачати час на дебаггер та перегляд лога помилок?

Об'єкти, масиви та простори імен

Можна сказати, що змінні, константи та функції - це минуле століття, але вони використовуються у розробці об'єктів. Хороший код - це коли алгоритм представлений об'єктами, що взаємодіють, а не послідовністю коректних конструкцій.

Якщо використовувати масиви об'єктів, маніпулювати ідеєю стека і останнім (першим) елементом масиву, то можна отримати динаміку: об'єкти самі "вирішують", як повинен працювати функціонал сайту в залежності від ситуації, що складається.

На PHP простір імен - це змінна особливий, представлена ​​власним унікальним ім'ям, часто складно складеним. Ім'я простору імен використовується в коді. Якщо це рядок, то один простір можна замінити на інший під час виконання скрипта.

Якщо імена namespace PHP використовує як значення змінних, це ще більш семантично навантажений синтаксис, ще сильніший, ніж масиви об'єктів.

Об'єкт - це структура та зміст, які характеризуються єдністю. Простір імен – це безліч об'єктів, елементів та зв'язків між ними.

Не можна проводити експерименти на працюючій системі, але завдяки namespace PHP надає можливість моделювати реальну працюючу систему в іншому просторі для цілей:

  • подальшого розвитку;
  • тестування;
  • технічного обслуговування та ін.

Якщо абстрагуватися від синтаксису, запропонованого розробниками PHP, і уявити простору імен як глобальні складні системи об'єктів, горизонти можливостей розширюються багаторазово.

Синтаксис та застосування простору імен

Слово namespace PHP приймає лише в першому рядку коду кожного файлу. Всі описи повинні йти лише за ним. Синтаксис включає лише ім'я, позначене у звичайному розумінні імені.

Істотно використовувати правильні слова, що відбивають сенс. Краще, коли ім'я довге, але в ньому є те, що дає чітке розуміння, про який простір йдеться, що воно робить, що описує, що приймає або для чого створено.

Простір можуть бути вкладені один в одного до нескінченності, але цим не слід зловживати. Ім'я має бути зрозумілим, вкладеність – обґрунтована, а послідовність імен просторів повинна мати логіку.

У застосуваннях use і namespace PHP допускає складне кодування, але завжди, коли є така можливість, краще обійтися простим варіантом.

Загальне правило: namespace - опис і це один файл, use - це імпорт простору в скрипт використання та призначення йому псевдоніма (короткого посилання).

Простий приклад автозавантаження класів (об'єктів)

У задачі є об'єкт для маніпулювання рядками, стилями оформлення елементів сторінки (опис CSS), об'єкт дати, файлової системи та бази даних. Сенс реалізації - створити за цими п'ятьма позиціями прості інтерфейси з метою використання необхідних можливостей лише через методи цих об'єктів.

Жодного прямого використання функцій та конструкцій мови не допускається. У такому завданні використовується на PHP автозавантаження класів. Namespace розглядається як сукупність об'єктів, що знаходяться в певному місці файлової системи. Зазвичай, всі об'єкти розміщуються у файловій системі за змістом, папками та у файлах з певною назвою.

У коді ліворуч позначено створення необхідних п'яти об'єктів, але саме вони знаходяться, не зазначено. У коді справа наведено текст автозавантажувача (основний скрипт), який при завантаженні класів (об'єктів) автоматично підставляє потрібний шлях до місця розміщення об'єкта та розширення файлу.

Приклад безлічі просторів імен

Бібліотека PhpOffice / PhpWord – якісний приклад використання складної ієрархії безлічі просторів імен. Папка елементів містить практично весь спектр елементів, доступних для формування документа *.docx (MS Word), інші папки містять необхідний інструментарій роботи з елементами, параграфами і таблицями.

Власне, бібліотека поміщена в папку проекту з тієї причини, що простір функціональності PhpOffice / PhpWord потрібно доповнити конкретним інструментарієм і зрештою створити власний варіант аналогічного продукту.

Завантаження безлічі класів різних просторів імен

Використання PHP namespace autoload, коли необхідно завантажувати безліч класів, а ієрархія розробленої системи об'єктів досить складна і уявити її складно, призводить до необхідності створення жорстких конструкцій.

Орієнтація розробника (що використовує продукт для продовження робіт) можлива лише в контексті семантики (розуміння проекту), яка представлена ​​належними поєднаннями слів, що відображають реальне значення та взаємозв'язки об'єктів.

Необхідність застосування бібліотеки в індивідуальному проекті призводить до вирішення завдання, як поєднувати простори імен розробника та авторів PhpOffice/PhpWord. Найкращим є розміщення даного продукту (його просторів та об'єктів) у власному просторі проекту.

Істотно відзначити, що без модифікації просторів імен цього продукту лише на рівні його абстрактних елементів і завантаження класів обійтися не вдасться. Це свідчить, що на PHP namespace використання внутрішніх просторів імен може бути виконане недостатньо абстрактно та універсально.

Файлова система та локалізація просторів

Фактично, простору імен - це «накреслення» шляху файлової системи до потрібного об'єкту. Використання імен файлів як імена об'єктів - природно і звично. Використання імен папок як іменування просторів імен – об'єктивно.

«Дерев'яна» організація інформації досить громіздка у застосуванні та ускладнює розробку, але вона є природним уявленням для систем об'єктів.

Проблема полягає в тому, що етап розробки представлений певним редактором коду, який поєднує в собі і видиме уявлення папок та зміст конкретної папки, але ще немає такого редактора, який би забезпечував наскрізний рух об'єктами та папками.

Проблема абстрактності та універсальності

Прийнято свідомістю розробника та об'єктивно насправді:

  • дає абстракцію та можливість маніпулювати інформацією відповідно до її реальної семантики;
  • простору імен відображають положення скриптів, об'єктів та частково сенсу проекту у файловій системі

Фактично, з'єднавши абстракцію ООП на імена об'єктів (файли) та наклавши її на файлову систему (папки) з адекватним формуванням імен namepace (шляхи + імена), можна керувати формуванням просторів імен у процесі виконання скрипту.

Програмування вже набуло потужної динаміки розвитку, але, якщо перекласти процес і навантаження етапу розробки з текстового редактора (у якому створюються скрипти та розміщуються по деревах папок) на ідею формування такого коду, який сам себе дозволяє вдосконалювати та розміщувати у потрібному місці файлової системи – програмування підніметься на нову висоту.