<?php
require_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;
}
}