如何让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 相关文章推荐
3.从实例开始
Oct 09 PHP
php 表单验证实现代码
Mar 10 PHP
php 图像函数大举例(非原创)
Jun 20 PHP
php 404错误页面实现代码
Jun 22 PHP
PHP开发不能违背的安全规则 过滤用户输入
May 01 PHP
php和js如何通过json互相传递数据相关问题探讨
Feb 26 PHP
PHP 动态生成静态HTML页面示例代码
Jan 15 PHP
php截取中文字符串函数实例
Feb 23 PHP
Mac系统下使用brew搭建PHP(LNMP/LAMP)开发环境
Mar 03 PHP
PHP实现简单的新闻发布系统实例
Jul 28 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
Sep 22 PHP
PHP多进程通信-消息队列使用
Mar 08 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
索尼SONY ICF-7600A(W)电路分析
2021/03/01 无线电
php 常用字符串函数总结
2008/03/15 PHP
php str_pad() 将字符串填充成指定长度的字符串
2010/02/23 PHP
ThinkPHP中实例Model方法的区别说明
2010/08/21 PHP
浅析php中jsonp的跨域实例
2013/06/21 PHP
怎么让脚本或里面的函数在所有图片都载入完毕的时候执行
2006/10/17 Javascript
JavaScript中Object和Function的关系小结
2009/09/26 Javascript
UpdatePanel和Jquery冲突的解决方法
2013/04/01 Javascript
js跨浏览器实现将字符串转化为xml对象的方法
2013/09/25 Javascript
javascript删除option选项的多种方法总结
2013/11/22 Javascript
用jQuery toggleClass 实现鼠标移上变色
2014/05/14 Javascript
JQuery异步获取返回值中文乱码的解决方法
2015/01/29 Javascript
通过XMLHttpRequest和jQuery实现ajax的几种方式
2015/08/28 Javascript
javascript中的3种继承实现方法
2016/01/27 Javascript
JavaScript知识点总结(五)之Javascript中两个等于号(==)和三个等于号(===)的区别
2016/05/31 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
使用node搭建自动发图文微博机器人的方法
2019/03/22 Javascript
Python统计文件中去重后uuid个数的方法
2015/07/30 Python
python实现简易内存监控
2018/06/21 Python
opencv实现简单人脸识别
2021/02/19 Python
Python通过Manager方式实现多个无关联进程共享数据的实现
2019/11/07 Python
关于numpy.where()函数 返回值的解释
2019/12/06 Python
浅谈keras中的目标函数和优化函数MSE用法
2020/06/10 Python
3分钟看懂Python后端必须知道的Django的信号机制
2020/07/26 Python
python 读取串口数据的示例
2020/11/09 Python
CSS3自定义滚动条样式 ::webkit-scrollbar的示例代码详解
2020/06/01 HTML / CSS
iPhoneX安全区域(Safe Area)底部小黑条在微信小程序和H5的屏幕适配
2020/04/08 HTML / CSS
最好的意大利皮夹克:D’Arienzo
2018/12/04 全球购物
老同学聚会感言
2014/02/23 职场文书
感恩母亲节活动方案
2014/03/04 职场文书
博士生导师推荐信
2014/07/08 职场文书
关于青春的演讲稿800字
2014/08/22 职场文书
2015年全国保险公众宣传日活动方案
2015/05/06 职场文书
护理心得体会范文
2016/01/22 职场文书
Pytest中skip和skipif的具体使用方法
2021/06/30 Python
vue实现登陆页面开发实践
2022/05/30 Vue.js