zend_loader_autoloader 源码 分析

来源:互联网 发布:推理题目的软件 编辑:程序博客网 时间:2024/05/19 00:51

<?phprequire_once 'Zend/Loader.php';//这个类的作用是注册自动加载方法,而且可以为各个命名空间注册方法class Zend_Loader_Autoloader{ //单例变量 protected static $_instance;

//所有的自动加载方法集合 protected $_autoloaders = array();

//默认自动加载方法,用zend自带的类 protected $_defaultAutoloader = array('Zend_Loader', 'loadClass');

//是否会有一个可靠的自动加载类 protected $_fallbackAutoloader = false;

//核 心自动加载方法 protected $_internalAutoloader;

//命名空间集合 protected $_namespaces = array( 'Zend_' => true, 'ZendX_' => true, );

/** * 示例: array('zend'=>array(array('zend_loader', 'autoload'), array('zend_load_autoloader', 'autoload'), 'zendx'=>array()); */ protected $_namespaceAutoloaders = array();

//是否屏蔽错误 protected $_suppressNotFoundWarnings = false;

//zend框架的路径 protected $_zfPath;

//经典单例模式 public static function getInstance() { if (null === self::$_instance) { self::$_instance = new self(); } return self::$_instance; }

//释放单例 public static function resetInstance() { self::$_instance = null; }

//被注册的自动加载方法,根据命 名空间找出对应的自动加载方法,然后加载类,加载成功返回真,否则false public static function autoload($class) { $self = self::getInstance();

foreach ($self->getClassAutoloaders($class) as $autoloader) { //从这里可以看出,自定义的自动加载方法支持三种形式1, 继承自zend内部接口类,2, 自定义的类, 3, 自定义的方法 if ($autoloader instanceof Zend_Loader_Autoloader_Interface) { if ($autoloader->autoload($class)) { return true; } } elseif (is_array($autoloader)) { if (call_user_func($autoloader, $class)) { return true; } } elseif (is_string($autoloader) || is_callable($autoloader)) { if ($autoloader($class)) { return true; } } }

return false; }

//为默认自动加载属性赋值 public function setDefaultAutoloader($callback) { if (!is_callable($callback)) { throw new Zend_Loader_Exception('Invalid callback specified for default autoloader'); }

$this->_defaultAutoloader = $callback; return $this; }

public function getDefaultAutoloader()//默认加载方法的getter方法 { return $this->_defaultAutoloader; }

/** * Set several autoloader callbacks at once * * @param array $autoloaders Array of PHP callbacks (or Zend_Loader_Autoloader_Interface implementations) to act as autoloaders * @return Zend_Loader_Autoloader */ public function setAutoloaders(array $autoloaders) { $this->_autoloaders = $autoloaders; return $this; }

/** * Get attached autoloader implementations * * @return array */ public function getAutoloaders() { return $this->_autoloaders; }

//根扰命名空间返回相应的自动加载方法 public function getNamespaceAutoloaders($namespace) { $namespace = (string) $namespace; if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) { return array(); } return $this->_namespaceAutoloaders[$namespace]; }

//注册命名空间,字串或数组 public function registerNamespace($namespace) { if (is_string($namespace)) { $namespace = (array) $namespace; } elseif (!is_array($namespace)) { throw new Zend_Loader_Exception('Invalid namespace provided'); }

foreach ($namespace as $ns) { if (!isset($this->_namespaces[$ns])) { $this->_namespaces[$ns] = true; } } return $this; }

//注销一个命名空间, 遍历数组并unset public function unregisterNamespace($namespace) { if (is_string($namespace)) { $namespace = (array) $namespace; } elseif (!is_array($namespace)) { throw new Zend_Loader_Exception('Invalid namespace provided'); }

foreach ($namespace as $ns) { if (isset($this->_namespaces[$ns])) { unset($this->_namespaces[$ns]); } } return $this; }

//取得所有注册的命名空间 public function getRegisteredNamespaces() { return array_keys($this->_namespaces); } //设置不同版本的zend目录 public function setZfPath($spec, $version = 'latest') { $path = $spec; if (is_array($spec)) { if (!isset($spec['path'])) { throw new Zend_Loader_Exception('No path specified for ZF'); } $path = $spec['path']; if (isset($spec['version'])) { $version = $spec['version']; } }

$this->_zfPath = $this->_getVersionPath($path, $version); set_include_path(implode(PATH_SEPARATOR, array( $this->_zfPath, get_include_path(), ))); return $this; }

public function getZfPath() { return $this->_zfPath; }

//设置或取得支持屏蔽错误这个属性 public function suppressNotFoundWarnings($flag = null) { if (null === $flag) { return $this->_suppressNotFoundWarnings; } $this->_suppressNotFoundWarnings = (bool) $flag; return $this; }

//设置支持可靠自动加载属性 public function setFallbackAutoloader($flag) { $this->_fallbackAutoloader = (bool) $flag; return $this; }

//取得可靠自动加载属性 public function isFallbackAutoloader() { return $this->_fallbackAutoloader; }

//根据类名取得本类的自动加载方法 public function getClassAutoloaders($class) { $namespace = false; $autoloaders = array();

//根据类名,取得所有注册的 命名空间=>自动加载方法 对,如果有本类名的命名空间,则生成确定命名空间和自动加载方法 foreach (array_keys($this->_namespaceAutoloaders) as $ns) { if ('' == $ns) { continue; } if (0 === strpos($class, $ns)) { if ((false === $namespace) || (strlen($ns) > strlen($namespace))) { $namespace = $ns; $autoloaders = $this->getNamespaceAutoloaders($ns); } } }

//取得所有注册的命名空间,如果上述命名空间在内,则将核心自动加载方法写入自动加载列表 foreach ($this->getRegisteredNamespaces() as $ns) { if (0 === strpos($class, $ns)) { $namespace = $ns; $autoloaders[] = $this->_internalAutoloader; break; } }

//如果没有命名空间则加载无命 名空间的自动加载方法 $autoloadersNonNamespace = $this->getNamespaceAutoloaders('');//php支持key为''的数组 if (count($autoloadersNonNamespace)) { foreach ($autoloadersNonNamespace as $ns) { $autoloaders[] = $ns; } unset($autoloadersNonNamespace); }

//如果命名空间不存在,并且可靠自动加载为真,则自动加载方法是核心加载方法 if (!$namespace && $this->isFallbackAutoloader()) { $autoloaders[] = $this->_internalAutoloader; }

return $autoloaders; }

//向栈的头部插入自动加载方法,并指定命名空间,并修改自动加载方法合集_autoloaders public function unshiftAutoloader($callback, $namespace = '') { $autoloaders = $this->getAutoloaders(); array_unshift($autoloaders, $callback); $this->setAutoloaders($autoloaders);

$namespace = (array) $namespace; foreach ($namespace as $ns) { $autoloaders = $this->getNamespaceAutoloaders($ns); array_unshift($autoloaders, $callback); $this->_setNamespaceAutoloaders($autoloaders, $ns); }

return $this; }

//为指定命名空间指定自动加载方法,并且记录到_autoloaders属性里 public function pushAutoloader($callback, $namespace = '') { $autoloaders = $this->getAutoloaders(); array_push($autoloaders, $callback); $this->setAutoloaders($autoloaders);

$namespace = (array) $namespace; foreach ($namespace as $ns) { $autoloaders = $this->getNamespaceAutoloaders($ns); array_push($autoloaders, $callback); $this->_setNamespaceAutoloaders($autoloaders, $ns); }

return $this; }

//删除自动加载方法 public function removeAutoloader($callback, $namespace = null) { if (null === $namespace) {//无命名空间则全部删除 $autoloaders = $this->getAutoloaders(); if (false !== ($index = array_search($callback, $autoloaders, true))) { unset($autoloaders[$index]); $this->setAutoloaders($autoloaders); }

foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) { if (false !== ($index = array_search($callback, $autoloaders, true))) { unset($autoloaders[$index]); $this->_setNamespaceAutoloaders($autoloaders, $ns); } } } else {//有命名空间则只删命名空间下的 $namespace = (array) $namespace; foreach ($namespace as $ns) { $autoloaders = $this->getNamespaceAutoloaders($ns); if (false !== ($index = array_search($callback, $autoloaders, true))) { unset($autoloaders[$index]); $this->_setNamespaceAutoloaders($autoloaders, $ns); } } }

return $this; }

protected function __construct() { spl_autoload_register(array(__CLASS__, 'autoload'));//注册自动加载方法 $this->_internalAutoloader = array($this, '_autoload');//为核心自动加载方法赋值 }

protected function _autoload($class)//核心自动加载方法,内部有是否报错开关,可屏蔽警告错误,成功返回类名,失败返回false { $callback = $this->getDefaultAutoloader(); try { if ($this->suppressNotFoundWarnings()) { @call_user_func($callback, $class); } else { call_user_func($callback, $class); } return $class; } catch (Zend_Exception $e) { return false; } }

//设置某命名空间的自动加载方法 protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '') { $namespace = (string) $namespace; $this->_namespaceAutoloaders[$namespace] = $autoloaders; return $this; }

//根据版本找出路径 protected function _getVersionPath($path, $version) { $type = $this->_getVersionType($version);

if ($type == 'latest') { $version = 'latest'; }

$availableVersions = $this->_getAvailableVersions($path, $version); if (empty($availableVersions)) { throw new Zend_Loader_Exception('No valid ZF installations discovered'); }

$matchedVersion = array_pop($availableVersions); return $matchedVersion; }

//返回最多4种版本,latest=>latest, 1=>major, 1.1=>minor, 1.1.1=>specific, 1.1.1.1.1=>error protected function _getVersionType($version) { if (strtolower($version) == 'latest') { return 'latest'; }

$parts = explode('.', $version); $count = count($parts); if (1 == $count) { return 'major'; } if (2 == $count) { return 'minor'; } if (3 < $count) { throw new Zend_Loader_Exception('Invalid version string provided'); } return 'specific'; }

//根据版本返回对应的zend库目录 protected function _getAvailableVersions($path, $version) { if (!is_dir($path)) { throw new Zend_Loader_Exception('Invalid ZF path provided'); }

$path = rtrim($path, '/'); $path = rtrim($path, '\\'); $versionLen = strlen($version); $versions = array(); $dirs = glob("$path/*", GLOB_ONLYDIR);//返回与模式匹配的目录数组 foreach ((array) $dirs as $dir) { $dirName = substr($dir, strlen($path) + 1); if (!preg_match('/^(?:ZendFramework-)?(\d+\.\d+\.\d+((a|b|pl|pr|p|rc)\d+)?)(?:-minimal)?$/i', $dirName, $matches)) { continue; }

$matchedVersion = $matches[1];//匹配出zend的版本

if (('latest' == $version) || ((strlen($matchedVersion) >= $versionLen) && (0 === strpos($matchedVersion, $version))) ) { $versions[$matchedVersion] = $dir . '/library';//找出zend库的目录 } }

uksort($versions, 'version_compare');//对版本进行排序 return $versions; }}


 

原创粉丝点击