我使用php spl_autoload_extensions自动加载所有类。我的问题是,是否可以同时实例化类,所以我不必在之后手动完成。
这是我的引导类:
class Bootstrap
{
private static $__loader;
private function __construct()
{
spl_autoload_register(array($this, 'autoLoad'));
}
public static function init()
{
if (self::$__loader == null) {
self::$__loader = new self();
}
return self::$__loader;
}
public function autoLoad($class)
{
$exts = array('.php', '.class.php');
spl_autoload_extensions("'" . implode(',', $exts) . "'");
set_include_path(get_include_path() . PATH_SEPARATOR . BASE);
foreach ($exts as $ext) {
if (is_readable($path = BASE . strtolower($class . $ext))) {
require_once $path;
return true;
}
}
self::recursiveAutoLoad($class, BASE);
}
private static function recursiveAutoLoad($class, $path)
{
if (is_dir($path)) {
if (($handle = opendir($path)) !== false) {
while (($resource = readdir($handle)) !== false) {
if (($resource == '..') or ($resource == '.')) {
continue;
}
if (is_dir($dir = $path . DS . $resource)) {
continue;
} else
if (is_readable($file = $path . DS . $resource)) {
require_once $file;
}
}
closedir($handle);
}
}
}
}
现在函数autoLoad()中的任何地方都可以使用类似的东西:
new()ClassName
每当我需要一个类的实例来调用它时:
Bootstrap::ClassName()->someFunction()
答案 0 :(得分:2)
一次实例化一切会破坏自动加载器的目的,因为它应该只加载你需要的东西,而不是一切。
理想情况下,您希望将其设置为当您尝试检索实例时,如果它不存在,请将其加载并返回。如果确实存在,请检索并返回。您可以使用magic method __callStatic
,以便将每个可能的类视为Bootstrap
的函数。我们可以将所有检索到的实例存储为private static
Bootstrap
属性。您可以使用new
关键字call a class from a string,但如果要传递任意数量的参数,则需要使用ReflectionClass。
这是基本的想法:
class Bootstrap {
private static $instances = array();
public static function __callStatic($name, $args) {
if (!in_array($name, array_keys(self::$instances))) {
//then we must make a new instance
//check if we have arguments
//for the constructor
if (!empty($args)) {
//then we need reflection to instantiate
//with an arbitrary number of args
$rc = new ReflectionClass($name);
$instance = $rc->newInstanceArgs($args);
} else {
//then we do not need reflection,
//since the new keyword will accept a string in a variable
$instance = new $name();
}
//and finally add it to the list
self::$instances[$name] = $instance;
} else {
//then we already have one
$instance = self::$instances[$name];
}
return $instance;
}
}
以下是一些示例类,可以看到它的实际效果:
class A {
function helloWorld() {
return "class " . __CLASS__;
}
}
class B {
function helloWorld() {
return "class " . __CLASS__;
}
}
class C {
public function __construct($name) {
$this->name = $name;
}
function helloWorld() {
return "class " . __CLASS__;
}
public function name() {
return "my name is $this->name";
}
}
<强>样本强>
echo Bootstrap::a()->helloWorld(); //class A
echo Bootstrap::b()->helloWorld(); //class B
echo Bootstrap::c('Charles')->helloWorld(); //class C
echo Bootstrap::c()->name(); //my name is Charles
注意:除此之外,还有一些问题:它没有尝试实例化不存在的类的任何异常处理。您也无法在bootstrap中使用与类同名的另一个方法名称。类名不区分大小写,因此Bootstrap::a()
将引用与Bootstrap::A()
不同的实例。根据您的需要,您应该能够根据需要自行为所有这些案例添加适当的处理。