Php自动加载并自动实例化所有类
我使用PHPSPL_自动加载_扩展来自动加载所有类。我的问题是,是否有可能同时实例化类,这样我就不必在之后手动进行实例化 这是我的引导类:Php自动加载并自动实例化所有类,php,class,Php,Class,我使用PHPSPL_自动加载_扩展来自动加载所有类。我的问题是,是否有可能同时实例化类,这样我就不必在之后手动进行实例化 这是我的引导类: class Bootstrap { private static $__loader; private function __construct() { spl_autoload_register(array($this, 'autoLoad')); } publi
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()中的任何地方,我都可以使用如下内容:
新()类名
而不是每当我需要一个类的实例来调用它时,比如:
Bootstrap::ClassName()->someFunction()
一次实例化所有内容有点违背自动加载程序的目的,因为它只加载您需要的内容,而不是所有内容 因此,理想情况下,您希望对其进行设置,以便在尝试检索实例时,如果该实例不存在,则将其加载并返回。如果它确实存在,则检索并返回它。您可以使用
\uu callStatic
,这样每个可能的类都将被视为引导的函数。我们可以将所有检索到的实例存储为Bootstrap
的private static
属性。您可以使用new
关键字传递,但如果要传递任意数量的参数,则需要使用
基本思路如下:
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::a()
引用的实例与Bootstrap::a()
引用的实例不同。根据您的需要,您应该能够根据需要自行添加所有这些案例的正确处理。感谢您提供的详细示例。我想加载一堆类的唯一原因是,在整个框架中,我总是需要这些类。例如会话类、登录用户信息、验证等。这仍然应该完成;在需要的时候,它们总是在那里,在那些你不需要的情况下,它们不会被加载,不管它们多么罕见them@user3176519我明白了,你希望所有这些东西都可以放在页面的顶部,但一般来说,你不应该实例化一些东西,直到你打算使用它