如何使 WordPress 插件可擴展

已發表: 2022-03-10
快速總結↬就在您認為自己終於找到了一個可以滿足您所有需求的插件時,仍然有一件很重要的小事它做不到。 了解如何使您的插件可擴展並減少頭痛。

您是否曾經使用過插件並希望它做一些不同的事情? 也許您需要一些超出插件設置頁面範圍的獨特東西。

我個人遇到過這種情況,我打賭你也遇到過。 如果您是 WordPress 插件開發人員,很可能您的一些用戶在使用您的插件時也遇到過這種情況。

這是一個典型的場景:你終於找到了能滿足你所有需求的插件——除了一件小事。 沒有啟用那個小東西的設置或選項,所以您瀏覽文檔並發現您無能為力。 您在 WordPress 插件的支持論壇中請求該功能 - 但沒有骰子。 最後,您將其卸載並繼續搜索。

想像一下,如果你是這個插件的開發者。 如果用戶要求某些特定功能,您會怎麼做?

理想的做法是實施它。 但是,如果該功能用於非常特殊的用例,那麼添加它是不切實際的。 擁有一個只有 0.1% 的用戶會使用的插件設置並不好。

您只想實現影響大多數用戶的功能。 實際上,80% 的用戶使用 20% 的功能(80/20 規則)。 因此,在實施之前,請確保任何新功能都受到強烈要求,並且 80%​​ 的用戶會從中受益。 如果您為請求的每個功能都創建了一個設置,那麼您的插件就會變得複雜和臃腫——沒有人想要這樣。

最好的辦法是使插件可擴展,代碼明智,以便其他人可以根據自己的需要增強或修改它。

在本文中,您將了解為什麼讓您的插件可擴展是一個好主意。 我還將分享一些關於我如何學會做到這一點的技巧。

跳躍後更多! 繼續往下看↓

是什麼讓插件可擴展?

簡而言之,可擴展插件意味著它遵循面向對象編程的 SOLID 原則的“O”部分——即開放/封閉原則。

如果您不熟悉開放/封閉原則,這基本上意味著其他人不應該為了修改某些內容而編輯您的代碼

將此原則應用於 WordPress 插件,這意味著如果插件中包含允許其他人修改其行為的規定,則該插件是可擴展的。 就像 WordPress 允許人們“掛鉤”到 WordPress 的不同區域一樣,但在插件級別。

插件的典型示例

讓我們看看如何創建一個可擴展的插件,從一個不能擴展的示例插件開始。

假設我們有一個插件,它生成一個側邊欄小部件,顯示三個最新帖子的標題。 該插件的核心是一個簡單地將這三個帖子的標題包裝在列表標籤中的函數:

 function get_some_post_titles() { $args = array( 'posts_per_page' => 3, ); $posts = get_posts( $args ); $output = '
    '; foreach ( $posts 作為 $post ) { $輸出 .= '
  • ' . $post->post_title 。 '
  • '; } $輸出 .= '
'; 返回$輸出; }

雖然這段代碼可以工作並完成工作,但它的可擴展性並不好。

為什麼? 因為函數是以自己的方式設置的,所以如果不直接修改代碼,就無法改變它的行為。

如果用戶想要顯示三個以上的帖子,或者可能包含帶有帖子標題的鏈接怎麼辦? 上面的代碼沒有辦法做到這一點。 用戶被插件的工作方式所困擾,無法改變它。

包括一百個設置不是答案

有多種方法可以增強上述插件以允許用戶對其進行自定義。

一種這樣的方法是在設置中添加很多選項,但即使這樣也可能無法滿足用戶希望從插件中獲得的所有可能性。

如果用戶想要執行以下任何操作(我們稍後會重新討論的場景)怎麼辦:

  • 顯示特定類別的 WooCommerce 產品或帖子;
  • 在另一個插件提供的輪播中顯示項目,而不是簡單的列表;
  • 執行自定義數據庫查詢,然後在列表中使用這些查詢的帖子。

如果我們向我們的小部件添加一百個設置,那麼我們將能夠涵蓋上述用例。 但是,如果其中一種情況發生了變化,現在用戶只想顯示當前有貨的 WooCommerce 產品怎麼辦? 小部件需要更多設置來適應這一點。 很快,我們就會有大量的設置。

此外,具有大量設置列表的插件並不完全是用戶友好的。 如果可能,請避開這條路線。

那麼,我們將如何解決這個問題呢? 我們會讓插件可擴展。

添加我們自己的鉤子以使其可擴展

通過研究上面的插件代碼,我們看到 main 函數執行的一些操作:

  • 它使用get_posts獲取帖子。
  • 它生成一個帖子標題列表。
  • 它返回生成的列表。

如果其他人要修改這個插件的行為,他們的工作很可能會涉及這三個操作。 為了使我們的插件可擴展,我們必須在這些周圍添加鉤子,以便為其他開發人員打開它們。

一般來說,這些是為插件添加鉤子的好地方:

  • 在主要流程周圍和內部,
  • 在構建輸出 HTML 時,
  • 用於更改帖子或數據庫查詢,
  • 在從函數返回值之前。

可擴展插件的典型示例

根據這些經驗法則,我們可以添加以下過濾器以使我們的插件可擴展:

  • 添加myplugin_get_posts_args用於修改get_posts的參數,
  • 添加myplugin_get_posts以覆蓋get_posts的結果,
  • 添加myplugin_list_item用於自定義列表條目的生成,
  • 添加myplugin_get_some_post_titles以覆蓋返回的生成列表。

這是添加了所有鉤子的代碼:

 function get_some_post_titles() { $args = array( 'posts_per_page' => 3, ); // Let other people modify the arguments. $posts = get_posts( apply_filters( 'myplugin_get_posts_args', $args ) ); // Let other people modify the post array, which will be used for display. $posts = apply_filters( 'myplugin_get_posts', $posts, $args ); $output = '
    '; foreach ( $posts 作為 $post ) { // 讓其他人修改列表條目。 $輸出 .= '
  • ' . apply_filters('myplugin_list_item', $post->post_title, $post) 。 '
  • '; } $輸出 .= '
'; // 讓其他人修改我們的輸出列表。 返回 apply_filters('myplugin_get_some_post_titles', $output, $args); }

您還可以在 GitHub 存檔中獲取上述代碼。

我在這裡添加了很多鉤子,這可能看起來不切實際,因為示例代碼非常簡單和小,但它說明了我的觀點:通過僅添加四個鉤子,其他開發人員現在可以以各種方式自定義插件的行為。

Hooks 的命名空間和上下文

在繼續之前,請注意關於我們已實現的鉤子的兩個重要事項:

  • 我們使用myplugin_為鉤子命名空間。
    這確保了鉤子的名稱不會與其他插件的鉤子衝突。 這只是一個好習慣,因為如果調用另一個具有相同名稱的鉤子,它可能會導致不需要的效果。
  • 我們還在上下文的所有鉤子中傳遞了對$args的引用。
    我這樣做是為瞭如果其他人使用此過濾器來更改代碼流中的某些內容,他們可以使用該$args參數作為參考來了解調用掛鉤的原因,以便他們可以相應地執行調整。

我們的鉤子的效果

還記得我之前談到的獨特場景嗎? 讓我們重新審視這些,看看我們的鉤子如何使它們成為可能:

  • 如果用戶想要顯示來自特定類別的 WooCommerce 產品或帖子,那麼他們可以使用過濾器myplugin_get_posts_args在插件查詢帖子時添加自己的參數,或者他們可以使用myplugin_get_posts用自己的列表完全覆蓋帖子。
  • 如果用戶想在另一個插件提供的輪播中顯示項目,而不是作為一個簡單的列表,那麼他們可以使用myplugin_get_some_post_titles覆蓋該函數的整個輸出,而是從那裡輸出一個輪播。
  • 如果用戶想要執行自定義數據庫查詢,然後在列表中使用該查詢的帖子,那麼,類似於第一個場景,他們可以使用myplugin_get_posts來使用自己的數據庫查詢並更改帖子數組。

好多了!

如何使用我們的過濾器的快速示例

開發人員可以使用add_filter掛鉤到我們上面的過濾器(或使用add_action進行操作)。

以我們上面的第一個場景為例,開發人員可以使用我們創建的myplugin_get_posts_args過濾器執行以下操作來顯示 WooCommerce 產品:

 add_filter( 'myplugin_get_posts_args', 'show_only_woocommerce_products' ); function show_only_woocommerce_products( $args ) { $args['post_type'] = 'product'; return $args; }

我們也可以使用動作掛鉤

除了使用apply_filters之外,我們還可以使用do_action使我們的代碼可擴展。 兩者的區別在於前者允許其他人更改變量,而後者允許其他人在我們代碼的各個部分執行附加功能。

使用動作時,我們實質上是向其他開發人員公開插件的流程,並讓他們一起執行其他操作。

它在我們的示例中可能沒有用(因為我們只顯示一個短代碼),但它在其他示例中會有所幫助。 例如,給定一個可擴展的備份插件,我們可以創建一個插件,該插件還將備份文件上傳到第三方服務,如 Dropbox。

“偉大的! 但我為什麼要關心讓我的插件可擴展呢?”

好吧,如果你仍然不相信這個想法,這裡有一些關於為什麼允許其他人修改你的插件行為是一個好主意的想法。

它為插件打開了更多自定義的可能性

每個人都有不同的需求。 而且你的插件很有可能不能滿足所有這些,你也不能預料到它們。 打開插件以允許修改插件行為的關鍵區域可以創造奇蹟。

它允許人們在不接觸插件代碼的情況下進行修改

其他開發人員不會被迫直接更改您的插件文件。 這是一個巨大的好處,因為直接修改插件的文件通常是不好的做法。 如果插件得到更新,那麼您的所有修改都將被擦除。

如果我們添加自己的鉤子供其他人使用,那麼插件的修改可以放在外部位置 - 比如說,在另一個插件中。 這樣一來,原插件完全不會被觸動,並且可以在不破壞任何東西的情況下自由更新,並且其他插件中的所有修改都將保持不變。

結論

可擴展插件真的很棒,為我們提供了很多定制可能性的空間。 如果您使您的插件可擴展,您的用戶和其他開發人員會因此而愛上您。

看看 WooCommerce、Easy Digital Downloads 和 ACF 等插件。 這些插件是可擴展的,你可以很容易地分辨出來,因為 WordPress 插件目錄中的許多其他插件都向它們添加了功能。 它們還提供了廣泛的動作和過濾器鉤子來修改插件的各個方面。 我在上面列舉的經驗法則已經出現在我對它們的研究中。

以下是使您的插件可擴展的一些要點:

  • 遵循開閉原則。 其他人不應該為了修改某些內容而編輯您的代碼。
  • 要使您的插件可擴展,請在以下位置添加掛鉤:

    • 在主要流程周圍和內部,
    • 在構建輸出 HTML 時,
    • 用於更改帖子或數據庫查詢,
    • 在從函數返回值之前。

  • 使用插件名稱命名您的鉤子名稱,以防止命名衝突。
  • 嘗試傳遞與鉤子相關的其他變量,以便其他人了解鉤子中發生的情況。
  • 不要忘記記錄插件的鉤子,以便其他人可以了解它們。

延伸閱讀

如果您想了解更多關於擴展插件的信息,這裡有一些資源:

  • 如何使您的 WordPress 插件可擴展,GitHub
    本文中的所有示例代碼。
  • “開始使用 WordPress Hooks 的有用技巧”,Thomas Maier,Smashing Magazine
  • “如何創建 WordPress 插件”,Smashing Magazine 的 Daniel Pataki
  • “Hooks”,插件手冊,WordPress.org