如何让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 数组遍历的差异(array_diff 的实现)
Mar 23 PHP
php中将数组存到文件里的实现代码
Jan 19 PHP
解析php常用image图像函数集
Jun 24 PHP
ThinkPHP3.1新特性之多层MVC的支持
Jun 19 PHP
浅谈PHP中Stream(流)
Jun 08 PHP
PHP快速排序quicksort实例详解
Sep 28 PHP
php 中奖概率算法实现代码
Jan 25 PHP
thinkphp分页集成实例
Jul 24 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
PHP的PDO预处理语句与存储过程
Jan 27 PHP
PHP中类与对象功能、用法实例解读
Mar 27 PHP
ThinkPHP5和ThinkPHP6的区别
Mar 31 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二维码生成
2015/10/19 PHP
Auntion-TableSort国人写的一个javascript表格排序的东西
2007/11/12 Javascript
初窥JQuery(二) 事件机制(1)
2010/11/25 Javascript
仿微博字符限制效果实现代码
2012/04/20 Javascript
jQuery中阻止冒泡事件的方法介绍
2014/04/12 Javascript
javascript模拟订火车票和退票示例
2014/04/24 Javascript
JS实现鼠标经过好友列表中的好友头像时显示资料卡的效果
2014/07/02 Javascript
浅谈javascript中call()、apply()、bind()的用法
2015/04/20 Javascript
JavaScript匿名函数之模仿块级作用域
2015/12/12 Javascript
JavaScript制作简单分页插件
2016/09/11 Javascript
JavaScript 身份证号有效验证详解及实例代码
2016/10/20 Javascript
ES6新数据结构Map功能与用法示例
2017/03/31 Javascript
解决vue router使用 history 模式刷新后404问题
2017/07/19 Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
2018/10/26 Javascript
详解在create-react-app使用less与antd按需加载
2018/12/06 Javascript
详解react阻止无效重渲染的多种方式
2018/12/11 Javascript
微信小程序实现单列下拉菜单效果
2019/04/25 Javascript
jQuery实现放大镜案例
2020/10/19 jQuery
Handtrack.js库实现实时监测手部运动(推荐)
2021/02/08 Javascript
python中Genarator函数用法分析
2015/04/08 Python
Python中Random和Math模块学习笔记
2015/05/18 Python
Python函数可变参数定义及其参数传递方式实例详解
2015/05/25 Python
python实现单线程多任务非阻塞TCP服务端
2017/06/13 Python
Python两台电脑实现TCP通信的方法示例
2019/05/06 Python
Python设置matplotlib.plot的坐标轴刻度间隔以及刻度范围
2019/06/25 Python
django创建简单的页面响应实例教程
2019/09/06 Python
python 实时调取摄像头的示例代码
2020/11/25 Python
Guess欧洲官网:美国服饰品牌
2019/08/06 全球购物
VisionPros美国站:加拿大在线隐形眼镜和眼镜零售商
2020/02/11 全球购物
乡镇纠风工作实施方案
2014/03/22 职场文书
软件售后服务承诺书
2014/05/21 职场文书
化验员岗位职责
2015/02/14 职场文书
2015年“我们的节日·中秋节”活动总结
2015/07/30 职场文书
初中物理教学反思
2016/02/19 职场文书
2016年大学生党员公开承诺书
2016/03/24 职场文书
彻底理解golang中什么是nil
2021/04/29 Golang