Fecshop 服務(wù)原理

2018-05-24 14:16 更新

Fecshop 服務(wù)原理

fecshop服務(wù)是一個(gè)公用性的底層,為各個(gè)應(yīng)用系統(tǒng)提供底層服務(wù)

1.原則約定

各個(gè)“應(yīng)用系統(tǒng)”,譬如appfront,appadmin,apphtml5,是一個(gè)獨(dú)立的文件結(jié)構(gòu) ,他們都有獨(dú)立的模塊,里面有controller(控制層) block(數(shù)據(jù)中間邏輯處理層) theme(模板view層) ,但是沒有model層,在原則上約定,各個(gè)“應(yīng)用系統(tǒng)”不能直接訪問model, 只能訪問Fecshop Service(服務(wù)),來(lái)進(jìn)行數(shù)據(jù)的獲取和處理工作,然后由service層 訪問model層進(jìn)行數(shù)據(jù)的獲取處理等工作。

2.服務(wù)層的功能粒度:

首先,對(duì)于model層的函數(shù)粒度,對(duì)應(yīng)的是數(shù)據(jù)的操作,譬如更改某一行數(shù)據(jù),添加一行數(shù)據(jù)等,這個(gè)地球人都知道。

對(duì)于service層的函數(shù)粒度,一般是我們語(yǔ)言描述需求的最小粒度,譬如:把一個(gè)產(chǎn)品加入購(gòu)物車, 刪除購(gòu)物車的某個(gè)產(chǎn)品,調(diào)出某個(gè)分類下的產(chǎn)品,登錄用戶,計(jì)算產(chǎn)品的最終價(jià)格,等等,對(duì)于上面的這些最小的 語(yǔ)言描述粒度,會(huì)在服務(wù)層實(shí)現(xiàn),然后直接訪問該服務(wù)中的方法即可。

3.實(shí)現(xiàn)原理

3.1 實(shí)例化過(guò)程:

當(dāng)我們執(zhí)行 Yii::$service->cart,就會(huì)訪問fecshop cart service 服務(wù) 當(dāng)執(zhí)行Yii::$service->cart->coupon 就會(huì)訪問 cart的子服務(wù)coupon。

下面是實(shí)例化原理:

在index.php入口文件中可以看到如下代碼:

new fecshop\services\Application($config['services']);
unset($config['services']);

查看 fecshop\services\Application.php的代碼如下:

<?php
/**
 * FecShop file.
 *
 * @link http://www.fecshop.com/
 * @copyright Copyright (c) 2016 FecShop Software LLC
 * @license http://www.fecshop.com/license/
 */
namespace fecshop\services;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
/**
 * @author Terry Zhao <2358269014@qq.com>
 * @since 1.0
 */
class Application
{
    public $childService;
    public $_childService;

    

    
    public function __construct($config = [])
    {
        Yii::$service       = $this;
        $this->childService = $config;
    }
    /**
     * 得到services 里面配置的子服務(wù)childService的實(shí)例
     */
    public function getChildService($childServiceName){
        if(!$this->_childService[$childServiceName]){
            $childService = $this->childService;
            if(isset($childService[$childServiceName])){
                $service = $childService[$childServiceName];
                $this->_childService[$childServiceName] = Yii::createObject($service);
            }else{
                throw new InvalidConfigException('Child Service ['.$childServiceName.'] is not find in '.get_called_class().', you must config it! ');
            }
        }
        return $this->_childService[$childServiceName];
    }

    
    /**
     * 
     */
    public function __get($attr){
        return $this->getChildService($attr);

        
    }

    
}

service配置,譬如:@fecshop\config\services\Cart.php

<?php
/**
 * FecShop file.
 * @link http://www.fecshop.com/
 * @copyright Copyright (c) 2016 FecShop Software LLC
 * @license http://www.fecshop.com/license/
 */
return [
    'cart' => [
        'class' => 'fecshop\services\Cart',

        
        # 子服務(wù)
        'childService' => [
            'quote' => [
                'class' => 'fecshop\services\cart\Quote',
            ],
            'quoteItem' => [
                'class' => 'fecshop\services\cart\QuoteItem',
            ],

            
            'info' => [
                'class' => 'fecshop\services\cart\Info',
                /**
                 * 單個(gè)sku加入購(gòu)物車的最大個(gè)數(shù)。
                 */
                'maxCountAddToCart' => 100,
                # 上架狀態(tài)產(chǎn)品加入購(gòu)物車時(shí),
                # 如果addToCartCheckSkuQty設(shè)置為true,則需要檢查產(chǎn)品qty是否>購(gòu)買qty,
                # 如果設(shè)置為false,則不需要,也就是說(shuō)產(chǎn)品庫(kù)存qty小于購(gòu)買qty,也是可以加入購(gòu)物車的。
                'addToCartCheckSkuQty' => true,
            ],
            'coupon' => [
                'class' => 'fecshop\services\cart\Coupon',
            ],
        ],
    ],
];

Yii::$service->cart 就是cart服務(wù)

Yii::$service 對(duì)應(yīng)的是 fecshop\services\Application 當(dāng)執(zhí)行Yii::$service->cart時(shí),找不到cart變量就會(huì)執(zhí)行 __get()魔術(shù)方法,進(jìn)而執(zhí)行 getChildService(),將上面cart配置的class對(duì)應(yīng)的文件fecshop\services\Cart, 進(jìn)行實(shí)例化,也就是說(shuō) Yii::$service->cart 對(duì)應(yīng)的是 fecshop\services\Cart 實(shí)例化的對(duì)象, 如果下次使用 Yii::$service->cart ,不會(huì)再實(shí)例化對(duì)象,F(xiàn)ecShop Service是單例模式。

Fecshop子服務(wù):Yii::$service->cart->coupon,通過(guò)上面的配置,會(huì)實(shí)例化 fecshop\services\cart\Coupon,子服務(wù)的原理和服務(wù)類似,都是單例模式。

3.2 關(guān)于service類

上面講解了 Yii::$service->cart,如何找到 fecshop\services\Cart的步驟,下面詳細(xì)講述 service類。

所有的服務(wù)類,譬如上面說(shuō)的cart服務(wù),都必須繼承 @fecshop\services\Service。 里面的方法都必須以action開頭,和controller中類似, 譬如執(zhí)行 Yii::$service->cart->addProductToCart($item),對(duì)應(yīng)的是 fecshop\services\Cart中的 protected function actionAddProductToCart($item)方法。

原理為:當(dāng)訪問 addProductToCart時(shí),由于找不到該函數(shù),就會(huì)執(zhí)行 @fecshop\services\Service->__call()魔術(shù)方法,然后由魔術(shù)方法, 將 addProductToCart 改成 actionAddProductToCart,然后去查找函數(shù),就會(huì)找到 ,這樣做的好處是,可以在__call()函數(shù)中記錄每一個(gè)service的方法調(diào)用開始時(shí)間 和結(jié)束時(shí)間,這樣就可以更好的調(diào)試出來(lái)哪一個(gè)service方法耗費(fèi)的時(shí)間長(zhǎng), 這個(gè)是為了更好地統(tǒng)計(jì)各個(gè)services的狀況,譬如:排查耗費(fèi)時(shí)間最長(zhǎng)的services, 使用最頻繁的services等, 當(dāng)然會(huì)耗費(fèi)一定的時(shí)間, 在線上可以關(guān)掉log記錄時(shí)間的功能,也可以間斷性的手動(dòng)開啟,進(jìn)行線上調(diào)試。

關(guān)于services log的開啟:@fecshop\config\services\Helper中看到如下配置:

return [
    'helper' => [
        'class' => 'fecshop\services\Helper',
        # 子服務(wù)
        'childService' => [
            'ar' => [
                'class' => 'fecshop\services\helper\AR',
            ],
            'log' => [
                'class' => 'fecshop\services\helper\Log',
                'log_config' => [
                    # service log config
                    'services' => [  
                        # if enable is false , all services will be close
                        'enable' => false,  # 這里可以開啟services log功能。

通過(guò)配置helper log服務(wù)的enable設(shè)置為true,可以開啟services的日志功能

當(dāng)然helper log服務(wù)還有其他的一些設(shè)置,具體請(qǐng)參看詳細(xì)代碼。

當(dāng)然,您可以把服務(wù)中的類函數(shù)定義成public ,函數(shù)名不以action開頭, 這種方式定義的函數(shù),開啟services log,不會(huì)被記錄,因?yàn)橹苯诱业胶瘮?shù)名,不會(huì) 訪問魔術(shù)方法__call()

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)