调用静态方法在PHP 5.3晚静态绑定辛格尔顿方法

问题描述:

我有一个包含这些方法的抽象类:调用静态方法在PHP 5.3晚静态绑定辛格尔顿方法

<?php 
public static function getInstance() { 
    $me = get_called_class(); 
    if (!isset(self::$_instances[$me])) { 
     $ref = new ReflectionClass($me); 
     self::$_instances[$me] = $reflection_object->newInstance(); 
     self::$_instances[$me]->init(); 
    } 
    return self::$_instances[$me]; 
} 

public function __construct() { 
    $me = get_class($this); 
    if(isset(self::$_instances[$me])) { 
     throw new Exception('The singleton class has already been instantiated!'); 
    } else { 
     self::$_instances[$me] = $this; 
     $this->_className = $me; 
    } 
} 

它的工作原理完全按照我同胞的单身中具体使用时的预期。试图从不共享同一父类的子类中获取实例时遇到问题。

我的堆栈跟踪是:

Fatal error: Call to undefined method Keywords_AdminMenu_OptionsTable::init() in D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-content\plugins\LocalGiant_WPF\library\LocalGiant\Module\Abstract.php on line 149 

Call Stack: 
    0.0012  331664 1. {main}() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-admin\admin.php:0 
    0.7772 3224864 2. do_action() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-admin\admin.php:151 
    0.7774 3225792 3. call_user_func_array() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-includes\plugin.php:405 
    0.7774 3225808 4. Keywords_AdminMenu->showMenu() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-includes\plugin.php:405 
    0.7796 3227016 5. Keywords_AdminMenu_View::showMenu() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-content\plugins\LocalGiant_WPF\modules\Keywords\AdminMenu.php:29 
    0.7821 3240776 6. Keywords_AdminMenu_OptionsTable->prepareItems() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-content\plugins\LocalGiant_WPF\modules\Keywords\AdminMenu\View.php:25 
    0.7822 3241824 7. LocalGiant_Module_Abstract->getInstance() D:\webroot\domains\dev.slbmeh.com\htdocs\wordpress\wp-content\plugins\LocalGiant_WPF\modules\Keywords\AdminMenu\OptionsTable.php:90 

的init()方法是在超类的Singleton一个抽象方法。类Keywords_AdminMenu_OptionsTable是来自WordPress的WP_List_Table的一组独立库中的一个类的子类。

类Keywords_AdminMenu_Options表的细分副本如下:发现

<?php 
class Keywords_AdminMenu_OptionsTable extends WP_List_Table { 

    public function __construct(){ 
     global $status, $page; 

     //Set parent defaults 
     parent::__construct(array(
      'singular' => 'module', 
      'plural' => 'modules', 
      'ajax'  => false 
     )); 

    } 

    function prepareItems() { 

     /* SNIP - Prepare my SQL query. */ 

     $moduleDatabase = Database_Module::getInstance(); 

     $current_page = $this->get_pagenum(); 

     $keywords = $moduleDatabase->simpleQuery($sql, $moduleLoader->getMyNamespace()); 

     /* SNIP - Handle my SQL data. */ 

    } 
} 

WP_List_Table的内容在这里:http://core.trac.wordpress.org/browser/tags/3.2.1//wp-admin/includes/class-wp-list-table.php

+0

你可以显示WP_List_Table吗? – Pete171

+0

这是一个相当大的类,所以我会给它一个链接。 http://core.trac.wordpress.org/browser/tags/3.2.1//wp-admin/includes/class-wp-list-table.php并将其添加到问题中。 –

+0

我不明白这个问题。 – Gordon

原来我的代码没有的getInstance声明为静态的。这段代码让我们更深入地了解静态绑定如何影响绑定。

<pre><?php 

class Singleton_Super { 

    protected static $_instances = array(); 
    protected $_className; 

    public function singletonSuperTest() { 

     $getCalled = get_called_class(); 
     $getClass = get_class($this); 
     $getName = $this->_className; 

     echo "\nSingleton_Super::singletonSuperTest()\n"; 
     echo "\tget_called_class() = $getCalled\n"; 
     echo "\tget_class(\$this) = $getClass\n"; 
     echo "\t_className() = $getName\n"; 

    } 

    public function whatsMyName() { 
     echo "\nSingleton_Super::whatsMyName()\n\t$this->_className\n"; 
    } 

    public static function getInstance() { 
     $me = get_called_class(); 
     echo "\nSingleton_Super::getInstance()\n\tget_called_class() = $me\n"; 
     if (!isset(self::$_instances[$me])) { 
      $ref = new ReflectionClass($me); 
      self::$_instances[$me] = $ref->newInstance(); 
     } 
     return self::$_instances[$me]; 
    } 

    public function __construct() { 
     $me = get_class($this); 
     echo "\nSingleton_Super::__construct()\n\tget_called_class() = $me\n"; 
     if(isset(self::$_instances[$me])) { 
      throw new Exception("The Singleton class, '$me', has already been instantiated."); 
     } else { 
      self::$_instances[$me] = $this; 
      $this->_className = $me; 
     } 
    } 

    public function __clone() { 
     trigger_error("Cloning is not allowed.", E_USER_ERROR); 
    } 

    public function __wakeup() { 
     trigger_error("Unserializing is not allowed.", E_USER_ERROR); 
    } 

} 

class Singleton_Child extends Singleton_Super { 

    public function singletonTest() { 

     $getCalled = get_called_class(); 
     $getClass = get_class($this); 
     $getName = $this->_className; 

     echo "\nSingleton_Child::singletonTest()\n"; 
     echo "\tget_called_class() = $getCalled\n"; 
     echo "\tget_class(\$this) = $getClass\n"; 
     echo "\t_className() = $getName\n"; 

    } 

} 

class Outer_Concrete_Super { 

    protected $_className; 

    public function __construct() { 
     $me = get_class($this); 
     $this->_className = $me; 
     echo "\nOuter_Concrete_Super::__construct()\n\tget_class(\$this) = $me\n"; 
    } 

    public function whatsMyName() { 
     echo $this->_className; 
    } 

    public function concreteSuperTest() { 

     $getCalled = get_called_class(); 
     $getClass = get_class($this); 
     $getName = $this->_className; 

     echo "\nOuter_Concrete_Super::concreteSuperTest()\n"; 
     echo "\tget_called_class() = $getCalled\n"; 
     echo "\tget_class(\$this) = $getClass\n"; 
     echo "\t_className() = $getName\n"; 

    } 

    public function superUseSingletonChild() { 
     $singleton = Singleton_Child::getInstance(); 
     $singleton->singletonTest(); 
    } 

} 

class Outer_Concrete_Child extends Outer_Concrete_Super { 

    public function concreteTest() { 

     $getCalled = get_called_class(); 
     $getClass = get_class($this); 
     $getName = $this->_className; 

     echo "\nOuter_Concrete_Super::concreteSuperTest()\n"; 
     echo "\tget_called_class() = $getCalled\n"; 
     echo "\tget_class(\$this) = $getClass\n"; 
     echo "\t\$_className = $getName\n"; 

    } 

    public function bigTest() { 
     $singleton = Singleton_Child::getInstance(); 
     $singleton->whatsMyName(); 
     $singleton->singletonSuperTest(); 
     $singleton->singletonTest(); 
    } 

} 

echo "\n*****************************\n"; 
echo "*  Constructors  *\n"; 
echo "*****************************\n\n"; 

$singleP = Singleton_Super::getInstance(); 
$singleC = Singleton_Child::getInstance(); 
$outerP = new Outer_Concrete_Super; 
$outerC = new Outer_Concrete_Child; 

echo "\n*****************************\n"; 
echo "* Third Party Class Testing *\n"; 
echo "*****************************\n\n"; 

$outerP->concreteSuperTest(); 
$outerC->concreteSuperTest(); 
$outerC->concreteTest(); 
$outerC->bigTest(); 

echo "\n*****************************\n"; 
echo "*   Singleton   *\n"; 
echo "*****************************\n\n"; 

$singleP->whatsMyName(); 
$singleP->singletonSuperTest(); 
$singleC->whatsMyName(); 
$singleC->singletonSuperTest(); 
$singleC->singletonTest(); 

?> 
</pre> 

返回结果:

***************************** 
*  Constructors  * 
***************************** 


Singleton_Super::getInstance() 
     get_called_class() = Singleton_Super 

Singleton_Super::__construct() 
     get_called_class() = Singleton_Super 

Singleton_Super::getInstance() 
     get_called_class() = Singleton_Child 

Singleton_Super::__construct() 
     get_called_class() = Singleton_Child 

Outer_Concrete_Super::__construct() 
     get_class($this) = Outer_Concrete_Super 

Outer_Concrete_Super::__construct() 
     get_class($this) = Outer_Concrete_Child 

***************************** 
* Third Party Class Testing * 
***************************** 


Outer_Concrete_Super::concreteSuperTest() 
     get_called_class() = Outer_Concrete_Super 
     get_class($this) = Outer_Concrete_Super 
     _className() = Outer_Concrete_Super 

Outer_Concrete_Super::concreteSuperTest() 
     get_called_class() = Outer_Concrete_Child 
     get_class($this) = Outer_Concrete_Child 
     _className() = Outer_Concrete_Child 

Outer_Concrete_Super::concreteSuperTest() 
     get_called_class() = Outer_Concrete_Child 
     get_class($this) = Outer_Concrete_Child 
     $_className = Outer_Concrete_Child 

Singleton_Super::getInstance() 
     get_called_class() = Singleton_Child 

Singleton_Super::whatsMyName() 
     Singleton_Child 

Singleton_Super::singletonSuperTest() 
     get_called_class() = Singleton_Child 
     get_class($this) = Singleton_Child 
     _className() = Singleton_Child 

Singleton_Child::singletonTest() 
     get_called_class() = Singleton_Child 
     get_class($this) = Singleton_Child 
     _className() = Singleton_Child 

***************************** 
*   Singleton   * 
***************************** 


Singleton_Super::whatsMyName() 
     Singleton_Super 

Singleton_Super::singletonSuperTest() 
     get_called_class() = Singleton_Super 
     get_class($this) = Singleton_Super 
     _className() = Singleton_Super 

Singleton_Super::whatsMyName() 
     Singleton_Child 

Singleton_Super::singletonSuperTest() 
     get_called_class() = Singleton_Child 
     get_class($this) = Singleton_Child 
     _className() = Singleton_Child 

Singleton_Child::singletonTest() 
     get_called_class() = Singleton_Child 
     get_class($this) = Singleton_Child 
     _className() = Singleton_Child 

在哪里,如果你改变从静态上的getInstance绑定您收到的结果:

***************************** 
*  Constructors  * 
***************************** 


Singleton_Super::getInstance() 
     get_called_class() = Singleton_Super 

Singleton_Super::__construct() 
     get_called_class() = Singleton_Super 

Singleton_Super::getInstance() 
     get_called_class() = Singleton_Child 

Singleton_Super::__construct() 
     get_called_class() = Singleton_Child 

Outer_Concrete_Super::__construct() 
     get_class($this) = Outer_Concrete_Super 

Outer_Concrete_Super::__construct() 
     get_class($this) = Outer_Concrete_Child 

***************************** 
* Third Party Class Testing * 
***************************** 


Outer_Concrete_Super::concreteSuperTest() 
     get_called_class() = Outer_Concrete_Super 
     get_class($this) = Outer_Concrete_Super 
     _className() = Outer_Concrete_Super 

Outer_Concrete_Super::concreteSuperTest() 
     get_called_class() = Outer_Concrete_Child 
     get_class($this) = Outer_Concrete_Child 
     _className() = Outer_Concrete_Child 

Outer_Concrete_Super::concreteSuperTest() 
     get_called_class() = Outer_Concrete_Child 
     get_class($this) = Outer_Concrete_Child 
     $_className = Outer_Concrete_Child 

Singleton_Super::getInstance() 
     get_called_class() = Outer_Concrete_Child 

Outer_Concrete_Super::__construct() 
     get_class($this) = Outer_Concrete_Child 
Outer_Concrete_Child 

Fatal error: Call to undefined method Outer_Concrete_Child::singletonSuperTest() in C:\inetpub\vhosts\BetterOffLocal.com\httpdocs\wp-content\plugins\LocalGiant_WPF\Singleton-Test.php on line 128 

我希望这个答案可以帮助别人了。或者至少提供有关如何解决此类问题的见解。

+0

除非这是一个答案,它应该是你的问题的更新 – Gordon

+0

是的,我解决了我自己的问题。 –