我什么时候在 php 中使用静态变量/函数?

我正在使用 PHP 刷新自己对 OOP 的认识,我看到了一个将函数和/或变量设置为静态的例子。何时以及为什么要将变量/函数设置为 static?我已经做了其他语言,并不真正记得曾经使用静态,我从来没有发现一个真正的目的。我知道它的作用,但为什么不用变量呢?

56929 次浏览

静态函数和变量用于访问全局范围内的变量/函数,如下所示:

echo myClass::myVariable;
echo myClass::myFunction();

当某些东西是静态的时候,它可以在任何地方被访问,并且非常类似于过程类型函数,除了它可以使用 self 并且包含在 class 作用域中之外。

class myClass{
static $myVariable = "myVar";
static function myFunction()
{
return "myFunc";
}
}

使用这种方法的一种方法是只保留一个类的一个实例,或者一个 Singleton 方法。

class myClass
{
static $class = false;
static function get_connection()
{
if(self::$class == false)
{
self::$class = new myClass;
}
else
{
return self::$class;
}
}
private function __construct()
{
// my constructor
}
// Then create regular class functions.
}

因为它有一个私有的构造函数,所以不能用 new操作符实例化它,所以必须调用 myClass::get_connection()来获得一个类。该函数可以创建新类(因为它是该类的成员)。然后它将该类存储在一个静态变量中,如果再次调用该函数,它将简单地返回创建的类。

最后,static 关键字用于在引用范围时保持静态。这意味着您不希望因为当前范围而发生任何“变化”。虽然 Singleton 方法稍微扩展了这一点,但它始终保持相同的思想,即您总是拥有相同的类,而不管您在哪个范围内。

PHP 文档
静态关键字
范围解析运算符

堆栈溢出知识
如何避免使用 PHP 全局对象
不使用全局变量在 PHP 函数之间共享变量
使类中的每个函数都可以访问全局变量
用于数据库连接的全局或单例
PHP 类: 何时使用: : vs.-> ?

这是一个随机的,虽然 相当好地描述了静态方法和实例方法之间的差异

来自邮件:

实例方法是实例方法,因为它们依赖于状态 实例方法绑定到一个 因为方法调用的行为 依赖于该特定实例的状态。

将方法声明为静态时,将该方法定义为 类方法应用于类,而不是应用于任何 由类方法引发的行为 不依赖于特定实例的状态 方法不能依赖于实例的状态,因为缺少静态方法 而是类方法的行为 要么取决于所有对象在类级别共享的状态, 或者独立于任何国家。

如果一个方法依赖于一个对象实例的状态,那么它应该是一个 如果一个方法对于所有或没有实例的 类,并且不依赖于对象状态,它应该是静态的 实例方法是最常用的 方法对于实用工具类和工厂类非常有用 其他用途。

当希望使用不绑定到实例的方法/变量时,可以使用 静电干扰。这种情况可能发生在:

  • 这与您的目的和实例没有任何关系(对于不支持 Java 等面向对象的语言中的工具箱是有用的,但对于 PHP 则没有用处)。

  • 您希望控制对实例的访问。通常,您要处理的实例在编写代码时没有定义,而是在执行时定义。单例模式是最好的例子。可以使用静态方法作为工厂,根据上下文创建对象或与其他实例共享资源。例如: 一个静态成员可以提供对数据库层的访问,这样应用程序的一部分就可以从任何地方访问同一个数据库层,并且它的打开/关闭没有冲突。

  • 性能很重要,而且该方法将被执行很多次。在这种情况下,您将节省一些 CPU 时间,防止解释器在每次调用时查找成员到实例。但是,如果 pers 成为这样一个问题,以至于您需要采用这种解决方案,那么可能需要重新考虑您的体系结构,或者为代码的关键部分使用一种更快的语言绑定。

  • 您有一个与类型相关但将应用于其他类型的方法。将方法写入第一个类型的声明中是有意义的,但是将其设置为静态的,因为它期望另一个类型的实例。

最好的例子是 String 解析器:

class MyObject
{
static function parse($str)
{
$obj = new MyObject();
// some parsing/setting happens here
return $obj;
}
}


// you create an object "MyObject" from a string, so it's more obvious
// to read it this way :
$new_obj = MyObject::parse("This a description of a super cool object");

另外,如果一个方法经常被调用,并且执行相同的操作,那么对于缓存来说也是非常有用的,例如:

/**
* Returns true if the user is logged in through shibboleth
*
* @return boolean true on success, else false
*/
protected function is_logged_in() {


//Check shibboleth headers
if (!empty($_SERVER['HTTP_SHIB_IDENTITY_PROVIDER']) || !empty($_SERVER['Shib-Identity-Provider'])) {
if (!empty($_SERVER[$this->core->dbconfig("shib_auth", self::SHIB_AUTH_CONFIG_UID)])) {
return true;
}
}
return false;
}

这个方法将在我的框架中经常调用,并且在那里它将为每次调用都为我的配置 $_ SERVER 键进行数据库查找

因此,当页面被处理时,我可能在一个页面加载中调用10次,它将有10个数据库调用,但我将其更改为:

/**
* Returns true if the user is logged in through shibboleth
*
* @return boolean true on success, else false
*/
protected function is_logged_in() {
static $logged_in = null;
if($logged_in != null) {
return $logged_in;
}


//Check shibboleth headers
if (!empty($_SERVER['HTTP_SHIB_IDENTITY_PROVIDER']) || !empty($_SERVER['Shib-Identity-Provider'])) {
if (!empty($_SERVER[$this->core->dbconfig("shib_auth", self::SHIB_AUTH_CONFIG_UID)])) {
$logged_in = true;
return true;
}
}
$logged_in = false;
return false;
}

所以如果我登录并缓存结果它只检查一次每个页面加载的正常行为。下次它将只返回缓存的值。 我经常使用这个特性来获得更好的性能。

希望这个能帮上忙。

访问: http://verraes.net/2014/06/when-to-use-static-methods-in-php/

静态方法只不过是带名称空间的全局函数。名称空间,我想我们都同意,是伟大的。至于全局函数: 我们一直在使用它们。PHP 中的本机函数构成了我们的基本构建块。

一般使用静态函数可以优化速度以及内存和方法的范围,不应该改变其应该是静态的性质,你可以访问对象的静态属性,方法没有启动它们,这样节省了内存的同时。

如果您希望与所有实例共享数据,比如当前执行时创建的数量的计数器。

静态元素有许多有用的特性。

  1. 首先,它们可以从脚本中的任何地方获得(假设您可以访问该类)。这意味着您可以访问功能,而无需将类的实例从一个对象传递到另一个对象,或者更糟糕的是,将实例存储在一个全局变量中。

  2. 其次,静态属性可用于类的每个实例,因此可以设置希望对类型的所有成员可用的值。

  3. 最后,不需要实例来访问静态属性或方法这一事实可以使您避免纯粹为了获得一个简单的函数而实例化对象。