ホームページ php教程 php手册 PHP面向切面编程组件

PHP面向切面编程组件

Jun 13, 2016 am 10:46 AM
cakephp mvc php yii 世代 使用 理由 私たち フレーム コンポーネント プログラミング のために

我们使用MVC框架,例如CI、YII、cakePHP,原因之一就是:能够使代码便于维护。

但当业务逻辑不断复杂时,在控制器中调用模型中的方法会越来越臃肿。

面向切面编程的思路,是解决不断变化的业务逻辑与写出便于维护代码的解决方法之一。

 


下面是向切面式组件源码,是根据AOP的思路设计的。

 

 

if (function_exists('__autoload')) { 
    trigger_error("Extension: It looks like your code is using an __autoload() function. Extension uses spl_autoload_register() which will bypass your __autoload() function and may break autoloading.", E_USER_WARNING); 

 
spl_autoload_register(array('ExtensionFactory', 'autoload')); 
 
class ExtensionFactory { 
     
    private static $extFamily = null; 
    private static $_classes = array( 
        'Extension' =>  '/Extension.php', 
        'ExtensionFamily' =>  '/ExtensionFamily.php' 
    ); 
     
    /**
     * Class autoloader. This method is provided to be invoked within an 
     * __autoload() magic method.
     * @param string $className The name of the class to load.
     */ 
    public static function autoload() { 
        foreach(self::$_classes as $v){ 
            require_once dirname(__FILE__) . $v; 
        } 
    } 
     
    /**
     * 必须先调用此方法来实例化扩展族,才能调用addExtension\removeExtension等
     * @return ExtensionFamily
     */ 
    public static function createExtension(){ 
        self::$extFamily = new ExtensionFamily(); 
        return self::$extFamily; 
    } 
     
    public static function removeExtension($extName){ 
        if(is_null(self::$extFamily)){ 
            throw new Exception("Please createExtension first"); 
            return false; 
        }else{ 
            unset(self::$extFamily->_extensionArray[$extName]); 
        } 
    } 
     
    public static function addExtension($extName, Extension $ext){ 
        if(is_null(self::$extFamily)){ 
            throw new Exception("Please createExtension first"); 
            return false; 
        }else{ 
            self::$extFamily->_extensionArray[$extName] = $ext; 
        } 
    } 
     
    public static function removeAllExtension(){ 
        if(is_null(self::$extFamily)){ 
            throw new Exception("Please createExtension first"); 
            return false; 
        }else{ 
            foreach(self::$extFamily->_extensionArray as $extName=>$ext){ 
                unset(self::$extFamily->_extensionArray[$extName]); 
            } 
        } 
    } 

if (function_exists('__autoload')) {
 trigger_error("Extension: It looks like your code is using an __autoload() function. Extension uses spl_autoload_register() which will bypass your __autoload() function and may break autoloading.", E_USER_WARNING);
}

spl_autoload_register(array('ExtensionFactory', 'autoload'));

class ExtensionFactory {
   
    private static $extFamily = null;
    private static $_classes = array(
        'Extension' =>  '/Extension.php',
        'ExtensionFamily' =>  '/ExtensionFamily.php'
    );
   
    /**
     * Class autoloader. This method is provided to be invoked within an
     * __autoload() magic method.
     * @param string $className The name of the class to load.
     */
    public static function autoload() {
        foreach(self::$_classes as $v){
            require_once dirname(__FILE__) . $v;
        }
    }
   
    /**
     * 必须先调用此方法来实例化扩展族,才能调用addExtension\removeExtension等
     * @return ExtensionFamily
     */
    public static function createExtension(){
        self::$extFamily = new ExtensionFamily();
        return self::$extFamily;
    }
   
    public static function removeExtension($extName){
        if(is_null(self::$extFamily)){
            throw new Exception("Please createExtension first");
            return false;
        }else{
            unset(self::$extFamily->_extensionArray[$extName]);
        }
    }
   
    public static function addExtension($extName, Extension $ext){
        if(is_null(self::$extFamily)){
            throw new Exception("Please createExtension first");
            return false;
        }else{
            self::$extFamily->_extensionArray[$extName] = $ext;
        }
    }
   
    public static function removeAllExtension(){
        if(is_null(self::$extFamily)){
            throw new Exception("Please createExtension first");
            return false;
        }else{
            foreach(self::$extFamily->_extensionArray as $extName=>$ext){
                unset(self::$extFamily->_extensionArray[$extName]);
            }
        }
    }
}

 


/**
 * 扩展家族
 *
 * @author Mr.Jin
 */ 
class ExtensionFamily implements Extension{ 
    public $_extensionArray = array(); 
     
    /**
     *
     * @param type $extName 扩展名
     * @param Extension $ext 实现Extension的对象
     */ 
    public function addExtension($extName, Extension $ext){ 
        $this->_extensionArray[$extName] = $ext; 
    } 
     
    public function beforeAppend(&$params){ 
        foreach($this->_extensionArray as $ext){ 
            $ext->beforeAppend($params); 
        } 
    } 
     
    public function afterAppend(&$params) { 
        foreach($this->_extensionArray as $ext){ 
            $ext->afterAppend($params); 
        } 
    } 

 
?> 
/**
 * 扩展家族
 *
 * @author Mr.Jin
 */
class ExtensionFamily implements Extension{
    public $_extensionArray = array();
   
    /**
     *
     * @param type $extName 扩展名
     * @param Extension $ext 实现Extension的对象
     */
    public function addExtension($extName, Extension $ext){
        $this->_extensionArray[$extName] = $ext;
    }
   
    public function beforeAppend(&$params){
        foreach($this->_extensionArray as $ext){
            $ext->beforeAppend($params);
        }
    }
   
    public function afterAppend(&$params) {
        foreach($this->_extensionArray as $ext){
            $ext->afterAppend($params);
        }
    }
}

?>

/**
 * 扩展接口
 *
 * @author Mr.Jin
 */ 
interface Extension { 
    public function beforeAppend(&$params); 
     
    public function afterAppend(&$params); 

 
?> 
/**
 * 扩展接口
 *
 * @author Mr.Jin
 */
interface Extension {
    public function beforeAppend(&$params);
   
    public function afterAppend(&$params);
}

?>

以上三个文件实现了简单的AOP组件。

 

下面是Demo:

/**
 * 自定义Extension
 * 用户积分Extension
 * 根据用户是否登录,决定此次消费是否记录用户积分
 *
 * @author Mr.Jin
 */ 
class ExampleExtension implements Extension { 
    public $check=false; 
     
    public function beforeAppend(&$isLogin) { 
        if($isLogin){ 
            $this->check = true; 
        } 
    } 
     
    public function afterAppend(&$pointer) { 
        if($this->check){ 
            //add pointer  
        }else{ 
            echo '未登录用户,积分不录入'; 
            return; 
        } 
    } 
 

 
?> 
/**
 * 自定义Extension
 * 用户积分Extension
 * 根据用户是否登录,决定此次消费是否记录用户积分
 *
 * @author Mr.Jin
 */
class ExampleExtension implements Extension {
 public $check=false;
   
    public function beforeAppend(&$isLogin) {
        if($isLogin){
         $this->check = true;
        }
    }
   
    public function afterAppend(&$pointer) {
        if($this->check){
         //add pointer
        }else{
         echo '未登录用户,积分不录入';
         return;
        }
    }

}

?>

 


demo.php
require_once('ExtensionFactory.php');//导入组件本身  
 
require_once('ExampleExtension.php');//导入扩展  
 
$ext = ExtensionFactory::createExtension(); 
 
ExtensionFactory::addExtension('example', new ExampleExtension());//积分录入功能  
 
/*
 * 按照需求的变化,可以增加相应的Extension.
 * eg.
 * 新需求:新增会员类型,根据不同类型,进行价格优惠。
 * 实现思路:
 * 一、建立卡号类型工厂
 * 二、建立SeniorMemberExtension、PuTongMeberExtension.
 * 三、工厂方法根据会员类型addExtension
 */ 
 
$isLogin = false; //假设用户未登录  
 
$ext->beforeAppend($isLogin); 
 
 
/**
 * 面向切面编程,最重要一点是:必须先分析出整个业务处理中,哪个才是重点。
 * 这里的重点是订单的入库。
 * 在订单入库之前可能业务逻辑不断增加,例如:登录验证、卡上余额验证等
 * 在订单入库之后:积分处理、订单监控等
 */ 
echo "此处是主要业务逻辑:订单入库\r\n"; 
 
$pointer = 100; 
 
$ext->afterAppend($pointer); 
require_once('ExtensionFactory.php');//导入组件本身

require_once('ExampleExtension.php');//导入扩展

$ext = ExtensionFactory::createExtension();

ExtensionFactory::addExtension('example', new ExampleExtension());//积分录入功能

/*
 * 按照需求的变化,可以增加相应的Extension.
 * eg.
 * 新需求:新增会员类型,根据不同类型,进行价格优惠。
 * 实现思路:
 * 一、建立卡号类型工厂
 * 二、建立SeniorMemberExtension、PuTongMeberExtension.
 * 三、工厂方法根据会员类型addExtension
 */

$isLogin = false; //假设用户未登录

$ext->beforeAppend($isLogin);


/**
 * 面向切面编程,最重要一点是:必须先分析出整个业务处理中,哪个才是重点。
 * 这里的重点是订单的入库。
 * 在订单入库之前可能业务逻辑不断增加,例如:登录验证、卡上余额验证等
 * 在订单入库之后:积分处理、订单监控等
 */
echo "此处是主要业务逻辑:订单入库\r\n";

$pointer = 100;

$ext->afterAppend($pointer);
运行结果:
此处是主要业务逻辑:订单入库
未登录用户,积分不录入

 摘自 God's blog

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

PHPでHTML/XMLを解析および処理するにはどうすればよいですか?

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

母音を文字列にカウントするPHPプログラム

コーディングの鍵: 初心者のための Python の力を解き放つ コーディングの鍵: 初心者のための Python の力を解き放つ Oct 11, 2024 pm 12:17 PM

コーディングの鍵: 初心者のための Python の力を解き放つ

Java をシンプルに: プログラミング能力を高める初心者向けガイド Java をシンプルに: プログラミング能力を高める初心者向けガイド Oct 11, 2024 pm 06:30 PM

Java をシンプルに: プログラミング能力を高める初心者向けガイド

未来を創る: まったくの初心者のための Java プログラミング 未来を創る: まったくの初心者のための Java プログラミング Oct 13, 2024 pm 01:32 PM

未来を創る: まったくの初心者のための Java プログラミング

Python による問題解決: 初心者プログラマーとして強力なソリューションをアンロックする Python による問題解決: 初心者プログラマーとして強力なソリューションをアンロックする Oct 11, 2024 pm 08:58 PM

Python による問題解決: 初心者プログラマーとして強力なソリューションをアンロックする

See all articles