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

作者:掠影
最后编辑时间:2017-11-14 13:56:23
浏览次数:1135



    距离上次更新本系列已经过去了N久,一段时间下来,从实践中也掌握了不少实用的框架技巧,故而继续更新:

    本次主要分享的是CI框架的Hook技巧,即挂载用的钩子;在CI框架中,当我们需要执行一些操作,同时这一操作会对CI 本身的流程影响时,常常有以下两种方式,其一是修改CI 源代码,但这对于后续更新等情况; 会要求重复更改,且易引起BUG,故而不推荐;

    其二便是本文所使用的Hook技巧:即通过CI框架在CodeIgniter.php中预置的特定位置来插入特定的代码段,来执行相对应的功能,从而实现不触及CI 代码的前提下,实现自定义功能的操作。

    

    下文为Hook简要的介绍和样例:

    1. 概念:

        在core文件夹下的Hooks.php中我们可以看到对于Hook的定义:对于__construct()函数,判断了config.php中的enable_hooks值,即当其为TRUE时开启;其次,加载hooks.php中预定义的$hook数组。        


$hook['post_controller_constructor'] = array(
    "class"     =>  "", //钩子类名
    "function"  => "authenticate",//钩子方法名
    "filename"  => "authenticate.php",//钩子文件名
    "filepath"  => "hooks",//钩子路径
    "params"    => array()//传给钩子的参数,以数组形式传递
);

        这里可以看到,我们定义了一个类型为post_controoler_constructor的钩子,其位置在指定的控制器被创建并调用了__constructor()后,指定的函数被调用前;此钩子的含义是authenticate.php中的authenticate函数;

        接下来我们可以看下authenticate.php中的文件内容,以更好的解释钩子的作用:


function authenticate(){
    if(!isset($_SESSION['user_id'])){ //用户未登陆时
        $_SESSION['user_id'] = md5(uniqid(rand(), true));
        $_SESSION['user_identity'] = 'visitor';
    }else{
        //默认的已经登陆用户
    }
}

           这个函数即为对已登陆的用户,略过相关操作;而对未登陆的用户默认设置一个访客ID,这一操作在一些电商等平台上是较为有效的设计(例如购物车等);

            而钩子的类型,在CI 中有默认以下几种:[1]


  • pre_system 在系统执行的早期调用,这个时候只有 基准测试类 和 钩子类 被加载了, 还没有执行到路由或其他的流程。
  • pre_controller 在你的控制器调用之前执行,所有的基础类都已加载,路由和安全检查也已经完成。
  • post_controller_constructor 在你的控制器实例化之后立即执行,控制器的任何方法都还尚未调用。
  • post_controller 在你的控制器完全运行结束时执行。
  • display_override 覆盖 _display() 方法,该方法用于在系统执行结束时向浏览器发送最终的页面结果。 这可以让你有自己的显示页面的方法。注意你可能需要使用 $this->CI =& get_instance() 方法来获取 CI 超级对象,以及使用 $this->CI->output->get_output() 方法来 获取最终的显示数据。
  • cache_override 使用你自己的方法来替代 输出类 中的 _display_cache() 方法,这让你有自己的缓存显示机制。
  • post_system 在最终的页面发送到浏览器之后、在系统的最后期被调用。    

            通过这些例子可以很清晰的了解到它们所处的位置,而实际上,这些挂载点也是可以自定义的,在CodeIgniter.php中的call_hook等调用里可以自由的设置(不过要改源代码),我们需要根据自己的实际情况选择合适的挂载点;


    下面提供一些例子:

    1. 拦截不符合类型的请求:

    我们常常需要对某些函数指定类型,即例如indexView()一类的函数,是提供页面加载的,即允许GET类型的访问;而对于indexAction()一类的函数,用于处理POST请求,即限定访问类型为POST,这些操作如果均手动给予限定,则不免显得极为繁琐,而在hook中,在这些请求被实例化控制器对象前即处理,则方便了许多;

    这里提供了blocker函数,挂载在cache_override处(controller加载前),对请求的URI进行加工后传递给不同的Method:

    

function blocker(){
    $RTR = & load_class('Router', 'core', isset($routing) ? $routing : NULL);
    if(is_post()) {
        $RTR->method .= "Action"; //对类型为POST的请求xx,转发到xxAction方法中
    }else if(is_get()){
        $RTR->method .= "View"; //对类型为GET的请求xx,转发到xxView方法中
    }
}





    总结:

    Hook是一个相当有用的特性,对于有自定义框架需求的童鞋们可以好好研究下并通过这一方式,将CI玩出自己的风格。


    [1]CI官方文档:http://codeigniter.org.cn/user_guide/general/hooks.html

取消

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

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

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

分享到: QQ空间 更多



评论区

  • 223.104*****: 2018-01-05
    假的评论??
  • 223.104*****: 2018-01-05
    试验下
  • 60.191.*****: 2018-11-06
    ssss
  • 119.131*****: 2019-05-13
    总感觉文档的钩子说明有点迷,如果有图的话就更好理解了。