如何让CI框架支持service层


Posted in PHP onOctober 29, 2014

大家知道CodeIgniter框架式MVC分层的,通常大家把业务逻辑写到Controller中,而Model只负责和数据库打交道。

但是随着业务越来越复杂,controller越来越臃肿,举一个简单的例子,比如说用户下订单,这必然会有一系列的操作:更新购物车、添加订单记录、会员添加积分等等,且下订单的过程可能在多种场景出现,如果这样的代码放controller中则很臃肿难以复用,如果放model会让持久层和业务层耦合。现在公司的项目就是,很多人将一些业务逻辑写到model中去了,model中又调其它model,也就是业务层和持久层相互耦合。这是极其不合理的,会让model难以维护,且方法难以复用。

是不是可以考虑在controller和model中加一个业务层service,由它来负责业务逻辑,封装好的调用接口可以被controller复用。

这样各层的任务就明确了:
Model(DAO):数据持久层的工作,对数据库的操作都封装在这。
Service : 业务逻辑层,负责业务模块的逻辑应用设计,controller中就可以调用service的接口实现业务逻辑处理,提高了通用的业务逻辑的复用性,设计到具体业务实现会调用Model的接口。
Controller :控制层,负责具体业务流程控制,这里调用service层,将数据返回到视图
View : 负责前端页面展示,与Controller紧密联系。

基于上面描述,实现过程:
(1)让CI能够加载service,service目录放在application下,因为CI系统没有service,则在application/core下新建扩展MY_Service.php

<?php

class MY_Service

{

    public function __construct()

    {

        log_message('debug', "Service Class Initialized");

    }

    function __get($key)

    {

        $CI = & get_instance();

        return $CI->$key;

    }

}

(2)扩展CI_Loader实现,加载service,在application/core下新建MY_Loader.php文件:

<?php

class MY_Loader extends CI_Loader

{

    /**

  * List of loaded sercices

  *

  * @var array

  * @access protected

  */

 protected $_ci_services = array();

 /**

  * List of paths to load sercices from

  *

  * @var array

  * @access protected

  */

 protected $_ci_service_paths  = array();

    /**

     * Constructor

     * 

     * Set the path to the Service files

     */

    public function __construct()

    {

        parent::__construct();

        $this->_ci_service_paths = array(APPPATH);

    }

    /**

     * Service Loader

     * 

     * This function lets users load and instantiate classes.

  * It is designed to be called from a user's app controllers.

  *

  * @param string the name of the class

  * @param mixed the optional parameters

  * @param string an optional object name

  * @return void

     */

    public function service($service = '', $params = NULL, $object_name = NULL)

    {

        if(is_array($service))

        {

            foreach($service as $class)

            {

                $this->service($class, $params);

            }

            return;

        }

        if($service == '' or isset($this->_ci_services[$service])) {

            return FALSE;

        }

        if(! is_null($params) && ! is_array($params)) {

            $params = NULL;

        }

        $subdir = '';

        // Is the service in a sub-folder? If so, parse out the filename and path.

        if (($last_slash = strrpos($service, '/')) !== FALSE)

        {

                // The path is in front of the last slash

                $subdir = substr($service, 0, $last_slash + 1);

                // And the service name behind it

                $service = substr($service, $last_slash + 1);

        }

        foreach($this->_ci_service_paths as $path)

        {

            $filepath = $path .'service/'.$subdir.$service.'.php';

            if ( ! file_exists($filepath))

            {

                continue;

            }

            include_once($filepath);

            $service = strtolower($service);

            if (empty($object_name))

            {

                $object_name = $service;

            }

            $service = ucfirst($service);

            $CI = &get_instance();

            if($params !== NULL)

            {

                $CI->$object_name = new $service($params);

            }

            else

            {

                $CI->$object_name = new $service();

            }

            $this->_ci_services[] = $object_name;

            return;

        }

    }

}

(3)简单例子实现:
控制器中调用service :

<?php

class User extends CI_Controller

{

    public function __construct() 

    {

  

        parent::__construct();

        $this->load->service('user_service');

    }

    public function login()

    {

        $name = 'phpddt.com';

        $psw = 'password';

        print_r($this->user_service->login($name, $psw));

    }

}

service中调用model :

<?php

class User_service extends MY_Service

{

    public function __construct()

    {

        parent::__construct();

        $this->load->model('user_model');

    }

    public function login($name, $password)

    {

        $user = $this->user_model->get_user_by_where($name, $password);

        //.....

        //.....

        //.....

        return $user;

    }

}

model中你只跟db打交道:

<?php

class User_model extends CI_Model

{

    public function __construct()

    {

        parent::__construct();

    }

    public function get_user_by_where($name, $password)

    {

        //$this->db

        //......

        //......

        return array('id' => 1, 'name' => 'mckee');

    }

}

基本实现思路就是这样的。

PHP 相关文章推荐
php之对抗Web扫描器的脚本技巧
Oct 01 PHP
PHP提取字符串中的图片地址[正则表达式]
Nov 12 PHP
php 读取文件头判断文件类型的实现代码
Aug 05 PHP
php生成缩略图示例代码分享(使用gd库实现)
Jan 20 PHP
Yii结合CKEditor实现图片上传功能
Jun 13 PHP
php异步多线程swoole用法实例
Nov 14 PHP
php从csv文件读取数据并输出到网页的方法
Mar 14 PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
May 20 PHP
php批量转换文件夹下所有文件编码的函数类
Aug 06 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
Aug 29 PHP
Laravel 5.4.36中session没有保存成功问题的解决
Feb 19 PHP
php和nginx交互实例讲解
Sep 24 PHP
使用array_map简单搞定PHP删除文件、删除目录
Oct 29 #PHP
PHPUnit安装及使用示例
Oct 29 #PHP
laravel安装和配置教程
Oct 29 #PHP
laravel 4安装及入门图文教程
Oct 29 #PHP
thinkphp浏览历史功能实现方法
Oct 29 #PHP
thinkphp获取栏目和文章当前位置的方法
Oct 29 #PHP
thinkphp实现like模糊查询实例
Oct 29 #PHP
You might like
层叠菜单的动态生成
2006/10/09 PHP
利用static实现表格的颜色隔行显示
2006/10/09 PHP
PHP_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法
2014/05/04 PHP
thinkphp模板的包含与渲染实例分析
2014/11/26 PHP
PHP过滤黑名单关键字的方法
2014/12/01 PHP
PHP关联数组实现根据元素值删除元素的方法
2015/06/26 PHP
JavaScript QueryString解析类代码
2010/01/17 Javascript
jquery实现微博文字输入框 输入时显示输入字数 效果实现
2013/07/12 Javascript
javascript常见用法总结
2014/05/22 Javascript
JavaScript字符串对象的concat方法实例(用于连接两个或多个字符串)
2014/10/16 Javascript
JavaScript获取页面中表单(form)数量的方法
2015/04/03 Javascript
jquery控制表单输入框显示默认值的方法
2015/05/22 Javascript
AngularJS入门教程之数据绑定用法示例
2016/11/01 Javascript
使用Angular.js实现简单的购物车功能
2016/11/21 Javascript
node+koa实现数据mock接口的方法
2017/09/20 Javascript
JS实现对json对象排序并删除id相同项功能示例
2018/04/18 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
js中Function引用类型常见有用的方法和属性详解
2019/12/11 Javascript
[06:43]DAC2018 4.5 SOLO赛 Maybe vs Paparazi
2018/04/06 DOTA
python显示天气预报
2014/03/02 Python
Python中处理字符串之endswith()方法的使用简介
2015/05/18 Python
Python实现确认字符串是否包含指定字符串的实例
2018/05/02 Python
PyCharm代码格式调整方法
2018/05/23 Python
python数据批量写入ScrolledText的优化方法
2018/10/11 Python
利用python读取YUV文件 转RGB 8bit/10bit通用
2019/12/09 Python
django admin后管定制-显示字段的实例
2020/03/11 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
利用Python如何制作贪吃蛇及AI版贪吃蛇详解
2020/08/24 Python
Django-Scrapy生成后端json接口的方法示例
2020/10/06 Python
Python基于Socket实现简易多人聊天室的示例代码
2020/11/29 Python
应届大专毕业生个人自荐信
2013/09/22 职场文书
高中毕业生个人自我鉴定
2013/11/24 职场文书
高三地理教学反思
2014/01/11 职场文书
党员批评与自我批评(5篇)
2014/09/23 职场文书
中国文明网向国旗敬礼寄语大全
2014/09/27 职场文书
运动会100米加油稿
2015/07/21 职场文书