php 如何在变量类上调用静态方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/642391/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I call a static method on a variable class?
提问by talentedmrjones
I'm trying to make some kind of function that loads and instantiates a class from a given variable. Something like this:
我正在尝试制作某种从给定变量加载和实例化类的函数。像这样的东西:
<?php
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = $class::getInstance();
}
}
?>
If I use it like this:
如果我像这样使用它:
<?php
loadClass('session');
?>
It should include and instantiate the session class.
它应该包含并实例化会话类。
BTW: the static getInstance function comes from this code:
顺便说一句:静态 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];
}
}
?>
The thing is that right now the way to use the functions in a class is this:
问题是现在在类中使用函数的方法是这样的:
<?php
$session = session::getInstance();
?>
But now I want to build that into a function so that I never again have to use that line of code. I just say loadClass('session'); and than I can use $session->blablablafunction();
但是现在我想将它构建到一个函数中,这样我就再也不必使用那行代码了。我只是说 loadClass('session'); 然后我可以使用 $session->blablablafunction();
回答by talentedmrjones
Calling static functions on a variable class name is apparently available in PHP 5.3:
在变量类名上调用静态函数显然在 PHP 5.3 中可用:
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
http://php.net/manual/en/language.oop5.static.php
http://php.net/manual/en/language.oop5.static.php
Could definitely use that right now myself.
我自己现在绝对可以使用它。
Until then you can't really assume that every class you are loading is designed to be a singleton. So long as you are using < 5.3 you'll have to just load the class and instantiate via the constructor:
在那之前,您不能真正假设您加载的每个类都设计为单例。只要您使用 < 5.3,您就必须加载类并通过构造函数实例化:
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = new $class;
}
}
}
OR
或者
Just load the class without creating an object from it. Then call "::getInstance()" on those meant to be singletons, and "new" on those that are not, from outside of the loadClass() function.
只需加载类,而无需从中创建对象。然后从 loadClass() 函数外部调用“::getInstance()”对那些意味着是单例的,并在那些不是的“new”上调用。
Although, as others have pointed out earlier, an __autoload() would probably work well for you.
尽管正如其他人之前指出的那样, __autoload() 可能对您有用。
回答by Greg
You can use call_user_func():
您可以使用call_user_func():
$class = call_user_func(array($class, 'getInstance'));
The first argument is a callbacktype containing the classname and method name in this case.
callback在这种情况下,第一个参数是包含类名和方法名的类型。
回答by kodisha
Why not use __autoload() function?
为什么不使用 __autoload() 函数?
then you just instantiate object when needed.
然后您只需在需要时实例化对象。
回答by Barrett Conrad
It looks like you are fighting PHP's current implementation static binding, which is why you are jumping through hoops with getCallingClass. I can tell you from experience, you should probably abandon trying to put instantiation in a parent class through a static method. It will cause you more problems in the end. PHP 5.3 will implement "late static binding"and should solve your problem, but that obviously doesn't help now.
看起来您正在与 PHP 的当前实现静态绑定作斗争,这就是您使用 getCallingClass 跳过箍的原因。我可以从经验告诉你,你应该放弃尝试通过静态方法将实例化放在父类中。最终会给你带来更多的问题。PHP 5.3 将实现“后期静态绑定”并且应该可以解决您的问题,但这显然现在无济于事。
You are probably better off using the autoload functionality mentioned by kodisha combined with a solid Singleton implementation. I'm not sure if your goal is syntactic sugar or not, but it think you will do better in the long run to steer clear of trying to save a few characters.
您可能最好将 kodisha 提到的自动加载功能与可靠的单例实现结合使用。我不确定你的目标是否是语法糖,但它认为从长远来看你会做得更好,避免试图保存几个字符。
回答by J.C. Inacio
Off the top of my head, needs testing, validation etc:
在我的脑海中,需要测试、验证等:
<?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;
}
}
?>
回答by Corey Ray
Late static bindings will work for you I think. In the construct of each class do:
我认为后期静态绑定对你有用。在每个类的构造中:
class ClassName
{
public static $instances = array();
public function __construct()
{
self::$instances[] = $this;
}
}
Then... Here is an autoloader I created. See if this solves your dilemma.
然后...这是我创建的自动加载器。看看这是否能解决你的困境。
// 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;
}
Then all you have to do is
那么你所要做的就是
$var = new ClassName();
but you have to have a php file in the path with the name ClassName.php where ClassName is the same as the name of the class you want to instantiate.
但是您必须在路径中有一个名为 ClassName.php 的 php 文件,其中 ClassName 与您要实例化的类的名称相同。

