CI 扩展 Service

CI 扩展 Service

说明

CodeIgniter是一套典型的MVC框架,M负责数据,C负责交互,V负责视图,但是随着业务逻辑越来越复杂,
必然会涉及到一些列操作过程,例如用户下订单,就会存在校验,核算金额,保存记录,增加积分等系列操作,
显然无法将所有逻辑都写在Controller中,导致代码臃肿以致无法维护。
为了解决以上问题,可以增加一个业务层service,由service负责业务逻辑的编写,分装好接口供Controller调用。

  • Model:模型层,作为数据载体
  • Service : 业务逻辑层,负责业务模块的逻辑应用设计
  • Controller :控制层,负责具体业务流程控制,调用service层,将数据返回到视图
  • View : 视图层,负责展示视图及数据

CodeIgniter中application是应用程序目录,其中Models,Views,Controllers分别对应M、V、C目录,
同样的,希望在application目录下存在services目录,用来存放业务逻辑层代码。

实现

父类

首先,我们在application/core下新建扩展MY_Service.php,作为所有service类的父类,代码如下

<?php

class MY_Service
{
    public function __construct()
    {
        log_message('info', "Service Class Initialized");
    }
 
    function __get($key)
    {
        $CI = & get_instance();
        return $CI->$key;
    }
}

加载

其次,我们在application/core下新建扩展MY_Loader.php,扩展默认的Loader类,在其中添加加载service的方法,
这样就可以通过loader加载对应service类

<?php
if (! defined ( 'BASEPATH' )) exit ( 'No direct access allowed.' );

class MY_Loader extends CI_Loader {
    
    //service path
    protected $_ci_services_paths = array(APPPATH);
    
    //service class
    protected $_ci_services = array();
    
    
    
    public function __construct() {
        parent::__construct ();
    }
    
    /**
    * 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	object
    */
    public function service($service = '', $params = NULL, $object_name = NULL)
    {
        if (empty($service))
        {
            return $this;
        }
        else if(is_array($service))
        {
            //Is the service is an array?If so,load every key
            foreach ($service as $key => $value)
            {
                is_int($key) ? $this->service($value, '', $object_name) : $this->service($key, $value, $object_name);
            }
            
            return $this;
        }
        
        $path = '';
        
        // 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
            $path = substr($service, 0, ++$last_slash);
            
            // And the service name behind it
            $service = substr($service, $last_slash);
        }
        
        if (empty($object_name))
        {
            $object_name = $service;
        }

        $object_name = strtolower($object_name);
        if (in_array($object_name, $this->_ci_services, TRUE))
        {
            return $this;
        }
        
        $CI =& get_instance();
        if (isset($CI->$object_name))
        {
            throw new RuntimeException('The service name you are loading is the name of a resource that is already being used: '.$object_name);
        }
        
        //load MY_Service
        $class = config_item('subclass_prefix').'Service';
        $app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;
        
        if(!class_exists($class, FALSE))
        {
            if (file_exists($app_path.$class.'.php'))
            {
                require_once($app_path.$class.'.php');
                if (!class_exists($class, FALSE))
                {
                    throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class);
                }
            }
        }
        
        $service = ucfirst($service);
        if (!class_exists($service, FALSE))
        {   
            //load service files
            foreach ($this->_ci_services_paths as $service_path)
            {
                if ( ! file_exists($service_path.'services/'.$path.$service.'.php'))
                {
                    continue;
                }
                //default path application/services/
                include_once($service_path.'services/'.$path.$service.'.php');
                
                $CI = &get_instance();
                
                if($params !== NULL)
                {
                    $CI->$object_name = new $service($params);
                }
                else
                {
                    $CI->$object_name = new $service();
                }
                
                $this->_ci_services[] = $object_name;
                
                if (!class_exists($service, FALSE))
                {
                    throw new RuntimeException($service_path."services/".$path.$service.".php exists, but doesn't declare class ".$service);
                }
                
                break;
            }
        
        }
    
        return $this;
    }
}

调用

在application/services目录下创建一个示例文件Demo.php,代码如下

<?php
class Demo extends MY_Service{
    
    public function Hello()
    {
        return "Hello World";
    }
}

在Controller中调用Demo服务,代码如下

<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class Home extends MY_Controller {
    
    public function Index()
    {
        //调用对应的服务
        $this->load->service('Demo');
        
        //执行服务方法
        echo $this->index->Hello();
    }
}

在浏览器中查看可以看到对应的输出为Hello World

原文地址:https://www.cnblogs.com/SLchuck/p/5804555.html