CI框架(CodeIgniter)使用技巧和步骤小结(五)

作者:掠影
最后编辑时间:2018-05-07 21:43:38
浏览次数:2010



回顾

距离上篇介绍Hook已经过去一阵子了,这段期间通过借鉴CI的设计思路,自己实现了一个简单的框架helpful-tools,经过这段时间的工作实践,对CI框架也有了一些新的认识;故而本篇从CI3的源码分析角度,对整个框架的一个大致结构做一个阶段性理解总结;

  • 本文中所有文件结构均为默认结构,为了简便起见一般不列出代码,请结合源码浏览)

  • 本文中一些需要额外注意的部分以[0-9]的形式给出,请在文末附录出查看)

正文

  1. 入口文件:index.php在入口文件中,主要实现了一些项目中用到的目录变量,工作环境变量,报错信息等的设置;对主要的application,views目录进行了判断(是否存在,是否为文件夹类型)[1],最后引入核心文件中的core/CodeIgniter.php,开始框架执行流程

  2. 核心框架文件:system/core/CodeIgniter.php本文件为整个框架的核心,从其命名上即可窥见一斑;以下列举文件中一些关键点:

    • 检测是否由入口文件进入:defined('BASEPATH') OR exit('No direct script access allowed');如果是直接访问(不通过index.php)则返回错误

      • 这一阻止方式比较直接(检测只有入口文件里才定义的一个常量),且在每一个非入口文件的PHP文件中都需要手动声明一次
      • 其他方式包括:在目录下添加.htaccess,建立index.html,里面设置报错信息等
    • require_once,即包含各类核心文件所用的函数[2],以下予以列举:

      • application/config/constants.php: 用于定义一些常量,可被application/config/ENVIRONMENT/下的同名文件覆盖;
      • system/core/Common.php:用于定义一些常用方法(如加载类文件,自定义错误处理器,自定义fatal处理器等,在框架流程中用到了再提及)
    • load_class: 定义于Common中,全局类加载器

      • 该函数内维护一个static变量$_classes[3],类似于全局数组,存有所有已经被实例化的类(这里实现了单例模式,每个类只存一个实例化对象)
      • 给定类名,类位置(目录)和初始参数,遍历应用目录(application)和系统目录(system)下对应位置的所有类,找到要求的类,并实例化-》存储
      • 返回存储在$_classes内的指定的实例化对象
    • log_message: 定义于Common中,全局记录器

      • 维护一个core/Log类的实例化对象,调用这个对象进行写日志的操作
    • error_handler:处理所有的错误

      • 调用_error_handler方法,对不引起fatal error的错误,
    • exception_handler: 处理全局异常

    • register_shutdown_function:用于处理所有会导致中止执行的错误

      • error_get_last():获取最后一次发生的错误
      • 判断错误发生情况,并转交给_error_handler执行[4]
    • 如果配置项中开启了composer自动加载,则调用application/vendor/autoload.php进行自动加载

    • 通过类加载器启动一个执行时间记录器Benchmark, 记录框架加载各部分的时间

    • 启动配置类(Config.php), 加载配置文件

    • 启动钩子(Hook)系统,如前篇文章所介绍CI框架(CodeIgniter)使用技巧和步骤小结(四)的一样,利用闭包来调用函数/类方法

      • 对单纯的方法直接调用
      • 对类的方法,实例化一个对象,并调用
    • 字符集处理/转换扩展启动(mbstring,iconv)

    • 加载一系列工具类,如URI类,路由类(ROUTER)【该部分内容将在下一篇中重点介绍,敬请期待:),打算作为第六篇】,输出类(缓存,响应头,响应格式等)【第七篇】

    • 核心成分:控制器的加载

      • 引入控制器基类(core/Controller)
      • 根据路由映射规则,找到所请求的路由器子类
      • 利用反射,调用所请求的类方法(判断是否为public)[5]
        • 这里需要注意的是,在CI_Controller基类中,有对Loader加载类的一个实例化(利用load_class, 单例),这个类用于加载所有的liraries, models等,可以是自动加载(在config/autoload.php中,也可以是手动加载,调用里面的函数,如model(), library()等)【第八篇】
      • 特殊规则:
        • 控制器方法不能以_(下划线)开头(框架中规定,可以修改框架源码[不建议])
        • 不能是基类中的方法(CI_Controller)中的方法
    • 调用一系列钩子,完成加载(实际上钩子的调用是贯穿整个流程的)

  3. 完成

作者:萨秋(掠影)
转载请联系原作者
邮件:ryoalex@foxmail.com

总结

本篇主要介绍了框架的整个流程,CI框架的核心为CodeIgniter.php文件,通过文件包含的形式调用了诸多核心文件;
其中重点为Config.php里的load_class(),Hooks.php里的call_hook()与Loader里面的initialize()和各种load方法,这些部分的实现都是相当有趣的,值得投入更深的精力去仔细研究,也是本人下几篇博文的重点研究对象(笑)

附录

  • [1] is_dir: 用于判断该文件是否为文件夹类型(当且仅当文件存在,且为文件夹类型时返回true)
  • [2]require和include的区别:前者若遇到问题(文件不存在之类的情况),则扔出Fatal级别的报错,并终止运行;后者扔出Warning报错,且继续运行
  • [3] 静态变量:仅在函数第一次被调用时初始化;当函数第二次被调用时,该变量保留上次调用结束后的值,不重新初始化
  • [4] 对引起fatal error的错误,如 E_ERROR, E_PARSE等,需要注册shutdown处理函数,对这一情况进行手动捕获,再转交给错误处理函数,这部分内容会单独开个新坑(笑),敬请期待
  • [5] 声明反射方法后,可对这一反射方法检查类型,如isPublic()或isContructor()等
  • [6][7][8] 未填完的坑:Router,Output,Loader三篇

取消

感谢您的支持,我会继续努力的!关闭

扫码支持
大家有钱的捧个钱场,没钱的捧个人场233333

打开支付宝扫一扫,即可进行扫码打赏哦

分享到: QQ空间 更多



评论区