Я бы хотел аккуратно организовать мои константы.
В 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?
Что касается перечисления: в 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 search them). Но чтобы привести вам пример, если я запустил свой файл с приведенными выше инструкциями, следующий оператор:
$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 OO, вам придется use
операторы use
или добавлять обратную косую черту всякий раз, когда вы написать new \mysqli()
.
Итак, у PHP есть свои недостатки, но, конечно, мы все так много знаем, что касается вашего вопроса, я считаю, что у вас есть ответ сейчас, и для меня продолжение этого разговора было бы совершенно бессмысленным. Все, что вам нужно знать об пространствах имен, можно найти в руководстве, BTW