`

自定义类自动加载类

阅读更多
<?php
require_once 'exception.php';

/**
 * 自动加载类
 *
 */
final class AutoloadClass {
	
	/**
     * 类搜索路径
     *
     * @var array
     */
    private static $_class_path = array();
    
    /**
     * 类搜索规则
     *
     * @var array
     */
    private static $_locate_rules = array();
            
    /**
     * 添加一个类搜索路径
     *
     * @param string $dir 要添加的搜索路径
     */
    static function import($dir)
    {
        $real_dir = realpath($dir);
        if ($real_dir)
        {
            $dir = rtrim($real_dir, '/\\') . DS;
            if (!isset(self::$_class_path[$dir]))
            {
                self::$_class_path[$dir] = $dir;
            }
        }
    }

    /**
     * 载入指定类的定义文件,如果载入失败抛出异常
     *
     * @param string $class_name 要载入的类
     * @param boolean $throw_exception 找不到指定类时是否抛出异常
     */
    static function loadClass($class_name, $throw_exception = true)
    {
        if (class_exists($class_name, false) || interface_exists($class_name, false))
            return;
		
        foreach (self::$_locate_rules as $rule){
        	$filename = call_user_func($rule,$class_name);
        	if ($filename) break;
        }
        
        // 缺省的类加载规则
        if (!$filename)
        	$filename = str_replace('_', DS, $class_name) . '.php';
    	
        foreach (self::$_class_path as $dir)
        {
            $path = $dir . DS . $filename ;
            if (is_file($path))
            {
                require $path;
            	if (class_exists($class_name, false) || interface_exists($class_name, false)) { return; }
            }
        }
        
        if ($throw_exception)
        { 
        	throw new ExpectedClassException($class_name, $filename, file_exists($filename));
        }
    }
    
    /**
     * 添加一个类查找规则回调函数,要求规则匹配成功则返回类路径名称
     * 
     * 诸如: modules\contact\controllers\default.php 
     * 失败返回false
     *
     * @param callback $callback
     */
    static function addLocateRule($callback){
    	if (is_callable($callback)) self::$_locate_rules[] = $callback;
    }
    
    /**
     * 用于 的类自动载入,不需要由开发者调用
     *
     * @param string $class_name
     * @access private
     */
    static function autoload($class_name)
    {
        self::loadClass($class_name, true);
    }

    /**
     * 注册或取消注册一个自动类载入方法
     * 
     * @param boolean $enabled 启用或禁用该服务
     */
    static function registerAutoload($enabled = true)
    {
        static $registered = false;

        if (!function_exists('spl_autoload_register'))
        {
            exit('spl_autoload does not exist in this PHP installation.');
        }
		
        $registered = $enabled ? ( $registered ? true : spl_autoload_register(array('AutoloadClass', 'autoload')) )
        	: !spl_autoload_unregister(array('AutoloadClass', 'autoload'));
    }
    

    /**
     * 按照 命名规则,搜索文件
     *
     * 命名规则就是文件名中的“_”替换为目录分隔符。
     *
     * @param string $filename
     * @param boolean $return 指示是否直接返回处理后的文件名,而不判断文件是否存在
     *
     * @return string
     */
    private static function getFilePath($filename, $return = false)
    {
    	$filename = str_replace('_', DS, $filename);
    	
    	$filename = DS == '/' ? str_replace('\\', DS, $filename) : str_replace('/', DS, $filename);

        if (strtolower(substr($filename, -4)) != '.php') {
            $filename .= '.php';
        }

        // 首先搜索当前目录
        if (is_file($filename)) { return $filename; }

        foreach (self::$_class_path as $dir)
        {
            $path = $dir . DS . $filename ;
        	if (is_file($path)) { return $path; }
        }
        return false;
    }
    
    /**
     * 载入指定的文件
     *
     * $filename 参数中的 “_” 将被替换为目录
     *
     * @param string $className
     * @param boolean $loadOnce 指定为 true 时,等同于 require_once
     *
     * @return boolean
     */
    static function loadFile($filename, $loadOnce = false)
    {
        static $is_loaded = array();

        $path = self::getFilePath($filename);
        if ($path != '') {
            if (isset($is_loaded[$path]) && $loadOnce) { return true; }
            $is_loaded[$path] = true;
            if ($loadOnce) {
                return require_once($path);
            } else {
                return require($path);
            }
        }
        throw new ExpectedFileException($filename);
    }
}

 使用demo:

<?php
// 

// 过滤 magic_quotes
if (get_magic_quotes_gpc()) {
	$in = array(& $_GET, & $_POST, & $_COOKIE, & $_REQUEST);
	while (list($k,$v) = each($in)) {
		foreach ($v as $key => $val) {
			if (!is_array($val)) {
				$in[$k][$key] = stripslashes($val);
				continue;
			}
			$in[] =& $in[$k][$key];
		}
	}
	unset($in);
}
set_magic_quotes_runtime(0);

// 设置自动加载类操作
require_once 'autoload.php';

AutoloadClass::registerAutoload(true);

// 导入应用根路径
AutoloadClass::import(App::ini('APP_DIR'));

/**
 * 定位控制器类文件路径
 *
 * @param string $class_name
 * @return string
 */
function locateControllerFile($class_name){
	if (!preg_match('/Controller$/i',$class_name))
		return false;
	$_ = preg_replace('/Controller$/i','',$class_name);
	
	if (empty($_)) return false;
	
	$_ = explode('_',$_);
	
	$_ = array_map('strtolower', $_);
	
	if ($_[0] == 'mod'){
		
		// Mod_Contact_DefaultController => modules\contact\controllers\default.php
		
		$_[0] = 'modules';
		$_[1] = $_[1] . '/controllers';
	}
	
	return implode('/',$_) . '.php';
}

/**
 * 定位模型类文件路径
 *
 * @param string $class_name
 * @return string
 */
function locateModelFile($class_name){
	
	if (!preg_match('/Model$/i',$class_name))
		return false;
	$_ = preg_replace('/Model$/i','',$class_name);
	
	if (empty($_)) return false;
	
	$_ = explode('_',$_);
	
	$_ = array_map('strtolower', $_);
	
	if ($_[0] == 'mod'){
		
		// Mod_Contact_UserModel => modules\contact\models\user.php
		
		$_[0] = 'modules';
		$_[1] = $_[1] . '/models';
	}
	
	return implode('/',$_) . '.php';
}

AutoloadClass::addLocateRule('locateControllerFile');
AutoloadClass::addLocateRule('locateModelFile');
 

 

 

分享到:
评论

相关推荐

    Java实现的自定义类加载器示例

    Java 实现的自定义类加载器示例 Java 实现的自定义类加载器是 Java 语言中的一种机制,允许开发者自定义类加载器...自定义类加载器可以满足特定的需求,例如执行代码前自动验证数字签名、根据用户需求动态地加载类等。

    PHP类的自动加载实例

    这里,我们定义了一个名为my_autoload()的自定义自动加载函数,它同样将类名转换为文件路径,但添加了当前目录(__DIR__)和特定的类文件存放目录(classes/)。然后,我们使用spl_autoload_register()来注册这个函数...

    卓开发:弹出自定义对话框自动播放视频(仿视频广告效果,使用mediaplayer和surfaceview做播放器)

    在安卓应用开发中,创建一个弹出自定义对话框并自动播放视频的功能,是提升用户体验、吸引用户注意力的有效手段,尤其适用于实现类似视频广告的效果。在这个项目中,我们使用了MediaPlayer和SurfaceView作为视频播放...

    Spring@PropertySource 配置文件自定义加密、自定义Yaml文件加载

    在Spring框架中,`@PropertySource`注解用于指定配置文件的位置,以便Spring可以在启动时自动加载这些属性值。在实际开发中,我们有时需要对这些配置文件进行加密,以增强系统的安全性。此外,除了传统的.properties...

    tomcat类加载器

    类加载器遵循双亲委派模型,这意味着当一个类加载器尝试加载类时,它首先会将请求委托给其父类加载器,直到到达顶层的Bootstrap ClassLoader,如果父类加载器无法找到该类,子类加载器才会尝试自己加载。 在Tomcat...

    springboot自定义自动装配.rar

    1. **创建配置类**:要自定义自动配置,首先创建一个带有`@Configuration`注解的类,这表示该类是一个配置源。在类中可以定义`@Bean`方法来创建Bean实例。 2. **使用`@Profile`**:可以通过`@Profile`注解来指定...

    springboot+java类热加载

    在Java中,类加载器负责查找并加载类到Java虚拟机中。我们可以通过自定义类加载器来实现热加载。例如,`MemoryClassLoader.java`可能就是一个自定义类加载器的实现,它可以在内存中动态加载或更新类。 **JarinJAR**...

    Java 自动加载JAR文件并运行其中的类方法

    要自动加载JAR文件并运行其中的类方法,我们需要以下几个步骤: 1. **获取JAR文件路径**:首先,我们需要知道JAR文件的物理位置。这可以通过用户输入、配置文件或系统环境变量来获取。 2. **添加到ClassPath**:...

    android 自动换行的自定义viewgroup

    标题"android 自动换行的自定义viewgroup"所指的,就是创建一个能够根据子视图的数量和大小自动调整布局,实现自动换行效果的自定义 ViewGroup 类。这样的组件通常用于展示网格或者流式布局,例如商品列表、图片墙等...

    类加载器文件

    这种设计遵循了**委托模式**,即自定义类加载器在尝试加载类之前会先询问其父加载器是否能加载该类,只有在父加载器无法加载时才会尝试自己加载。 #### 八、类的卸载与重载 1. **卸载**: Java类一旦被加载到JVM中...

    自定义Dialog 以加载进度为例

    接下来,可以绑定动画和事件监听器,使进度条随着加载的进度自动更新,同时播放帧动画。最后,你可以在需要显示加载提示的地方调用这个自定义Dialog。 总结起来,自定义Dialog“以加载进度为例”涉及到的技术主要...

    类的自动加载.zip

    总结一下,`spl_autoload_register`函数使得在PHP中实现类的自动加载变得简单,通过注册自定义的自动加载函数,我们可以更有效地组织和管理代码。这个功能特别适用于大型项目,其中包含大量的类和文件。通过遵循一致...

    示例代码:自定义注解,使用ImportBeanDefinitionRegistrar自动加载

    本示例探讨的主题是如何通过自定义注解并结合`ImportBeanDefinitionRegistrar`实现自动加载,这在创建可重用的模块化服务时非常有用。`ImportBeanDefinitionRegistrar`是Spring框架提供的一种机制,用于在配置类加载...

    自定义,实现下拉刷新、上拉加载功能

    3. 更新列表:加载新数据后,通过Adapter的notifyDataSetChanged()方法通知ListView有新的数据添加,列表会自动加载新的内容。 三、AutoListView的主要文件 在实现AutoListView时,你可能需要以下主要文件: 1. ...

    《Android:JNI调用C++自定义类的详细方法》源码

    本篇将详细介绍如何在Android中通过JNI调用C++自定义类,从而实现Java与C++的深度集成。 首先,我们需要了解JNI的基本概念。JNI是一种接口,它定义了一套规则和函数,使得Java代码能够调用本地(Native)代码,同时...

    PHP文件自动加载

    `spl_autoload_register()` 是PHP 5.3引入的一种更灵活的自动加载机制,它可以注册多个自定义的自动加载函数,并且可以提供更加灵活的类文件搜索策略。 **1. 基础用法** ```php // 注册自动加载函数 spl_autoload_...

    自定义Dialog加载ExpandableListView

    本主题将深入探讨如何实现一个自定义Dialog来加载ExpandableListView,以实现下拉显示并支持点击触发功能。 首先,我们了解下ExpandableListView。ExpandableListView是Android SDK中的一个控件,它可以展示可折叠...

    自定义加载控件

    在Android开发中,自定义加载控件是一种常见的需求,它能提供独特的用户体验并增强应用的视觉效果。初学者可以通过学习自定义控件的设计来提升自己的技能。本文将深入探讨自定义加载控件的设计原理和实践过程,同时...

    jvm字节码自动加载

    在Java虚拟机(JVM)中,字节码自动加载是一项关键功能,它使得Java程序能够在运行时动态地发现和加载类。字节码是由Java源代码编译而成的二进制格式,它包含了类和接口的信息。了解JVM如何自动加载字节码对于深入...

    swift-iOS中的高性能自定义点加载指示器

    6. **集成到项目**:在需要使用自定义点加载指示器的地方,通过代码实例化并添加到父视图,或者在Storyboard中拖拽一个`UIView`并指定其为自定义类。 7. **交互与控制**:提供开始和停止加载的方法,以便在适当的...

Global site tag (gtag.js) - Google Analytics