問題描述

當開發一個插件應該將這些功能分組到一個類中以避免命名空間衝突?

使用類創建 PHP 的性能開銷?

如果有性能打擊,應該是功能名稱只是 pre-fixed 而不是?

最佳解決方案

When developing a plugin should the functions be grouped together into a Class to avoid namespace conflicts?

是的,但這只是一個小小的論據。 In-fact 不是 OOAD 中的一個類的”true” 性質。

Does using classes create performance overheads for PHP?

不,不是特別。糟糕的設計和/或壞的書寫代碼或 pre-mature 優化比實際的語言功能創造出更多的性能問題。

If there is a performance hit, should function names just be pre-fixed instead?

如書面所述,沒有表現打擊。糟糕的書面代碼將會更好的表現出色,而不是強制您做壞事的良好代碼。


底線:

您可以對插件進行不同的使用。您可以使用它們具有某種命名空間,並將其用於全局函數”just” 。最直接的形式是靜態類函數,下面的 code-example 顯示了第一個全局函數,然後是全局靜態類函數:

/* global function */
function myplug_hook()
{
}

add_filter('the_hook', 'myplug_hook');


/* global static function */
class myplug
{
    public static function hook()
    {
    }
}

add_filter('the_hook', 'myplug::hook');

這只是一個示例,顯示您需要為單個鈎子鍵入更多。另外,它顯示了命名空間的工作原理:您可以更容易地替換單個類名稱來重命名所有靜態函數,然後搜索並替換 myplug::,因為 myplug_可能因為錯誤的肯定而更難。但最終沒有什麼區別。

關鍵是:靜態類函數 Docs 不是真的很多,然後是全局 functionsDocs 。

這個例子也是如此:命名空間很好,但是使用 worpdress,命名空間停止使用鈎子:回調函數是硬編碼的,因此使用類的命名空間的好處 (base-name 的一個位置,類名) 不會有幫助你的代碼與 wordpress 的鈎子名稱進行幹預。

真正的好處是使用實際的類實例和 non-static 函數。這有利於您開始使用 OO 原則,您可以簡化代碼。靜態類函數比一個解決方案更為問題。

那麼它不僅僅是語法糖。

要點是:做一些有助於您編寫可以輕鬆處理和維護的代碼的東西。不要 over-rate 的表現,這是一個常見的錯誤。更重要的是你編寫的代碼很容易閲讀和理解,只是做你所需要的。也許這個問題和答案在這個上下文中有更大的幫助:多個自定義的 Metabox 幫助。

一個常見的方法我甚至使用較小的插件是使用靜態幫助函數實例化插件,其餘的駐留在插件實例中。這有助於封裝主要的插件邏輯,它可以從命名空間中獲益,而私有成員也可以使用不符合標準全局功能的鈎子之間的 re-used 。以下 code-example 顯示模式:

<?php
/** Plugin Headers ... */

return MyPlugin::bootstrap(); 

class MyPlugin
{
    /** @var MyPlugin */
    static $instance;
    static public function bootstrap() {
        if (NULL === self::$instance) {
            self::$instance = new __CLASS__;
        }
        return self::$instance;
    }
    # ...
}

這是我用於基本插件文件的常見模式。插件類一方面表示 Wordpress 的插件,另一方面它允許開始為自己的代碼使用面向對象的範例,甚至可以完全面向對象 (但不需要) 。它是一個控制器,與整個 wordpress API 接口作為請求。

如示例所示,將創建一個插件的實例。這樣可以使用像構造函數文檔 (__construct) 這樣的已知的常量來初始化實際的插件:

# ...
class MyPlugin
{
    # ...
    public function __construct()
    {
        add_filter('the_hook', array($this, 'hook'));
    }

    public function hook()
    {
    }
    # ...
}

當鈎子被註冊時,這個插件對象已經受益於它的設計:你已經停止了 hard-code 的具體插件類名的實際鈎子功能。這是可能的,因為該類與回調的對象實例綁定。聽起來很複雜,只是説:$this 是插件。可以在鈎子回調中使用,比較註冊類方法作為鈎子回調。

這種模式允許與 wordpress 更容易的接口:注入被減少到鈎子的名稱以及它們提供的數據。然後,您可以開始直接實現這個插件類,或者重構對它的實現,所以只能將代碼放入插件類,這是最小限度,以定義你的插件與 wordpress 的接口,但保持一般的邏輯除了 worpdress 。這是樂趣開始的地方,最有可能是每個插件作者想要從長遠來看。

所以不要用 worpdress 編程,而是反對它。由於 worpdress 是相當靈活的,沒有通用或容易描述程序的接口。一個基本的插件類可以承擔起這個角色,使您可以為自己的代碼提供更多的靈活性,這將導致更容易的代碼和更好的性能。

因此,對於 name-spacing 來説,不僅僅是一個好處。我可以給的最佳建議是:嘗試自己。沒有多少你會鬆動,只有新的東西要發現。

在您保持插件兼容性的同時,您通過了更多主要的 WordPress 更新之後,您可能會注意到差異。

注意事項:如果您的插件直接與 wordpress 集成以完成工作,則使用一個或兩個公共功能可能更適合您。為工作採取正確的工具。

次佳解決方案

類 VS 函數集


Performance

一般:Afaik,”performance” 在類和函數集之間沒有區別。

詳情:

  • 如果您對 function_exists()class_exists()提出質疑,那麼通常您會得到很多功能 (wp core 中的〜 1.800(?)) 與類 (〜 100(?) 在 wp core 中) 有很大差異。所以製作的東西”pluggable”,因此質疑存在是執行時間的不同。
  • 類比函數集提供了一個很大的優勢:你可以更容易地避免在不需要它的請求上調用它,然後使用函數。您只需要對類進行條件檢查,而不是為每個函數執行條件檢查。所以如果你不需要它在每一個頁面加載,並可以避免調用大量的 if / else 語句,功能”performs better” 。

建築 – 工作原理:

函數集:通常,函數在你調用的行中被執行。所以每次你打電話的東西,你必須再寫一次,如果你不得不多説一次。

類:類有不同的褻瀆。最接近函數集的類是”factory” 類 (wikipedia / google) 。 Imo 它幾乎與一組函數相同,但封裝在一個類中。但也有其他”types” 的類。你可以這樣寫一個抽象的或者一個父類的類,你可以用一個子類來擴展它。在一個現實世界的例子中:假設你有一個類來建立一些靜態文本字段。在您的__construct()功能中,您有一組場景,如”left_column”,”right_column”& “footer_field” 。然後你調用類似 $text_field = new TextFieldClass(); 來實例化類。之後你只需調用 $text_field->add( $case => 'left_column', 'case' => 'foo text' );$text_field->add( $case => 'footer_field', 'case' => 'bar text' ); 。然後,當您實例化類時,只有當您構建文本字段時才會調用兩個類函數,那麼所有的條件都已經被執行了。在這個 szenario 中,你可以節省一些 ms 的執行時間。


個人想法

如果你明智地寫下你的課,那麼你的表現會有一個小的優勢。但是,您將有一個組織良好的結構來工作。到目前為止沒有什麼壯觀。但是,如果您考慮以下”split” 用於插件中的類和函數的用例,那麼您將得到我的最後一點:類是內部的,函數是 API 。只要您通過公共可用功能 (即調用類或類函數) 提供 API,那麼您將進一步開發您的插件。您可以自由地改變內部結構,甚至改變插件的可能性,而無需隨時隨地影響用户。

例:

// construction of object
if ( ! class_exists( 'WPSE_HelloWorld' ) )
{

class WPSE_HelloWorld
{
    function __construct( $args = array( 'text', 'html', 'echo' ) )
    {
        // call your object building procedures here
        $this->hello_world( 'text', 'html', 'echo' );
    }

    function hello_world( 'text', 'html', 'echo' )
    {
        $start_el = '<{$html}>';
        $end_el = '</{$html}>';
        if ( $echo )
        {
            return print "{$start_el}{$some}{$end_el}";
        }

        return "{$start_el}{$some}{$end_el}";
    }
} // END Class 

}

// API: public functions
function the_hello_world( $args( 'echo' => true ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

function get_hello_world( array( $args( 'echo' => false) ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

// then you can call it like get_the_title() or the_title(), which you know from the WP API:
// 'echo' is set to false per default:
$some_var = get_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *returns* "<strong>hello reader</strong>"

// 'echo' is set to true per default:
the_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *prints/echos* "<strong>hello reader</strong>"

注意:請同時閲讀在評論中發佈的鏈接 @ t310s 。

第三種解決方案

這是插件作者的一種純粹的風格選擇。速度沒有真正的區別。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。