如何让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 相关文章推荐
附件名前加网站名
Mar 23 PHP
php 操作excel文件的方法小结
Dec 31 PHP
phpmyadmin显示utf8_general_ci中文乱码的问题终级篇
Apr 08 PHP
使用session判断用户登录用户权限(超简单)
Jun 08 PHP
php连接函数implode与分割explode的深入解析
Jun 26 PHP
PHP抓取、分析国内视频网站的视频信息工具类
Apr 02 PHP
php实现的百度搜索某地天气的小偷代码
Apr 23 PHP
PHP中使用break跳出多重循环代码实例
Jan 21 PHP
PHP异常处理定义与使用方法分析
Jul 25 PHP
Laravel构建即时应用的一种实现方法详解
Aug 31 PHP
PHP实现发送微博消息功能完整示例
Dec 04 PHP
ThinkPHP3.1.2 使用cli命令行模式运行的方法
Apr 14 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的构造方法,析构方法和this关键字详细介绍
2013/10/22 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
捕获关闭窗口的脚本
2009/01/10 Javascript
jQuery方法简洁实现隔行换色及toggleClass的使用
2013/03/15 Javascript
做好七件事帮你提升jQuery的性能
2014/02/06 Javascript
让angularjs支持浏览器自动填表
2014/11/10 Javascript
jQuery实现的多张图无缝滚动效果【测试可用】
2016/09/12 Javascript
JS传参及动态修改页面布局
2017/04/13 Javascript
JavaScript获取用户所在城市及地理位置
2018/04/21 Javascript
node打造微信个人号机器人的方法示例
2018/04/26 Javascript
vue使用echarts图表的详细方法
2018/10/22 Javascript
详解微信小程序与内嵌网页交互实现支付功能
2018/10/22 Javascript
Vue动态修改网页标题的方法及遇到问题
2019/06/09 Javascript
浅谈一个webpack构建速度优化误区
2019/06/24 Javascript
Python使用poplib模块和smtplib模块收发电子邮件的教程
2016/07/02 Python
Python排序搜索基本算法之希尔排序实例分析
2017/12/09 Python
在windows下Python打印彩色字体的方法
2018/05/15 Python
python实现决策树分类(2)
2018/08/30 Python
python之验证码生成(gvcode与captcha)
2019/01/02 Python
python numpy 按行归一化的实例
2019/01/21 Python
利用PyCharm Profile分析异步爬虫效率详解
2019/05/08 Python
django2.2安装错误最全的解决方案(小结)
2019/09/24 Python
解决os.path.isdir() 判断文件夹却返回false的问题
2019/11/29 Python
Python sql注入 过滤字符串的非法字符实例
2020/04/03 Python
Sentry错误日志监控使用方法解析
2020/11/12 Python
New Balance英国官方网站:始于1906年,百年慢跑品牌
2016/12/07 全球购物
巴西女装购物网站:Eclectic
2018/04/24 全球购物
Watch Station官方网站:世界一流的手表和智能手表
2020/01/05 全球购物
社团招新策划书
2014/02/04 职场文书
文明村创建实施方案
2014/03/27 职场文书
计划生育证明格式范本
2014/09/12 职场文书
个性与发展自我评价
2015/03/06 职场文书
2015年银行员工工作总结
2015/04/24 职场文书
关于迟到的检讨书
2015/05/06 职场文书
2015年安全保卫工作总结
2015/05/14 职场文书
Django对接elasticsearch实现全文检索的示例代码
2021/08/02 Python