如何让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维护文件系统
Oct 09 PHP
如何在PHP程序中防止盗链
Apr 09 PHP
PHP生成带有雪花背景的验证码
Sep 28 PHP
PHP跳转页面的几种实现方法详解
Jun 08 PHP
CURL状态码列表(详细)
Jun 27 PHP
PHP5.5和之前的版本empty函数的不同之处
Jun 13 PHP
浅析php适配器模式(Adapter)
Nov 25 PHP
PHP实现基于文本的摩斯电码生成器
Jan 11 PHP
PHP小偷程序的设计与实现方法详解
Oct 15 PHP
PHP连接MYSQL数据库的3种常用方法
Feb 27 PHP
PHP连接及操作PostgreSQL数据库的方法详解
Jan 30 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
Dec 30 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
用文本作数据处理
2006/10/09 PHP
php替换超长文本中的特殊字符的函数代码
2012/05/22 PHP
关于PHP的curl开启问题探讨
2014/04/08 PHP
php实现兼容2038年后Unix时间戳转换函数
2015/03/18 PHP
一个PHP实现的轻量级简单爬虫
2015/07/08 PHP
PHP安全下载文件的方法
2016/04/07 PHP
BootStrap Tooltip插件源码解析
2016/12/27 Javascript
4个顶级开源JavaScript图表库
2018/09/29 Javascript
webpack的 rquire.context用法实现工程自动化的方法
2020/02/07 Javascript
详解js中的原型,原型对象,原型链
2020/07/16 Javascript
node.js通过Sequelize 连接MySQL的方法
2020/12/28 Javascript
[38:40]2018DOTA2亚洲邀请赛 4.6淘汰赛 mineski vs LGD 第一场
2018/04/10 DOTA
[53:29]完美世界DOTA2联赛循环赛 DM vs Matador BO2第二场 11.04
2020/11/05 DOTA
Python使用wget实现下载网络文件功能示例
2018/05/31 Python
python针对不定分隔符切割提取字符串的方法
2018/10/26 Python
python实现windows壁纸定期更换功能
2019/01/21 Python
使用WingPro 7 设置Python路径的方法
2019/07/24 Python
Python全栈之列表数据类型详解
2019/10/01 Python
Python获取对象属性的几种方式小结
2020/03/12 Python
python实现3D地图可视化
2020/03/25 Python
Django 解决开发自定义抛出异常的问题
2020/05/21 Python
利用Python实现学生信息管理系统的完整实例
2020/12/30 Python
使用CSS3实现一个3D相册效果实例
2016/12/03 HTML / CSS
意大利综合购物网站:Giordano Shop
2016/10/21 全球购物
APM Monaco中国官网:来自摩纳哥珠宝品牌
2017/12/27 全球购物
意大利和国际最佳时尚品牌:Drestige
2019/12/28 全球购物
土木工程毕业生自荐信
2013/09/21 职场文书
毕业生求职自荐书范文
2014/03/27 职场文书
股东合作协议书范本
2014/04/14 职场文书
春游踏青活动方案
2014/08/14 职场文书
世界读书日的活动方案
2014/08/20 职场文书
销售顾问工作计划书
2014/09/15 职场文书
2015年新学期寄语
2015/02/26 职场文书
小学家庭教育心得体会
2016/01/14 职场文书
入党申请书怎么写?
2019/06/21 职场文书
MongoDB修改oplog大小的四种方法
2022/04/11 MongoDB