Являются ли глобальные константы PHP хорошей современной практикой развития?
Я работаю над новым проектом с большой кодовой базой PHP. Приложение использует довольно много PHP-констант (define('FOO', 'bar')
), особенно для таких вещей, как параметры подключения к базе данных. Эти константы определены в одном файле конфигурации, который require_once()
'd непосредственно по существу каждому классу приложения.
Несколько лет назад это имело бы смысл, но с тех пор я получил ошибку Unit Testing, и эта плотная связь между классами действительно беспокоит меня. Эти константы пахнут глобальными переменными, и они ссылаются непосредственно на код приложения.
Это еще хорошая идея? Было бы разумно скопировать эти значения в объект и использовать этот объект (т.е. Bean - там, я сказал), чтобы передать их через инъекцию зависимостей классам, которые взаимодействуют с базой данных? Могу ли я победить какие-либо преимущества PHP-констант (скажем, скорость или что-то еще), выполнив это?
Другим подходом, который я рассматриваю, было бы создание отдельной конфигурации PHP script для тестирования. Мне все равно нужно понять, как тестировать классы для использования конфигурации песочницы script вместо глобальной конфигурации script. Это все еще кажется хрупким, но для всего приложения может потребоваться менее полная модификация.
Ответы
Ответ 1
По-моему, константы должны использоваться только в двух обстоятельствах:
- Фактические постоянные значения (т.е. вещи, которые никогда не изменятся,
SECONDS_PER_HOUR
).
- OS-зависимые значения, если константа может быть использована прозрачно приложением, в любой возможной ситуации.
Даже тогда я бы пересмотрел, будут ли более удобными константы классов, чтобы не загрязнять пространство констант.
В вашей ситуации я бы сказал, что константы не являются хорошим решением, потому что вы захотите предоставить альтернативные значения в зависимости от того, где они используются.
Ответ 2
Эти константы падают как глобальные переменные, и они ссылаются непосредственно [...]. Было бы разумно скопировать эти значения в объект и [...] передать их через инъекцию зависимостей?
Абсолютно! Я бы пошел еще дальше и сказал, что даже классовые константы следует избегать. Поскольку они являются общедоступными, они выставляют внутренние компоненты, и они являются API, поэтому вы не можете легко их изменить, не рискуя нарушить существующие приложения из-за жесткой связи. Объект конфигурации имеет гораздо больший смысл (просто не делайте его Singleton).
Также смотрите:
Ответ 3
Чтобы ответить на этот вопрос, важно обсудить стиль написания кода.
PHP 5 включает в себя ряд полезных функций ООП, один из которых является константами класса. Если вы используете объектно-ориентированный подход, а не загрязняете глобальное пространство имен или беспокоитесь о переопределении общих констант, вы должны использовать константы класса.
FOO_BAR
может быть FOO::BAR
в конце, это сводится к области, где вы хотите, чтобы константа была определена.
Если вы пишете более процедурную программу стиля или смешиваете процедуры с некоторыми классами, глобальные константы не являются проблемой. Если код, над которым вы работаете, становится неуправляемым из-за констант, которые вы используете, попробуйте изменить ситуацию. В противном случае, не беспокойтесь об этом.
Кроме того, константы класса не позволят вам использовать возвращаемые значения функции, глобальные константы будут. Это замечательно, когда у вас есть значение, которое никогда не будет изменено в рамках всей программы, но должно быть сгенерировано.
Ответ 4
использование констант для информации о подключении к базе данных отлично. Это предотвращает жесткое кодирование его внутри самого объекта, и поскольку его только для чтения вы не можете перезаписать значения.
Я не люблю жестко кодировать мои настройки в объекте, поскольку все может измениться, но если вы захотите это сделать, это будет работать так же хорошо.
Ответ 5
Если у вас PHP 5.3 или новее, вы можете использовать namespace
.
http://www.php.net/manual/en/language.namespaces.php
Работает с const variable = 'something';
К сожалению, это не wokrk с define('variable','something');
Глобалы в пространстве имен инкапсулируются. В некоторых ситуациях это лучше, чем наличие объекта.
Ответ 6
Я не согласен с константами, а не с жестким кодом:-)
Я предпочитаю, производительность в стороне, Zend_Config_Ini из ZendFramework.
Вы можете перегружать разделы, поддерживать значения, доступные только для чтения, в памяти и другие:
http://framework.zend.com/manual/en/zend.config.adapters.ini.html