我正在尝试创建一种从给定变量加载和实例化类的函数。像这样:
<?php
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = $class::getInstance();
}
}
?>
如果我这样使用它:
<?php
loadClass('session');
?>
它应该包含并实例化会话类。
BTW:静态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-&gt; blablablafunction();
答案 0 :(得分:46)
在PHP 5.3中显然可以在变量类名上调用静态函数:
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
http://php.net/manual/en/language.oop5.static.php
现在我自己可以使用它。
在此之前,您无法真正假设您正在加载的每个课程都设计为单身。只要你使用&lt; 5.3你必须加载类并通过构造函数实例化:
function loadClass($class) {
$sClassPath = SYSPATH."/classes/{$class}.php";
if (file_exists($sClassPath)) {
require_once($sClassPath);
$class = new $class;
}
}
OR
只需加载类而不从中创建对象。然后在那些打算成为单例的东西上调用“:: getInstance()”,在loadClass()函数之外调用那些不是“new”的东西。
虽然正如其他人早先指出的那样,__ autoload()可能对您有用。
答案 1 :(得分:38)
您可以使用call_user_func()
:
$class = call_user_func(array($class, 'getInstance'));
第一个参数是callback
类型,在这种情况下包含类名和方法名称。
答案 2 :(得分:2)
答案 3 :(得分:0)
看起来你正在与PHP的当前实现静态绑定作斗争,这就是你使用getCallingClass跳过箍的原因。我可以从经验告诉你,你应该放弃尝试通过静态方法将实例化放在父类中。它最终会给你带来更多问题。 PHP 5.3将实现"late static binding"并且应该解决您的问题,但现在显然没有帮助。
您可能最好使用kodisha提到的自动加载功能以及坚实的Singleton实现。我不确定你的目标是否是语法糖,但它认为从长远来看你会做得更好,避免试图保存一些角色。
答案 4 :(得分:0)
脱离我的头脑,需要测试,验证等:
<?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;
}
}
?>
答案 5 :(得分:0)
我认为,后期静态绑定对你有用。在每个类的构造中做:
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文件 ClassName.php 其中ClassName与要实例化的类的名称相同。