CI加载流程及结构分析(一)

入口文件入口文件主要完成下列工作: 1. 指定 CodeIgniter 框架所在目录; 2. 定义 APPPATH 常量,指示应用程序文件根目录; 3. 载入 codeigniter/CodeIgniter.php 文件,启动框架。 codeigniter/CodeIgniter.php 文件这个文件是 CodeIgniter 的基本文件,主要完成初始化 CodeIgniter 框架和启动应用程序两项工作。 1. 实例化 CI_Benchmark,这个类用于标记应用程序执行消耗的时间; 2. 载入应用程序的配置文件 require(APPPATH.?config/config‘.EXT); 3. 实例化 CI_Config,这个类用于将数组封装为可以操作的配置服务; 4. 实例化 CI_Router,这个类用于分析 URL 请求,确定要执行的控制器和动作; 5. 实例化 CI_Output,这个类提供输出内容的缓存和检查服务; 6. 通过 $OUT->_display_cache($CFG, $RTR) 尝试输出缓存内容,如果成功,则结束程序运行; 7. 判断控制器类定义文件是否存在。如果不存在则通过 show_404() 显示错误信息; 8. 实例化 CI_Input,这个类提供对 $_GET、$_POST 的访问手段,并封装了一些过滤方法; 9. 实例化 CI_URI,这个类提供对 URL 的分析、构造服务; 10. 实例化 CI_Language,这个类提供多语言字符串映射服务; 11. 载入 codeigniter/Base4.php 或者 codeigniter/Base5.php; 12. 载入 libraries/Controller.php; 13. 载入控制器类定义文件; 14. 实例化控制器类; 15. 如果控制器使用了 scaffolding 功能,则调用控制器的 _ci_scaffolding() 方法,否则调用控制器动作方法; 16. 通过 $OUT->_display(); 输出内容($OUT 是 CI_Output 的实例)。 CI_Benchmark 这个类很简单,就是用 microtime() 函数记录时间点,并提供 elapsed_time() 方法来计算两个时间点之间消耗的时间。这个类功能不多,但是很实用。CodeIgniter 中大部分类都是这种设计思想,值得称赞! CI_Config 这个类其实是在内部维护了一个数组,用来记录应用程序的设置(类似 Windows 注册表)。这种简单的封装可以强制应用程序按照固定的规范访问设置,同时又不将设置保存为全局变量,避免无意中遭到破坏或篡改。 CI_Router CI_Router 功能很单一。CI_Router 首先分析出应用程序当前使用的 URL 模式:PATHINFO 或普通模式。接下来从 URL 地址中分析出控制器名字、动作名以及参数名和参数值。分析的结果保存为 CI_Router 对象实例的成员变量。这里比较有特点的是,CI_Router 可以根据开发者在应用程序设置里面定义的模式来分析 URL,而不是使用某种固定的模式。 CI_Output CI_Output 有两个主要功能:获得应用程序执行的所有输出内容和输出缓存服务。应用程序执行的输出结果都会保存为 CI_Output 的成员变量。然后根据应用程序设置,CI_Output::_display() 方法会调用 CI_Output::_write_cache() 方法将输出内容缓存起来。下一次当使用 CI_Output::_display_cache() 时如果缓存已经建立了,并且没有过期,则会直接输出缓存内容。在 CI_Output::_write_cache() 中,是根据 URL 地址和 URL 参数来确定缓存 ID 的。因此即便是同一个控制器和动作,只要使用不同的 URL 参数,也会缓存不同的内容。这个类的功能很简单,因此在许多动态页面是无法使用的。例如用户登录前和登录后,访问同一个控制器和动作并使用相同的 URL 参数,页面内容也有可能是不同的。这时,CI_Output 的缓存就不能使用。因为从本质上来说,CI_Output 提供的缓存是在应用程序之外的,所以应用程序无法根据当前状态来决定是否缓存页面。当一个页面被缓存后,对该页面的访问实际上根本就不会执行应用程序代 码,而是由 CI_Output 取出缓存内容直接就输出了。 CI_Input CI_Input 是输入数据过滤器,并且提供了对 $_GET、$_POST 的封装服务。例如用 CI_Input::post() 方法来访问 $_POST。由于多了这层封装,CI_Input 可以在 post() 方法中对数据进行更多的过滤。这种封装从出发点上看,是很不错的。但是这也会造成一些问题。例如 CI_Input 只有在调用 post() 方法时才能进行过滤。如果应用程序使用 $_POST 直接获取数据,那么实际上就绕过了安全屏障。如果应用程序使用了第三方库,那么这种风险更大,因为第三方库很可能会直接使用 $_POST 等全局变量。因此有些开发者认为过滤应该是全局的,即在框架初始化时,就对所有输入数据进行过滤。但初始化时的全局过滤灵活性很差,要么全过滤,要么都不 过滤,没法做到对个别数据的单独过滤。 CI_Input 的另一个问题,就是没有处理 magic_quotes。不管 magic_quotes 设置为什么,CI_Input 都没有对数据进行相关的处理。这样一来,如果服务器的 magic_quotes 设置不同,那么应用程序得到的数据也是不一致的。后来查看数据库驱动的代码,发现 CI_Input 将对 magic_quotes 的处理放到了数据库驱动中。这种设计是有很大缺陷的!如果应用程序取得数据后,并不是存入数据库(例如直接显示或存入文件),那么就必须自行判断 magic_quotes 的状态。这种判断不但烦琐,而且容易遗忘。所以框架有责任将所有数据整理为一致的格式,要么是应用 addslashes() 转义过后的数据,要么是没有转义的数据。奇怪的是 CI_Input 却对输入数据的字段名进行了 magic_quotes 检查,并应用了 addslashes()。这是为了让数据库字段名不会成为 SQL 注入攻击的根源。甚至,CI_Input 还会将 \n\r\n\r 替换为 \n。这种随意篡改原始数据的做法,非常不可取。总之,我个人认为 CodeIgniter 在这部分的设计是很糟糕的。不过要改善也很简单,几行代码就可以了。然后修改一下数据库驱动。但是由于已经有许多采用 CodeIgniter 开发的应用程序,所以这样的升级改动,影响是非常大的。 CI_URI 由于 CodeIgniter 允许应用程序定义 URL 映射模式,所以需要专门的工具来生成 URL 地址。CI_URI 就是完成这些工作的。 […]

Codeigniter调用PHPExcel 导入excel例子

1.把PHPExcel放到application\libraries下,并新建个tool.php用来调用 PHPExcel官方网站: http://www.codeplex.com/PHPExcel <?php class Tool{ /**导入Excel文件到MySql数据库 $file:Excel文件的名称; $filetempname:Excel文件上传到服务器的临时文件名 $sql:传入的sql语句 **/ function UploadExcel($file,$filetempname,$strsql) { set_include_path(get_include_path().PATH_SEPARATOR .BASEPATH.’libraries/PHPExcel/PHPExcel’); require_once ‘PHPExcel/PHPExcel.php’; require_once ‘PHPExcel/PHPExcel/IOFactory.php’; require_once ‘PHPExcel/PHPExcel/Reader\Excel5.php’; $tools_filePath = dirname(dirname(dirname(dirname(__FILE__)))).”/UploadFiles/”; $tools_filePath = str_replace(‘\\’,’/’,$tools_filePath); //防止最大可使用的内存总量过少 if(intval(ini_get(‘memory_limit’)) <= 20) { ini_set(‘memory_limit’,’20M’); } $uploadDir = $tools_filePath; if (!is_dir($uploadDir)) { if (!mkdir($uploadDir, 0777,TRUE) || !chmod($uploadDir, 0777)) { exit(“创建上传目录失败”); } } $filename = explode(“.”,$file);//把上传的文件名以“.”好为准做一个数组。 $date […]