Php自动加载并自动实例化所有类

Php自动加载并自动实例化所有类,php,class,Php,Class,我使用PHPSPL_自动加载_扩展来自动加载所有类。我的问题是,是否有可能同时实例化类,这样我就不必在之后手动进行实例化 这是我的引导类: class Bootstrap { private static $__loader; private function __construct() { spl_autoload_register(array($this, 'autoLoad')); } publi

我使用PHPSPL_自动加载_扩展来自动加载所有类。我的问题是,是否有可能同时实例化类,这样我就不必在之后手动进行实例化

这是我的引导类:

  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我明白了,你希望所有这些东西都可以放在页面的顶部,但一般来说,你不应该实例化一些东西,直到你打算使用它