问题
I'm working on a new project with a sizeable PHP codebase. The application uses quite a few PHP constants ( define('FOO', 'bar')
), particularly for things like database connection parameters. These constants are all defined in a single configuration file that is require_once()
'd directly by basically every class in the application.
A few years ago this would have made perfect sense, but since then I've gotten the Unit Testing bug and this tight coupling between classes is really bothering me. These constants smell like global variables, and they're referenced directly throughout the application code.
Is this still a good idea? Would it be reasonable to copy these values into an object and use this object (i.e. a Bean - there, I said it) to convey them via dependency injection to the the classes that interact with the database? Am I defeating any of the benefits of PHP constants (say speed or something) by doing this?
Another approach I'm considering would be be to create a separate configuration PHP script for testing. I'll still need to figure a way to get the classes under test to use the sandbox configuration script instead of the global configuration script. This still feels brittle, but it might require less outright modification to the entire application.
回答1:
In my opinion, constants should be used only in two circumstances:
- Actual constant values (i.e. things that will never change,
SECONDS_PER_HOUR
). - OS-dependent values, as long as the constant can be used transparently by the application, in every situation possible.
Even then, I'd reconsider whether class constants would be more appropriate so as not to pollute the constants space.
In your situation, I'd say constants are not a good solution because you will want to provide alternative values depending on where they're used.
回答2:
These constants smell like global variables, and they're referenced directly […]. Would it be reasonable to copy these values into an object and […] convey them via dependency injection?
Absolutely! I would go even further and say even class constants should be avoided. Because they are public, they expose internals and they are API, so you cannot change them easily without risking breaking existing applications due to the tight coupling. A configuration object makes much more sense (just dont make it a Singleton).
Also see:
- Brittle Global State & Singletons from
- http://misko.hevery.com/code-reviewers-guide/
回答3:
To answer this question it is important to discuss the style of code being written.
PHP 5 includes a number of useful OOP features, one of which is class constants. If you're using an object oriented approach, rather than polluting the global namespace, or worry about overriding common constants, you should use class constants.
FOO_BAR
could be FOO::BAR
in the end, it comes down to the scope of where you want the constant defined.
If you're writing a more procedural style program, or mixing procedural with some classes, global constants aren't an issue. If the code you're working on is becoming unmanageable due to the constants you're using, try changing things around. Otherwise, don't worry about it.
Additionally, class constants wont allow you to use function return values, global constants will. This is great when you have a value that wont ever be changed throughout the scope of the program, but needs to be generated.
回答4:
using constants for database connection information is perfectly fine. This prevents hard-coding it within the object itself and since its read-only you can't overwrite the values.
I'm not fond of hard-coding my settings in an object, as things can change, but if you wanted to do that, that would work just as well.
回答5:
If You have PHP 5.3 or newer, You may use namespace
.
http://www.php.net/manual/en/language.namespaces.php
It works with const variable = 'something';
Unfortunately, it doesn't wokrk with define('variable','something');
Globals in namespace are encapsulated. In some situations it is better than having an object.
回答6:
I don't agree constants, nor the hardcode :-)
I prefer, performance aside, Zend_Config_Ini from ZendFramework.
You can overload sections, maintain the values read-only in memory, and others:
http://framework.zend.com/manual/en/zend.config.adapters.ini.html
来源:https://stackoverflow.com/questions/6736330/are-php-global-constants-a-good-modern-development-practice