PHP

индекс
206,76

Пространство имён в php 5.3 и php 6

Пространство имён (namespace/package) знакомо java и c# программистам, теперь доступно и в php. Нужно оно для того, что-бы не писать длинные перефиксы к названиям классов, как сейчас делается в Zend, PEAR и других библиотеках и платформах для совместимости.

Вместо этого классы, функции, интерфейсы (абстрактные классы) и константы могут быть объединены в одно пространство имён. Глобальные переменные в это пространство не входят.

Простой пример

Определяется пространство ключевым словом namespace

//определяем класс в пространстве
namespace MyCMS::Core;
class System{}

Использование этого класса в третьих библиотеках осуществляется ключевым словом use

require_once('mycms/core.php');
use MyCMS::Core::System; //импортируем только заданный класс
$objSystem=new System;

Как вы уже догадались, разделитель :: работает так же как и вызов статических методов, разделяя уровень пространства имён и конкретный класс. Уровень вложённости пространств можно использовать наряду с модульностью библиотеки, например реализовать пространства Database::MySQL::Adapter и Database::Oracle::Adapter.

Новые возможности и новые проблемы

Если в пространстве имён имя класса перезаписывает ранее объявленный глобальный класс или функцию, то к нему по прежнему можно обратится через ::SomeClassName, однако не зная к какой именно реализации программист обращается может вызвать проблемы. Например можно переобъявить стандартные php функции, поменять sin() и cos() местами, что-бы кому-то жизнь мёдом не казалась.

Для отладки существует рабочая константа __NAMESPACE__.

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

A::B() // вызов функции B из namespace A
A::B() // вызов статичного метода B у класса A

Читайте по теме:

Оригинал
+28
22 июня 2008, 19:37
42

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

+2
anycolor #
Не боян-ли?

По-моему лучше в оригинале прочитать - например тут - http://ilia.ws/files/phpquebec_php53.pdf
0
mastikhin #
Спасибо, приятная статья. Многим полезно будет новое узнать.
Один только вопрос - почему на в блоге PHP? Перенесли бы.
0
tot_ra #
перевёл
0
anycolor #
И вопрос в догонку - может автор знает какие-то ньюансы работы с неймспейсами в 5.3 и 6 версии, все-таки лично мне хочется больше уже ньансов, а не простого переписывания того, что написано в принципе везде про появление неймспейсов в новых версиях..

Согласен, вопрос актуальный, но нужно как-то больше конкретики.
0
tot_ra #
увы, рабочий хостинг всё ещё на 5.2.5 стоит
0
anycolor #
Очень жаль :(
0
Radeon #
Установите 5.3 в качестве cgi... И будет счастье ;-)
0
oRb #
Мда, чет они перемудрили с двумя двоеточиями. Неужели сложно было придумать новое обозначение? типо >> или три двоеточия)
0
tot_ra #
А разве >> не бинарный сдвиг?
0
oRb #
точняк, вылетело из головы) тогда :>:
0
stas_agarkov #
точку надо!! как в нормальных ЯВУ.
0
Caesar #
зачем? двоеточие на эту роль хорошо подходит, в то же время, неймспейсы - имхо недостаточный повод чтобы вносить в язык новый синтаксический элемент.

Неоднозначности между функцией в неймспейсе и статическим методом, которая приведена в посте, для интерпретатора, на самом деле, не существует - он не позволит вам иметь в пределах одного пространства имет два одинаковых идентификатора. Что же касается удобства для программиста - ну, извиняйте, думать надо как неймспейсы называть это раз....

и два: в чем концептуальная разница между статическим методом и функцией в неймспейсе, а? (-:

А, ну и ещё: в питоне, например, для обращения к методам объектов и к объектам из ругого пространства имён тоже используется одинаковый синтаксис (точка) и ничего, никто пока не умер (-:
0
tot_ra #
Метод связан с классом или объектом, тогда как функция от объекта не зависит
http://en.wikipedia.org/wiki/Method_(computer_science)
http://en.wikipedia.org/wiki/Function_(computer_science)
0
Caesar #
не-не. я спрашивал конкретно про статические методы.

с точки зрения вызывающего в чем разница?

насколько важно мне знать чем концептуально отличаются класс C и неймспейс N в этих примерах:

C::get_instance();
N::get_instance();
0
hlomzik #
self
как я понимаю, в неймспейсах он не доступен
0
Caesar #
снаружи когда я вызываю это, зачем мне знать как оно внутри работает?
0
tot_ra #
1. В статичных методах при наследовании насколько я помню можно обращаться к родительским методам через parent::метод
2. Обращение к статичным параметрам класса (правда с наследием там вроде баги были)
Как я понимаю c namespace такого не проделаешь, хотя выглядит оно одинаково и вероятно реализуется тоже.
0
Caesar #
1. снаружи когда я это вызываю, зачем мне знать как оно работает внутри?
2. см. п. 1

Естественно, если я хочу наследоваться, то разница есть и я вынужден буду узнать как оно устроено, однако вопрос стоял не так.
0
whoiskoss #
Это преемственность С++
0
corristo #
в C++ такая же неоднозначность существует. И ничего, живут.
+1
anycolor #
Проблема надуманна, это факт. Просто такое положение дел не привычно в PHP, так, как неймспейсов до этого вообще не было, поэтому многих смущает то, как это выглядит и выдумывают проблему на пустом месте.
НЛО прилетело и опубликовало эту надпись здесь
0
megahertz #
интересно, когда версии с поддержкой неймспейсов станут распространены на различных хостингах, имена классов в Zend Framework остануться такими же, или все переведут на неймспейсы...
0
f33l #
а о совместимости ты подумал?
0
megahertz #
ZF активно развивается, нельзя тащить с собой кучу старого кода только для совместимости, а то как у microsoft получится. конечно, в случае таких тяжелых нововведений нужно дать достаточно времени разработчикам на переход
0
f33l #
вот именно, что достаточно, а это растянется очень надолго..
0
Caesar #
префиксы в именах старых классов ради обратной совместимости - не такое уж большое зло, как мне кажется.
+1
Xobb #
require_once — моветон в php 5+, есть SPL. А так ниче нового не сказали, анонс namespace был давно.
0
tot_ra #
Вы имеете ввиду autoload? Помоему он тоже require_once использует.
+1
anycolor #
Он использует то, что напишет программист. __autoload() - это просто функция, а не магия какая-то :)

function __autoload($className) {
$fileName = $className.'.class.php';
require PATH_ROOT."classes/".$fileName;
}

Простейший пример.
0
tot_ra #
Я такую конструкцию и использую, вот и интересуюсь - можно ли и как попроще (и куда уж проще)?
0
anycolor #
Тогда я не совсем понял, что значит "Вы имеете ввиду autoload? Помоему он тоже require_once использует. ".

Ответ на Ваш вопрос - "а куда еще проще?".
0
tot_ra #
Я не складирую все файлы в одну папку если вы подразумеваете autoload по умолчанию
0
anycolor #
Ну на самом деле я не подразумевал, у меня как раз в разных папках.

Я делаю это приблизительно так:

function __autoload($className) {
$locations = array('forum', 'fun', 'gallery', 'leecher', 'soap', 'common');

$fileName = $className.'.class.php';
foreach ($locations as $path) {
if (file_exists(PORTAL_PATH_ROOT."classes/".$path."/".$fileName)) {
require PATH_ROOT."classes/".$path."/".$fileName;
break;
}
}
}

Вы же можете массив сделать в конфиге или из базы выбирать, в зависимости от того, как храните информацию о модулях.
0
anycolor #
PORTAL_PATH_ROOT = PATH_ROOT - плохо отредактировал.
0
tot_ra #
Видите - всё правильно, вы тоже require используете, а что Xobb имел ввиду я не понимаю..
0
Xobb #
Я имею ввиду SPL-register. Оно позволяет написать правило загрузки классов. Наглядный пример здесь. Да, в принципе используется require, но только один раз и больше его в коде использовать не надо. Своим комментарием я имел ввиду, что если мы уж настолько продвинуты чтобы использовать namespace то было б хорошо научится и делать autoload.
0
beq #
Спасибо за информацию! Давно пишу на php, а про эту фичу не знал. Буду разбираться, надоело писать в стиле php4
0
zarincheg #
По поводу spl_autoload_register, я его использовал одно время, но потом отказался в пользу статичного(единственного) автолоада с проверками дирректорий и наличия файлов, поскольку динамическая регистрация уж очень много ресурсов жрет.
0
Angerslave #
Не понимаю, чем require плох. Да, автолоад, несомненно, рулит, но, имхо, это какая-то глупая религия - сокращать количество require до 1 в проекте... Конечно, 500 require это тоже перебор, но autoload так или иначе выполняет столько же require(достаточно глянуть по профайлеру), хоть они и сосредоточены в одном методе.
0
ashofthedream #
Все просто - уменьшение сложности. Тебе не надо задумыватся о том как подключать, где и по какому принципу классы, ты решаешь это все зарание и больше не задумываешься.
0
Angerslave #
Хм, тут такие хитрые коды пишут, лишь бы не писать лишние require... Может я читаю как-то не так, но мне кажется, что слишком категорично высказано, что на весь проект должен быть 1 require и тот в автолоаде... Я и сам активно юзаю autoload, но не вижу смысла сокращать количество require до 1-2, имхо, разумный предел - 5-10, хотя всё зависит от архитектуры проекта.
0
gro #
А разве исполнение php-файлов ограничивается только подключением классов?
0
Xobb #
Простите меня пожалуйста, вы сноб и приебываетесь.
require_once('mycms/core.php');
use MyCMS::Core::System; //импортируем только заданный класс
$objSystem=new System;

Мое мнение относится только к коду выше. И никуда больше. Да, я сам использую require, когда мне надо подключить левый код к своему проекту, который не следует API фреймворка, на котором я работаю.
0
gro #
Несомненно можно было бы разобрать ваш код и, возможно, даже признать свою неправоту. Но, к сожалению, вынужден завершить наш диалог пожеланием вам отправится к определенной матери. спасибо.
0
anycolor #
Да ну..для классов уже давно используется __autoload, а если пишут на функциях все, то кто уж им виноват..
0
Angerslave #
Хм, почему моветон?
0
Xobb #
посмотрите мой комментарий.
0
morg0th #
Уважаемый Ларри Уолл - чтото мне это все напоминает =)
0
tot_ra #
Вас так пугают двоеточия?
0
morg0th #
Наоборот, Уважаемый! Радуют =) Изобретение велосипеда направляется к своему логическому завершению =)
0
FloppyFormator #
Да, хорошо, что не стали изобретать велосипед. PHPшникам легче будет понимать код на Perl.
0
AleksDesker #
Как правило для хороших PHPшников нет проблемы понимать Perl, посколько до PHP они писали на Perl :)
0
prudis #
require_once('mycms/core.php');
use MyCMS::Core::System; //импортируем только заданный класс

А разве require_once не "импортировало" уже все то, что было в mycms/core.php?
0
hlomzik #
use автоподстановку делает.
Как я понимаю, new Class() будет на самом деле делать new MyCMS::Core::System::Class()...
Имхо, бесполезная штука — нагляднее использовать полное название неймспейса или хотя бы алиас...
0
caezar #
во всех языках сделали такую бесполезную штуку. вот глупцы.
0
Angerslave #
Вы о чём? Это чтобы конфликтов имён классов в разных неймспейсах небыло. Ну и чтобы, используя много классов из неймспейса, не писать много раз подряд всю вереницу вложености NS.
0
caezar #
я о сарказме на тему того, на что отвечал
0
Angerslave #
Пардон, не сразу уследил...
0
hlomzik #
я только про use ;) и я ступил, признаю, сам ведь буду использовать...
0
hlomzik #
Хотелось бы, например, знать
  • как можно в автолоаде узнать запрашиваемый неймспейс или как можно (и можно ли) делать локальные (в рамках одного неймспейса) автолоады
  • можно ли перемещаться по иерархии неймспейсов? потому как если нет, то лучше было бы сделать вложенные классы для static обращений
  • как понять фразу мануала «К примеру, если пространство имён A::B::C импортировано, new C() будет транслировано как new A::B::C().», если new A::B::C() обращается к неймспейсу A::B
0
ashofthedream #
По поводу первого: в автолоад имя класса приходит полностью My::Namespace::For:MyClass.
0
hlomzik #
я подозревал, спасибо )
0
beq #
Хороший язык - php, сейчас правда перешел с него на Java и уже плотно занимаюсь только ею, но такое чувство что концептуально (т.е. за исключением некоторых моментов синтаксиса и конечно же рантайма) между ними скоро не будет различий ;)
0
ptalus #
боюсь, что основное концептуальное различие - строгая типизация, навряд ли будет добавлено в PHP
0
beq #
А вот это бооольшой вопрос )) На крайняк будет 2 явы - со строгой типизацией и без строгой типизации )))
0
trix #
вообще-то уже есть, в виде Groovy )
0
beq #
Не, ну груви это все же не php ))
0
trix #
это сильно круче :) так сказать, ява мутирует в питона и руби
0
gro #
Нашли чего бояться :)
–1
afi #
пространства имен штука очень полезная. Но, как это обычно бывает у разработчиков PHP, хотели как лучше - получилось как всегда: какой то корявый синтаксис System::Core. А ведь можно было сделать очень просто и красиво:


namespase System.Core
{
    class MyClass()
    {}
}
0
nekufa #
к сожалению, точка уже давно забита под конкатенацию строк :(
0
jay #
уверяю, нет никакой технической проблемы, что точка конкатенирует строки. На месте имени нэймспэйса же не expression.

А в принципе точка как конкатенация строки — бред полный, плюс куда лучше был бы.
0
nekufa #
Хватит говорить со мной как с разработчиком пхп!
0
afi #
ну в общем, дело не в точке, а в единообразности - содержимое класса находится между фигурными скобками{}, так почему же сам класс не поместить в пространство имен между {}.
0
neon #
Постепенно php превращается в perl. Это не может не радовать. Так глядишь и оператор =~ появится вместно ужасных preg_*
0
Angerslave #
Хм, Namespace'ы двигают PHP в сторону Perl? Сомневаюсь, думаю, NS это серьёзная необходимость - во многих продвинутых языках(с точки зрения реализации возможностей ООП) Namespace'ы уже давно реализованы, так что PHP, пусть и слегка запоздало, просто подтягивается до неписаных стандартов. имхо.
0
neon #
Сам писал только на 4 пхп, поэтому не видел раньше в пхп оператора use =)

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