如何让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数字格式化
Dec 06 PHP
discuz Passport 通行证 整合笔记
Jun 30 PHP
destoon后台网站设置变成空白的解决方法
Jun 21 PHP
destoon调用discuz论坛中带图片帖子的实现方法
Aug 21 PHP
Yii框架中sphinx索引配置方法解析
Oct 18 PHP
MAC下通过改apache配置文件切换php多版本的方法
Apr 26 PHP
php判断str字符串是否是xml格式数据的方法示例
Jul 26 PHP
php单元测试phpunit入门实例教程
Nov 17 PHP
Laravel关联模型中过滤结果为空的结果集(has和with区别)
Oct 18 PHP
python进程与线程小结实例分析
Nov 11 PHP
PHP中md5()函数的用法讲解
Mar 30 PHP
PHP5.6.8连接SQL Server 2008 R2数据库常用技巧分析总结
May 06 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
PHP变量赋值、代入给JavaScript中的变量
2015/06/29 PHP
php 无限分类 树形数据格式化代码
2016/10/11 PHP
在Thinkphp中使用ajax实现无刷新分页的方法
2016/10/25 PHP
PHP一个简单的无需刷新爬虫
2019/01/05 PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
2019/04/02 PHP
js change,propertychange,input事件小议
2011/12/20 Javascript
jquery 实现上下滚动效果示例代码
2013/08/09 Javascript
jQuery 无刷新分页实例代码
2013/11/12 Javascript
jQuery中empty()方法用法实例
2015/01/16 Javascript
js获得当前系统日期时间的方法
2015/05/06 Javascript
JS将滑动门改为选项卡(需鼠标点击)的实现方法
2015/09/27 Javascript
jQuery的选择器中的通配符[id^='code']或[name^='code']及jquery选择器总结
2015/12/24 Javascript
css和js实现弹出登录居中界面完整代码
2017/11/26 Javascript
JS插件clipboard.js实现一键复制粘贴功能
2020/12/04 Javascript
jQuery实现的模仿雨滴下落动画效果
2018/12/11 jQuery
bootstrap Table实现合并相同行
2019/07/19 Javascript
Vue实现简易计算器
2020/02/25 Javascript
Vue+ElementUI 中级联选择器Bug问题的解决
2020/07/31 Javascript
Python实现list反转实例汇总
2014/11/11 Python
Python多线程编程(一):threading模块综述
2015/04/05 Python
python在控制台输出进度条的方法
2015/06/20 Python
python实现单线程多任务非阻塞TCP服务端
2017/06/13 Python
Python基于pyCUDA实现GPU加速并行计算功能入门教程
2018/06/19 Python
解决python os.mkdir创建目录失败的问题
2018/10/16 Python
利用Python求阴影部分的面积实例代码
2018/12/05 Python
python3 pathlib库Path类方法总结
2019/12/26 Python
pandas数据选取:df[] df.loc[] df.iloc[] df.ix[] df.at[] df.iat[]
2020/04/24 Python
用Python实现童年贪吃蛇小游戏功能的实例代码
2020/12/07 Python
Skip Hop官网:好莱坞宝宝挚爱品牌
2018/06/17 全球购物
意大利消费电子产品购物网站:SLG Store
2019/12/26 全球购物
劳资专员岗位职责
2013/12/27 职场文书
八年级数学教学反思
2014/01/31 职场文书
《理想》教学反思
2014/02/17 职场文书
颁奖典礼主持词
2014/03/25 职场文书
车辆工程专业求职信
2014/06/14 职场文书
《这片土地是神圣的》教学反思
2016/02/16 职场文书