测试函数是否从静态上下文中运行


Test if a function is run from a static context

我正在编写一个PHP类,并包含了一些用于快速访问的静态函数,因为它们通常使用并且函数简单。但是,它们确实使用其中的一个对象来访问数据库。在整个代码中,我可能会从静态和非静态上下文中使用这些静态方法,因此我希望能够测试是否从静态或非静态上下文中调用函数,以便避免在从非静态上下文中调用函数(此实例对象和要静态使用的函数中的实例对象)时创建重复对象。是否有任何方法,我可以在函数中测试这一点,以便我可以使用实例对象,如果函数从非静态上下文中调用,并创建它自己的对象,如果函数从静态上下文中调用?

代码示例:

class MyClass {
  private $db;
  function __constuct(){
    $this->db = new DBConnect();
  }
  public static function myFunction(){
    if(/* Is static */){
      $db = new DBConnect();
    } else {
      $db =& $this->db;
    }
    // Do processing with $db, etc.
  }
}

当一个方法被声明为静态时,不仅魔术变量$this不可用(返回NULL),但它是无法判断函数是否实际上是从静态上下文中调用的。回溯意味着对于静态代码方法,调用$object-> Method()是内部翻译为className::method()在运行时

http://php.net/manual/en/language.oop5.static.php

只有在不强制方法仅为静态的情况下才能检查非静态访问。从函数声明中去掉static关键字,并使用:

进行测试
public function myFunction(){
    if(!isset($this)) {

(它仍然可以作为静态函数调用,即使您没有这样声明它)

底线-不要创建只包含静态函数的类。它不是OOP,它只是你旧的过程代码伪装成OOP

如果你静态执行函数,没有$this,因为没有对象。您最终也将使private $db成为静态变量,并将其用作self::$db

也就是说,我建议放弃这种模式,并编写如下:

class Foobar
{
   protected $_connection = null;
   public function __construct( DBConnect $db )  
   {
      $this->_connection = $db;
   }
   public function some_function()
   {
      $db = $this->_connection;
      // Do processing with $db, etc.
   }
}

你像这样使用这个类:

$db = new DBConnection(  /* your password , user , host , etc. */);
$stuff = new FooBar( $db );
$stuff->some_function();
$blah = new DifferentClass( $db );

这样就可以与所有需要它的类共享相同的连接。现在FooBar类不负责连接或者必须知道您的连接细节。

解决方案1:将$db变量设为私有,并通过getter使用它

解决方案2:在数据库端实现一个单例模式

即使从实例调用静态方法(不推荐),也不需要访问$this,所以你的类是致命的。

class sns {
   public static function moo() {
      var_dump($this->fng);
   }
   public function goo() {
      var_dump($this);
   }
}
sns::moo();
$_ = new sns;
$_->moo();
$_->goo();

正如另一个海报从php手册中指出的。

然而,

$db可以静态定义,所以它只需要创建一次,而不管对象是否是实例。