<?php
//本类的功能是为zend提供一个autoload类, 本类可算做一个示例,用户可自定义自己的autoload类,,从而替换这个类
class Zend_Loader
{
//这是autoload中用来加载一个类文件的方法,参数分别是: 类名(支持命名空间), 目录(数组或字串),先检查类是否存在,再用类名生成真正的类名和目录,再从所有目录中加载类,再
//判断本类是否加载
public static function loadClass($class, $dirs = null)
{
if (class_exists($class, false) || interface_exists($class, false)) {
return;
}
if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
require_once 'Zend/Exception.php';
throw new Zend_Exception('Directory argument must be a string or an array');
}
$className = ltrim($class, '\\');
$file = '';
$namespace = '';
if ($lastNsPos = strripos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$file = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$file .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
if (!empty($dirs)) {
$dirPath = dirname($file);
if (is_string($dirs)) {
$dirs = explode(PATH_SEPARATOR, $dirs);
}
foreach ($dirs as $key => $dir) {
if ($dir == '.') {
$dirs[$key] = $dirPath;
} else {
$dir = rtrim($dir, '\\/');
$dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
}
}
$file = basename($file);
self::loadFile($file, $dirs, true);
} else {
self::loadFile($file, null, true);
}
if (!class_exists($class, false) && !interface_exists($class, false)) {
require_once 'Zend/Exception.php';
throw new Zend_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file");
}
}
//加载类文件, 参数是:名字, 目录 , 是否只加载一次 原理:先把dir全部写入include_path, 然后直接 加载文件 ,最后再还原include_path
public static function loadFile($filename, $dirs = null, $once = false)
{
self::_securityCheck($filename);
/**
* Search in provided directories, as well as include_path
*/
$incPath = false;
if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) {
if (is_array($dirs)) {
$dirs = implode(PATH_SEPARATOR, $dirs);
}
$incPath = get_include_path();
set_include_path($dirs . PATH_SEPARATOR . $incPath);
}
/**
* Try finding for the plain filename in the include_path.
*/
if ($once) {
include_once $filename;
} else {
include $filename;
}
/**
* If searching in directories, reset include_path
*/
if ($incPath) {
set_include_path($incPath);
}
return true;
}
//判断文件是否可读,先用系统函数判断,再用
public static function isReadable($filename)
{
if (is_readable($filename)) {
// Return early if the filename is readable without needing the
// include_path
return true;
}
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'
&& preg_match('/^[a-z]:/i', $filename)
) {
//如果文件名是一个绝对路径,并且是在windows下,按下文逻辑来看,现在就可以咔嚓了
return false;
}
foreach (self::explodeIncludePath() as $path) {//用所有include_path来与类名组合,判断可读性,只要有一个可读就返回真,否则一直判断
if ($path == '.') {
if (is_readable($filename)) {
return true;
}
continue;
}
$file = $path . '/' . $filename;
if (is_readable($file)) {
return true;
}
}
return false;
}
//分解include_path为数组,也可以分解指定的path
public static function explodeIncludePath($path = null)
{
if (null === $path) {
$path = get_include_path();
}
if (PATH_SEPARATOR == ':') {
// On *nix systems, include_paths which include paths with a stream
// schema cannot be safely explode'd, so we have to be a bit more
// intelligent in the approach.
$paths = preg_split('#:(?!//)#', $path);
} else {
$paths = explode(PATH_SEPARATOR, $path);
}
return $paths;
}
//本方法直接调 用loadclass方法
public static function autoload($class)
{
trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead', E_USER_NOTICE);
try {
@self::loadClass($class);
return $class;
} catch (Exception $e) {
return false;
}
}
//注册或取消新的autoload方法,第二个参数是注册或取消,
public static function registerAutoload($class = 'Zend_Loader', $enabled = true)
{
trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead', E_USER_NOTICE);
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
if ('Zend_Loader' != $class) {
self::loadClass($class);
$methods = get_class_methods($class);
if (!in_array('autoload', (array) $methods)) {
require_once 'Zend/Exception.php';
throw new Zend_Exception("The class \"$class\" does not have an autoload() method");
}
$callback = array($class, 'autoload');
if ($enabled) {
$autoloader->pushAutoloader($callback);
} else {
$autoloader->removeAutoloader($callback);
}
}
}
//对一个文件名的安全性检查
protected static function _securityCheck($filename)
{
/**
* Security check
*/
if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) {
require_once 'Zend/Exception.php';
throw new Zend_Exception('Security check: Illegal character in filename');
}
}
//加载一个文件 , 一次或不限
protected static function _includeFile($filespec, $once = false)
{
if ($once) {
return include_once $filespec;
} else {
return include $filespec ;
}
}
}