【问题标题】:PHP class for all site "globals" instead of define / global所有站点“全局”的 PHP 类,而不是定义/全局
【发布时间】:2014-06-14 19:30:52
【问题描述】:

我正在努力改进我的网站引擎。所以我可以停止在函数内部设置全局 $vars

所以现在我用这个来设置我所有的全局站点变量:

define('ROOT_prefix', 'mysitename_');
define('ROOT_support', 'support@mysite.com');

我可以在任何地方访问它们。但感觉不是很好(或聪明)的做法..

我对课程知之甚少.. 但我不能/不应该为此使用课程吗?

这行得通:

class ROOT {
  public static $prefix = 'mysitename_';
  public static $support = 'support@mysite.com';
}

然后我可以在我网站上的任何地方使用它(甚至在函数内部):

echo '<h1>Please contact support at: '.ROOT::$support.' </h1>';

这是一个好方法,还是有更好的方法?

【问题讨论】:

  • 使用常量并不是一个坏习惯,如果你让事情井井有条,应该没问题。我看不出在这种情况下使用类的目的
  • 如果你有一个Config 类,你应该使用依赖注入(基本上把它传递给你需要配置的对象)。所以:public function __construct(RootConfigClass $config) { /** **/ }.

标签: php function class oop global


【解决方案1】:

如果这些“全局变量”的值在脚本的整个运行时都不会改变,那么您绝对应该使用常量,因为这正是它们的用途。

为了便于阅读,您应该将它们全部集中在一个公共包含文件中。

(以下基于cmets编辑)

由于看起来您正在使用常量来进行某种内容的本地化,因此为此使用类可能是明智的。正如我所说:在面向程序的脚本中使用常量来表示不变的值本身并不是一个坏习惯,但在本地化的上下文中,有更好的方法。

其中一个方法是创建一个具有一些静态方法的类,以根据传递的 ini 文件翻译字符串,这与其他 cmets 和此处的答案中提到的依赖注入一致。

这样一个类的示例如下所示:

class Localizer {

    public static function localize($langFile, $string) {
        if (!file_exists($langFile)) {
            throw new Exception($langFile . 'not found!');
        }

        $lang = parse_ini_file($langFile);

        return (!empty($lang[$string])) ? $lang[$string] : false;
    }

}

你可以这样使用它:

echo Localizer::localize('./english.ini', 'hello') . "\n";
echo Localizer::localize('./english.ini', 'email') . "\n";

这假设一个 ini 文件看起来像这样:

; english.ini
hello = 'Hello!'
email = 'test@test.com'

实际上,这可能是比为您的应用程序运行的每种语言释放大量常量更“正确”的方式,但是每次您需要本地化字符串时它都会打开文件,这不会最适合大型系统上的大量应用。但是,与常量一样,只要事先包含该类,您就可以在应用程序中的任何函数范围内访问该类的静态方法。无需使用常量或声明全局变量。

最合适和最有效的方法是实例化一个类,而不是使用静态方法,这会将文件加载到内存中并保存在那里,无需为每个翻译的字符串打开文件。但这将要求您能够将包含此类实例化的变量传递给代码中需要它的每个函数,或者将其声明为全局,这正是您首先要避免的。

因此,为了做到这一点,您可能需要重新构造您的代码,以允许在整个过程中进行依赖注入。

要继续使用您当前的代码和结构,您可以继续使用生成的常量,这会更加混乱,不太“合适”,并且不可扩展,但优点是您只会读取一次 ini 文件,并保持他们在记忆中。

或者您可以使用静态方法,这种方法更“合适”,但每次本地化字符串时都需要读取文件,这意味着在大型系统上,它可能会导致效率低下。但实际上,如果您的应用程序数量较少,您可能永远不会看到由此产生的问题。

这种方法的主要优点是可扩展性和简洁的代码。虽然在很短的时间内声明常量在文件打开和内存使用方面可能更有效,但在大多数情况下,它不是可扩展的,因为您可以拥有无​​限数量的字符串和语言文件,这意味着您最终可能会陷入将来每次加载应用程序时都会加载成千上万个常量。

如果您使用一个类,并且只加载该特定用户在运行时需要的文件/字符串,那么无论您支持多少种语言和字符串,都可以避免这种情况。

【讨论】:

  • 它们不会改变。作为所有页面上的第一件事,我将它们放在必需的文件中。那么使用define()可以吗?
  • 当然,这不仅没问题,而且在大多数情况下都是正确的做法。尤其是在整个应用程序是程序化的,而不是面向对象的情况下。
  • 即使我用 define() 设置了 200 个变量(常量)?我正在考虑包含语言文件: $lang = parse_ini_file('english.ini'); foreach ($lang as $key=>$value) { 定义 ($key, $value); }
  • 从文本基础配置文件中程序生成常量本身没有问题,尤其是在程序应用程序中而不是面向对象的应用程序中。我见过很多做同样的事情的应用程序。但是您应该注意执行此操作的上下文。具体来说,可能有更好的方法来处理本地化,就像您在评论中暗示的那样。你能在这里提供更多关于上下文的信息吗?你到底在用这些常量做什么,它们都是为了获取不同语言的字符串吗?
  • @mowgli 静态站点名称和句子通常用于常量,但出于本地化目的这样做是不可扩展的,因为您最终可能会创建数千个常量,并且可能必须处理为它们管理更复杂的命名约定,枚举它们的复杂方法等。它可能会变得混乱。请阅读我编辑的答案以了解其他一些选项。
【解决方案2】:

静态类变量并不比常量好。它们仍然是全局可访问的值。没有真正的变化。

如果你想改进你的风格,你应该使用依赖注入。这仅仅意味着您将函数或类所需的所有变量作为参数传递给函数/类。就是这么简单,真的。如果你想解耦你的代码,你需要在不同的部分之间创建边界。这意味着一块不会“伸出”并获得全局变量;相反,您将该片段定义为接受参数并编写另一片段将其传递给该参数。

请阅读How Not To Kill Your Testability Using Statics 了解有关此主题的深入解释。

【讨论】:

    【解决方案3】:

    您可以在需要时将变量设置为全局变量。只需使用global ${$variablename};。

    其中$variablename 包含需求变量的名称。例如,它可能是数组键或值。

    【讨论】:

      【解决方案4】:

      将您的属性声明为public 允许对其进行修改。

      如果您希望它们成为常量,就像使用 define 创建时一样,您必须将它们声明为 protected 并使用方法来访问它们:

      class ROOT {
          protected $prefix = 'mysitename_';
          protected $support = 'support@mysite.com';
      
          public static getPrefix(){
              return $this->prefix;
          }
          public static getSupport(){
              return $this->getSupport;
          }
      }
      

      这种方式实际上比使用define()实际上要好得多。

      这是向单例模式迈出的一步 (http://en.wikipedia.org/wiki/Singleton_pattern)。

      下一步是构建一个包含这些常量的Application 类(ROOT 名称听起来不错),并可能从配置文件中加载它们。

      在这个Application 单例中,您可以构建一些主要功能,例如init() 用于bootstrap,包含其他类、数据库配置、日志系统、模板系统等等...

      【讨论】:

      • 这比使用常量有什么好处?
      • @deceze 我已经解释过了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-24
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多