如何让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 相关文章推荐
打造计数器DIY三步曲(中)
Oct 09 PHP
php和js交互一例-PHP教程,PHP应用
Jan 03 PHP
escape unescape的php下的实现方法
Apr 27 PHP
php设计模式 Template (模板模式)
Jun 26 PHP
php urlencode()与urldecode()函数字符编码原理详解
Dec 06 PHP
IIS安装Apache伪静态插件的具体操作图文
Jul 01 PHP
php采集内容中带有图片地址的远程图片并保存的方法
Jan 03 PHP
php数组键名技巧小结
Feb 17 PHP
PDO::rollBack讲解
Jan 29 PHP
PHP PDOStatement::bindValue讲解
Jan 30 PHP
laravel-admin自动生成模块,及相关基础配置方法
Oct 08 PHP
php和js实现根据子网掩码和ip计算子网功能示例
Nov 09 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中++i 与 i++ 的区别
2012/08/08 PHP
基于命令行执行带参数的php脚本并取得参数的方法
2016/01/25 PHP
php使用escapeshellarg时中文被过滤的解决方法
2016/07/10 PHP
PHP简单实现DES加密解密的方法
2016/07/12 PHP
PHP封装mysqli基于面向对象的mysql数据库操作类与用法示例
2019/02/25 PHP
基于laravel where的高级使用方法
2019/10/10 PHP
js判断IE6/IE7/FF的代码[XMLHttpRequest]
2011/02/16 Javascript
基于jquery跨浏览器显示的file上传控件
2011/10/24 Javascript
jquery load事件(callback/data)使用方法及注意事项
2013/02/06 Javascript
原生javascript实现图片滚动、延时加载功能
2015/01/12 Javascript
理解JavaScript事件对象
2016/01/25 Javascript
Bootstrap树形组件jqTree的简单封装
2016/01/25 Javascript
vuex中使用对象展开运算符的示例
2017/09/25 Javascript
js实现HTML中Select二级联动的实例
2018/01/05 Javascript
vue-router 实现导航守卫(路由卫士)的实例代码
2018/09/02 Javascript
Vue 样式绑定的实现方法
2019/01/15 Javascript
Node.js Windows Binary二进制文件安装方法
2019/05/16 Javascript
初学vue出现空格警告的原因及其解决方案
2019/10/31 Javascript
vue-autoui自匹配webapi的UI控件的实现
2020/03/20 Javascript
[42:20]2014 DOTA2华西杯精英邀请赛5 24 DK VS NewBee
2014/05/25 DOTA
pycharm 使用心得(八)如何调用另一文件中的函数
2014/06/06 Python
使用wxPython获取系统剪贴板中的数据的教程
2015/05/06 Python
Python基于checksum计算文件是否相同的方法
2015/07/09 Python
python自动发邮件库yagmail的示例代码
2018/02/23 Python
Python3 使用cookiejar管理cookie的方法
2018/12/28 Python
Python计算时间间隔(精确到微妙)的代码实例
2019/02/26 Python
Python使用百度翻译开发平台实现英文翻译为中文功能示例
2019/08/08 Python
python实现高斯判别分析算法的例子
2019/12/09 Python
Python如何实现自带HTTP文件传输服务
2020/07/08 Python
医院实习介绍信
2014/01/12 职场文书
元旦活动感言
2014/03/08 职场文书
好学生评语大全
2014/05/05 职场文书
党员对十八届四中全会的期盼思想汇报范文
2014/10/17 职场文书
2014年小学辅导员工作总结
2014/12/23 职场文书
Python爬取科目四考试题库的方法实现
2021/03/30 Python
MySQL窗口函数的具体使用
2021/11/17 MySQL