Пространство имён в 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

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


    Оригинал
    Поделиться публикацией

    Похожие публикации

    Комментарии 78
      +2
      Не боян-ли?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                                            Мое мнение относится только к коду выше. И никуда больше. Да, я сам использую require, когда мне надо подключить левый код к своему проекту, который не следует API фреймворка, на котором я работаю.
                                                              0
                                                              Несомненно можно было бы разобрать ваш код и, возможно, даже признать свою неправоту. Но, к сожалению, вынужден завершить наш диалог пожеланием вам отправится к определенной матери. спасибо.
                                            0
                                            Да ну..для классов уже давно используется __autoload, а если пишут на функциях все, то кто уж им виноват..
                                              0
                                              Хм, почему моветон?
                                          • НЛО прилетело и опубликовало эту надпись здесь
                                              0
                                              Вас так пугают двоеточия?
                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                0
                                                Да, хорошо, что не стали изобретать велосипед. PHPшникам легче будет понимать код на Perl.
                                                  0
                                                  Как правило для хороших PHPшников нет проблемы понимать Perl, посколько до PHP они писали на Perl :)
                                                0
                                                require_once('mycms/core.php');
                                                use MyCMS::Core::System; //импортируем только заданный класс

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


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

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

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

                                                              Самое читаемое