我有一个包含这些方法的抽象类:
<?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 :(得分:2)
事实证明我的代码没有将getInstance声明为static。这段代码可以更深入地了解静态绑定如何影响绑定。
<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
我希望这个答案可以帮助别人。或至少提供有关如何解决此类问题的见解。