PHP全局常量是一个很好的现代开发实践吗?

时间:2011-07-18 16:45:43

标签: php unit-testing dependency-injection tdd

我正在开发一个具有相当大的PHP代码库的新项目。该应用程序使用了相当多的PHP常量(define('FOO', 'bar')),特别是对于数据库连接参数等。这些常量都在一个配置文件中定义,该文件基本上是应用程序中的每个类require_once()'。

几年前,这本来是完全合理的,但从那时起我就遇到了单元测试错误,这种类之间的紧密耦合真的让我烦恼。这些常量闻起来像全局变量,它们在整个应用程序代码中直接引用。

这还是个好主意吗?将这些值复制到一个对象中并使用这个对象(即Bean,我说它)通过依赖注入将它们传递给与数据库交互的类是否合理?我是否通过这样做来击败PHP常量的任何好处(比如速度或其他东西)?

我正在考虑的另一种方法是创建一个单独的配置PHP脚本进行测试。我仍然需要想办法让测试中的类使用沙箱配置脚本而不是全局配置脚本。这仍然感觉很脆弱,但它可能需要对整个应用程序进行较少的彻底修改。

6 个答案:

答案 0 :(得分:6)

在我看来,常量只能在两种情况下使用:

  • 实际常数值(即永不改变的事物,SECONDS_PER_HOUR)。
  • 与操作系统相关的值,只要应用程序可以在任何可能的情况下透明地使用该常量。

即便如此,我还是会重新考虑类常量是否更合适,以免污染常数空间。

在你的情况下,我会说常量不是一个好的解决方案,因为你会根据它们的使用位置提供替代值。

答案 1 :(得分:5)

  

这些常量闻起来像全局变量,它们直接引用[...]。将这些值复制到对象中并通过依赖注入传达它们是否合理?

绝对!我会更进一步说甚至应该避免类常量。因为它们是公开的,所以它们暴露内部并且它们是API,因此您不能轻易地更改它们而不会由于紧密耦合而破坏现有应用程序的风险。配置对象更有意义(只是不要使它成为Singleton)。

另见:

答案 2 :(得分:4)

要回答这个问题,讨论正在编写的代码的风格很重要。

PHP 5包含许多有用的OOP功能,其中一个是类常量。如果您使用的是面向对象的方法,而不是污染全局命名空间,或者担心重写常见常量,则应使用类常量。

FOO_BAR最终可能是FOO::BAR,它可以归结为您希望定义常量的范围。

如果您正在编写更多程序样式的程序,或者将程序与某些类混合,则全局常量不是问题。如果您正在使用的代码由于您正在使用的常量而变得无法管理,请尝试更改内容。否则,不要担心。

此外,类常量不允许使用函数返回值,全局常量。当你有一个在整个程序范围内永远不会改变的值,但需要生成时,这很好。

答案 3 :(得分:2)

使用常量来获取数据库连接信息非常好。这可以防止在对象本身内对其进行硬编码,因为它是只读的,所以不能覆盖这些值。

我不喜欢在对象中对我的设置进行硬编码,因为事情可能会发生变化,但如果你想这样做,那也会有效。

答案 4 :(得分:1)

如果你有PHP 5.3或更新版本,你可以使用namespace http://www.php.net/manual/en/language.namespaces.php

适用于const variable = 'something';
不幸的是,它没有define('variable','something');

命名空间中的全局变量被封装。在某些情况下,它比拥有一个物体更好。

答案 5 :(得分:0)

我不同意常数,也不同意硬编码:-)

我更喜欢表现,ZendFramework的Zend_Config_Ini。

您可以重载节,在内存中保持只读值,以及其他:

http://framework.zend.com/manual/en/zend.config.adapters.ini.html