簡體   English   中英

PHP / OOP-使用父類運行子函數

[英]PHP/OOP - Using parent class to run child functions

我正在尋找一種可以將單個子類擴展為多個子類的方法,一次只能選擇其中一個子類。 一個非常基本的例子:

class API_Base {

    public $context;

    public function __construct() {
        $this->init()
    }
}

class Mailchimp_API extends API_Base {

    public function init() {
        $this->context = 'mailchimp';
        $this->enabled = false; 
    }

    public function add_contact($email_address) {
        // mailchimp API for adding contact
    }
}

class Infusionsoft_API extends API_Base {

    public function init() {
        $this->context = 'infusionsoft';
        $this->enabled = true;
    }

    public function add_contact($email_address) {
        // infusionsoft API for adding contact
    }

}

每個孩子都會初始化自己並注冊為選項供用戶選擇。 用戶選擇了要使用的集成后,它將保存到數據庫中。 我希望以后訪問API_Base類似於:

$api = new API_Base();
$api->context; // should be "infusionsoft"
$api->add_contact($email_address);

因此,運行$api->add_contact() ,它僅運行add_contact()函數以進行活動的API集成。

最終我想以某種方式使用get_class_methods(); 返回僅活動API的功能,因此訪問API的功能可以知道可能的情況(即某些API支持電子郵件列表,而其他API不支持,或支持創建自定義字段等)。

我通過調用parent::set_context($context);獲得了一些成功parent::set_context($context); 從啟用的類中,但我仍然不知道如何讓父級僅執行“已啟用”子類中的方法。

繼承不是這樣工作的。 子子類從其父類繼承。

為了解決您的問題,您可以向API_Base添加一個工廠方法,該方法將通過其類型創建API實現:

class API_Base {
    public static function createByType($type)
    {
        switch ($type) {
            case 'mailchimp': return new Mailchimp_API();
            case 'infusionsoft': return new Infusionsoft_API();
            default: throw new \InvalidArgumentException(spintf('Invalid API type "%s"', $type));
        } 
    }
    // other methods
}

並像這樣使用它:

$api = API_Base::createByType($user->selectedApi);
$api->context; // should be "infusionsoft"
$api->add_contact($email_address);

您可以考慮抽象類實現。 抽象類的作用是,擴展抽象類的人可以執行它擁有的方法。

abstract class Something{
       function __construct(){
        // some stuff
       }

       function my_func(){
         $this->myTest ;
       }

      abstract function my_func(); 

      }

    class Some extends Something{

      function __construct(){
        parent::__construct() ;
      }

      function my_test(){
           echo "Voila" ;
      }

    }

多虧了Ihor的建議,我的工作方式對我來說非常完美。 我最終要做的是:

在主插件文件中,有一個可過濾的功能,其他開發人員可以在需要時添加新的集成。 第一個參數是slug(對於我的自動裝帶器),第二個參數是類名。

public function get_apis() {

    return apply_filters( 'custom_apis', array(
        'infusionsoft-isdk'         => 'MYPLUGIN_Infusionsoft_iSDK',
        'infusionsoft-oauth'        => 'MYPLUGIN_Infusionsoft_oAuth',
        'activecampaign'            => 'MYPLUGIN_ActiveCampaign'
    ) );

}

每個集成都包含段和類名。 然后在我的API_Base類中,我在構造函數中有這個:

class API_Base {

    public $available_apis = array();

    public $api;

    public function __construct() {

        $configured_apis = main_plugin()->get_apis();

        foreach( $configured_apis as $slug => $classname ) {

            if(class_exists($classname)) {

                $api = new $classname();
                $api->init();

                if($api->active == true)
                    $this->api = $api;

                $this->available_apis[$slug] = array( 'name' => $api->name );

                if(isset($api->menu_name)) {
                    $this->available_apis[$slug]['menu_name'] = $api->menu_name;
                } else {
                    $this->available_apis[$slug]['menu_name'] = $api->name;
                }

            }

        }

    }
}

然后,在我的主文件中,運行所有包含項:

self::$instance->api_base       = new API_Base();
self::$instance->api            = self::$instance->api_base->api;

現在我可以叫self::$instance->api->add_contact($email); 它將觸發當前活動的API中的任何一個。

這似乎是最好的方法,因為這樣一來,插件加載時我只能旋轉一次API,而不必每次使用時都必須創建一個新實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM