天天看點

thinkphp 面向切面程式設計-行為拓展

thinkphp的CBD模式

核心保留了最關鍵的部分,并在重要位置設定了标簽用以标記,其他功能都采用行為擴充和驅動的方式組合,開發人員可以根據自己的需要,對某個标簽位置進行行為擴充或者替換,就可以友善的定制架構底層,也可以在應用層添加自己的标簽位置和添加應用行為。而标簽位置類似于AOP概念中的“切面”,行為都是圍繞這個“切面”來進行程式設計。

CBD主要由Core(核心)、Behavior(行為)以及Drivers(驅動)三部分組成。在ThinkPHP中,Core是指諸如路由配置,基礎模型類、Behavior中使用到的行為标簽配置這些最重要的核心函數庫、類庫以及配置檔案。Behavior是架構中比較關鍵的一種機制,在thinkphp中是實作了“鈎子”的功能,恰當的使用可以有效降低業務邏輯之間的耦合度,下面會詳細。而Drivers是基于功能的,為架構的功能拓展提供驅動,比如資料庫驅動,緩存驅動。

Behavior(行為)

AOP

這種在運作時,動态地将代碼切入到類的指定方法、指定位置上的程式設計思想就是面向切面的程式設計 http://hejiajunsh.iteye.com/blog/1776569

AOP(Aspect Oriented Program)與傳統的面向對象程式設計并不沖突,反而可以對OOP程式設計作出補充,增加某些代碼的重用性,降低不同業務邏輯之間的耦合度,使團隊開發更為容易且可以有效降低開發周期。

鈎子函數

鈎子是程式設計裡一個常見概念,非常的重要。它使得系統變得非常容易拓展,(而不用了解其内部的實作機理,這樣可以減少很多工作量)。

可以了解為當一個玻璃球從空中落下,即将砸到人的時候,有個事件會提前發生.例如告訴那個被砸的人,球已經在下落過程中,

告訴就是一個事件,一個鈎子,我們可以針對不同的人做出不同的相應,如果是男人我們告訴他這個球砸到人不疼,如果是女人則告訴她很疼;

鈎子函數可以截獲并處理其他應用程式的消息。每當特定的消息發出,在沒有到達目的視窗前,鈎子程式就先捕獲該消息,亦即鈎子函數先得到控制權。這時鈎子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。

設定鈎子的過程其實就是設定事件驅動的過程,簡單來講就是定義鈎子函數,注冊事件,監聽(挂載),滿足觸發條件并觸發鈎子函數。

行為拓展

行為(Behavior)是ThinkPHP擴充機制中比較關鍵的一項擴充,行為既可以獨立調用,也可以綁定到某個标簽(位)中進行偵聽。這裡的行為指的是一個比較抽象的概念,你可以想象成在應用執行過程中的一個動作或者處理,在架構的執行流程中,各個位置都可以有行為産生,例如路由檢測是一個行為,靜态緩存是一個行為,使用者權限檢測也是行為,大到業務邏輯,小到浏覽器檢測、多語言檢測等等都可以當做是一個行為,甚至說你希望給你的網站使用者的第一次通路彈出Hello,world!這些都可以看成是一種行為,行為的存在讓你無需改動架構和應用,而在外圍通過擴充或者配置來改變或者增加一些功能。

換言之,TP架構中Behavior實作了AOP(面向切面)程式設計,即綁定标簽,利用Hook函數設定觸發點。

tp提供了諸如'app_init'(應用初始化标簽位),'path_info'(path_info檢測标簽位),'app_began'(應用開始标簽位),'app_end'(應用結束标簽位)等内置标簽位。

行為拓展添加過程

  • 建立Behavior類

可以直接放在Think\Behaviors中,也可以放在應用目錄中(Application\Common\Behavior),建立檔案,命名格式為 标簽名+Behavior.class.PHP 。要注意類中必須含有run方法,預設run方法為入口方法。

代碼内容

namespace Common\Behavior;

use Think\Behavior;

class TolldetectBehavior extends Behavior
{
    //方法名必須為run,作為入口檔案
    public function run(&$param){
        echo "Hello ";
    }
}
           
  • 注冊标簽(挂載)

    ThinkPHP中的标簽注冊方法有兩種,一種是手動注冊,一種是自動注冊。

下面為手動注冊方法add()的源碼

/**
     * 動态添加插件到某個标簽
     * @param string $tag 标簽名稱
     * @param mixed $name 插件名稱
     * @return void
     */
    static public function add($tag,$name) {
        if(!isset(self::$tags[$tag])){
            self::$tags[$tag]   =   array();
        }
        if(is_array($name)){
            self::$tags[$tag]   =   array_merge(self::$tags[$tag],$name);
        }else{
            self::$tags[$tag][] =   $name;
        }
    }
           

我們在調用時用Hook::add($tags,$name)就可以綁定。注意tags為要綁定的标簽名,$name為具體的behavior行為檔案。

如果使用自動注冊,則需要在Common目錄下建立tags.php檔案。其中可以直接通過傳回數組的方法進行批量綁定,TP在運作中會自動加載這個配置并進行綁定。例如:

<?php 
return array(
    "hellow" => array('Home\\Behaviors\\TolldetectBehavior')
);
 ?>
           

以上代碼就完成了'hellow'标簽與我上面定義的事件的自動注冊。

當我們手動或自動完成了行為拓展的綁定,就可以設定事件的觸發點了。

觸發鈎子則會執行run方法。