如何在变量类上调用静态方法?
Posted
技术标签:
【中文标题】如何在变量类上调用静态方法?【英文标题】:How can I call a static method on a variable class? 【发布时间】:2010-10-13 03:30:02 【问题描述】:我正在尝试创建某种从给定变量加载和实例化类的函数。像这样的:
<?php
function loadClass($class)
$sClassPath = SYSPATH."/classes/$class.php";
if (file_exists($sClassPath))
require_once($sClassPath);
$class = $class::getInstance();
?>
如果我这样使用它:
<?php
loadClass('session');
?>
它应该包含并实例化会话类。
顺便说一句:静态 getInstance 函数来自此代码:
<?php
function getCallingClass()
$backtrace = debug_backtrace();
$method = $backtrace[1]['function'];
$file = file($backtrace[1]['file']);
$line = $file[($backtrace[1]['line'] - 1)];
$class = trim(preg_replace("/^.+?([A-Za-z0-9_]*)::$method\(.*$/s", "\\1\\2", $line));
if(! class_exists($class))
return false;
return $class;
class Core
protected static $instances = array();
public static function getInstance()
$class = getCallingClass();
if (!isset(self::$instances[$class]))
self::$instances[$class] = new $class();
return self::$instances[$class];
?>
问题是,现在在类中使用函数的方式是这样的:
<?php
$session = session::getInstance();
?>
但是现在我想将它构建到一个函数中,这样我就再也不用使用那行代码了。 我只是说 loadClass('session'); 而且我可以使用 $session->blablablafunction();
【问题讨论】:
【参考方案1】:在变量类名上调用静态函数显然在 PHP 5.3 中可用:
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
http://php.net/manual/en/language.oop5.static.php
我自己现在肯定可以使用它。
在此之前,您不能真正假设要加载的每个类都设计为单例。只要您使用的是
function loadClass($class)
$sClassPath = SYSPATH."/classes/$class.php";
if (file_exists($sClassPath))
require_once($sClassPath);
$class = new $class;
或
只需加载类而不从中创建对象。然后在 loadClass() 函数之外对那些意味着是单例的调用“::getInstance()”,对那些不是单例的调用“new”。
尽管正如其他人之前指出的那样,__autoload() 可能对您很有效。
【讨论】:
【参考方案2】:我认为后期静态绑定对你有用。在每个类的构造中:
class ClassName
public static $instances = array();
public function __construct()
self::$instances[] = $this;
然后... 这是我创建的自动加载器。看看这是否解决了你的困境。
// Shorten constants for convenience
define ('DS', DIRECTORY_SEPARATOR);
define ('PS', PATH_SEPARATOR);
$template = "default";
// Define an application path constants
define ('APP_ROOT', realpath('.').DS);
define ('VIEW', APP_ROOT . 'Views' . DS);
define ('MODEL', APP_ROOT . 'Models' . DS);
define ('CONTROLLER', APP_ROOT . 'Controllers' . DS);
define ('TEMPLATE', VIEW."templates".DS.$template.DS);
define ('CONTENT', VIEW."content".DS);
define ('HELPERS', MODEL."helpers".DS);
// Check if application is in development stage and set error reporting and
// logging accordingly
error_reporting(E_ALL);
if (defined('DEVELOPMENT'))
ini_set('display_errors', 1);
else
ini_set('display_errors', 0);
ini_set('log_errors', 'On');
ini_set('error_log', APP_ROOT.'error.log');
$paths = array(APP_ROOT, VIEW, MODEL, CONTROLLER, TEMPLATE, CONTENT, HELPERS);
// Set the include path from Config Object
set_include_path(implode(PS, $paths));
// Autoloader
function __autoload($class)
require_once $class.'.php';
return;
那么你要做的就是
$var = new ClassName();
但你必须在路径中有一个名称为 php 的文件 类名.php 其中 ClassName 与您要实例化的类的名称相同。
【讨论】:
【参考方案3】:在我的脑海中,需要测试、验证等:
<?php
function loadClass($className)
if (is_object($GLOBALS[$className]))
return;
$sClassPath = SYSPATH."/classes/$className.php";
if (file_exists($sClassPath))
require_once($sClassPath);
$reflect = new ReflectionClass($className);
$classObj = $reflect->newInstanceArgs();
$GLOBALS[$className] = $classObj;
?>
【讨论】:
【参考方案4】:看起来您正在与 PHP 的当前实现静态绑定作斗争,这就是您使用 getCallingClass 越过障碍的原因。我可以根据经验告诉您,您可能应该放弃尝试通过静态方法将实例化放在父类中。它最终会给你带来更多的问题。 PHP 5.3 将实现"late static binding" 并且应该可以解决您的问题,但这显然没有帮助。
使用 kodisha 提到的自动加载功能结合可靠的 Singleton 实现可能会更好。我不确定您的目标是否是语法糖,但它认为从长远来看您会做得更好,以避免尝试保存几个字符。
【讨论】:
【参考方案5】:为什么不使用 __autoload() 函数?
http://www.php.net/autoload
然后您只需在需要时实例化对象。
【讨论】:
【参考方案6】:你可以使用call_user_func()
:
$class = call_user_func(array($class, 'getInstance'));
第一个参数是 callback
类型,在这种情况下包含类名和方法名。
【讨论】:
以上是关于如何在变量类上调用静态方法?的主要内容,如果未能解决你的问题,请参考以下文章