Я хочу аккуратно организовать свои константы.

В C ++ я бы поместил перечисления или переменные в пространство имен (или более) следующим образом:

namespace foo
{
    namespace bar
    {
        enum herp { derp, sherp, sheep };
    }

    namespace Family
    {
        const string mom  = "Anita";
        const string son  = "Bob";
        const string daughter = "Alice";
    }
}

Это дало бы мне возможность получить к ним доступ, например

int x = foo::bar::derp;
string nameOfMom = foo::Family::mom;
string nameOfSon = foo::Family::son;

Как я могу реализовать это в PHP?

0
Linuxxon 11 Мар 2014 в 15:52
Возможный дубликат PHP и перечислений
 – 
jycr753
11 Мар 2014 в 15:59

1 ответ

Лучший ответ

Что касается перечисления: в PHP нет перечисления. Вы можете написать массив (который на самом деле является HashTable внизу) или вам придется использовать (отдельное) пространство имен и / или определить для него класс, учитывая, что перечисление ближе к классу, я бы, вероятно, выбрал для последнего и напишите:

class FakeEnum
{
    const DERP = 0;
    const SHERP = 1;
    const SHEEP = 2;
}

Jycr753 уже связал этот вопрос, и он показывает, как вы могли эмулировать перечисления в PHP, но, если вы спросите меня, это просто зашло так далеко слишком . Использование ReflectionClass просто для имитации отсутствующей конструкции - все равно что модифицировать вашу машину, чтобы она могла использоваться как мотоцикл.

Переходим к пространствам имен:
Пространства имен в PHP относительно «новые» , и они не на 100% эквивалентны пространствам имен C ++. Во-первых, они не могут быть вложены так, как вы пытаетесь. Для этого вам придется прибегнуть к объявлению классов внутри заданного пространства имен и согласиться с тем, что это допускает только 1 дополнительный уровень.
Я так понимаю, вы ищете что-то вроде этого:

namespace Foo
{
    const FOOBAR = 123;
}
namespace Bar
{
    const FOOBAR = 456;
}
namespace Work
{
    const FOOBAR = __NAMESPACE__;
    include 'global_const.php';
    echo 'Global FOOBAR const is: ', \FOOBAR, PHP_EOL,
        'Foo::FOOBAR is: ', \Foo\FOOBAR, PHP_EOL,
        'Bar::FOOBAR is: ', \Bar\FOOBAR, PHP_EOL,
        'Work::FOOBAR is: ', FOOBAR, PHP_EOL;
}

Где файл global_const.php определяет глобальную константу следующим образом:

define('FOOBAR', 'global');//just to be consistent ;-P

Результат:

Global FOOBAR const is: global
Foo::FOOBAR is: 123
Bar::FOOBAR is: 456
Work::FOOBAR is: Work

Конечно, в действительности ваш код будет распределен по нескольким файлам, и чаще всего вы будете использовать только одно пространство имен для этого файла и use другие пространства имен (≃ using в C ++):

namespace My\Core\Components\Output;
use Foo,
    Bar,
    My\Core\Components\Input as CoreInput;
use External\Component\Input as HelperInput;

Несоответствия в системе пространств имен PHP хорошо задокументированы (поиск по ним в Google). Но чтобы дать вам пример, если я начну свой файл с приведенных выше утверждений, следующее утверждение:

$myVar = Foo\SOME_CONSTANT;

Решает в

global namespace (\ for short)
    ->Foo namespace
        -> SOME_CONSTANT

Но если бы я удалил use Foo, то же утверждение преобразуется в:

\
  -> My
     -> Core
         -> Components
             -> Output
                -> Foo
                   -> SOME_CONSTANT

Это может показаться вполне разумным, но одно и то же правило не применяется к основным функциям: \str_replace или str_replace оба разрешены правильно, с той лишь разницей, что последнее будет сначала выполните поиск функции с именем str_replace в текущем пространстве имен, чтобы затем вернуться к глобальному пространству имен.
Хорошо, с некоторой "доброй волей" вы можете возразить, что это тоже довольно предсказуемое поведение. К сожалению, как ни странно или злонамеренно, PHP не ведет себя таким же образом при использовании своих основных объектов (например, DateTime, stdClass, Exception или PDO ...).
Возьмем, к примеру, расширение mysqli_*: вы можете использовать его процедурный API во всех своих пространствах имен и быть счастливым туристом, но если вы предпочитаете объектно-ориентированный API, вам придется использовать операторы use , или добавьте обратную косую черту всякий раз, когда вы пишете new \mysqli().

Итак, у PHP есть свои недостатки, но, конечно, мы все это знаем, что касается вашего вопроса, я считаю, что у вас есть ответ, и для меня было бы совершенно бессмысленно продолжать эту тираду. Все, что вам нужно знать о пространствах имен, можно найти в руководстве, BTW

2
Community 23 Май 2017 в 15:04
Спасибо, думаю, мне придется иметь дело с тем фактом, что я не могу сделать так, чтобы он выглядел так же хорошо, как в C ++, и должен прибегнуть к чему-то другому. Но большое спасибо за этот пост, он все равно очень помог (:
 – 
Linuxxon
11 Мар 2014 в 17:51