所有网站的PHP类"全局"而不是定义/全局

时间:2014-06-14 19:30:53

标签: php function class oop global

我正在努力改进我的网站引擎。所以我可以停止在函数

中设置全局$ 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>';

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

4 个答案:

答案 0 :(得分:2)

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

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

(根据评论进行编辑)

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

其中一个就是创建一个带有一些静态方法的类来根据传入的ini文件转换字符串,这与其他注释和答案中提到的依赖注入一致。

这样一个类的例子看起来像这样:

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文件,并保持他们在记忆中。

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

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

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

答案 1 :(得分:1)

静态类变量并不比常量更好。它们仍然是全球可访问的价值观。没有真正的改变。

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

请阅读How Not To Kill Your Testability Using Statics以获取有关此主题的深入说明。

答案 2 :(得分:-1)

将您的属性声明为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,包含其他类,数据库配置,日志系统,模板系统等等。上...

答案 3 :(得分:-1)

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

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