最近做了一些事情,其中一件就是分离出之前基于CI写的Service层并打包发布到GitHub。
想着还是应该留下一点什么,便是来由。
这是还在Yumeer的时候,那会儿江哥刚来,梳理了整个业务逻辑,发现杂乱无章,遂推倒了重来。还是我一人负责后端,囿于经验,之前完全是hard-coding,代码复用性基本为0,加之CI的特性:
-The Model represents your data structures. Typically your model classes will contain functions that help you retrieve, insert, and update information in your database.
-The View is the information that is being presented to a user. A View will normally be a web page, but in CodeIgniter, a view can also be a page fragment like a header or footer. It can also be an RSS page, or any other type of “page”.
-The Controller serves as an intermediary between the Model, the View, and any other resources needed to process the HTTP request and generate a web page.
导致大量business logic堆积到Controller层甚至Model层,着实难看。后面江哥提出一个想法,做Microservice,了解过后,准备开做。
CI的简洁易用性出于此,麻烦也同出于此。由于Controller层无法互相调用,在设计模式上,只能通过新构建一层架于C-M之间。本着面向Google/Stackoverflow编程的原则(手动滑稽),先找了找,发现了一些思路和代码片段。遂开始仔细分析。
CI提供了极其灵活的扩展接口,分析过后,找到一条路,简而言之就是通过对core的扩展,增加一层类似于library层的独立层,同样使用原生load进行加载。
核心代码:
// The service layer core
public function service($service = '', $params = NULL, $object_name = NULL)
{
if (is_array($service)) {
foreach ($service as $class) {
$this->service($class, $params);
}
return $this;
}
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 . 'services/' . $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 $this;
}
}
// Extend load
class MY_Service
{
public function __construct()
{
log_message('debug', "Service Class Initialized");
}
function __get($key)
{
$CI =& get_instance();
return $CI->$key;
}
}
Flowchart:
待补
GitHub:
acerest/ServiceLayer4CodeIgniter
欢迎Star :)