プラグイン開発の客観的なベストプラクティス?[閉まっている]
-
16-10-2019 - |
質問
情報を収集するためにコミュニティ Wiki を立ち上げる 客観的 プラグイン開発のベストプラクティス。この質問のきっかけとなったのは、 wp-hackers に関する @EAMann のコメント.
その目的は、客観的なベスト プラクティスがどのようなものであるかについて協力し、最終的にはコミュニティのコラボレーション レビュー プロセスでそれらを使用できるようにすることです。
アップデート: 最初のいくつかの回答を見た後、回答ごとに必要なアイデア/提案/ベスト プラクティスは 1 つだけであることが明らかになり、投稿する前にリストを確認して重複がないことを確認する必要があります。
解決
アクションとフィルターを使用する
人々が何らかのデータを追加または変更したいと考えている場合は、次のようにします。 提供する apply_filters() 戻る前に.
追伸私が少し残念に思ったことの1つは、あなたの質問が答えているのは、エンドユーザー向けにのみ設計されたプラグインの割合です。独自のフックがありません。WordPress がほとんどのプラグインと同じように設計されていたら想像してみてください。それは柔軟性が低く、非常にニッチなソリューションになります。
おそらく、WordPress に他のプラグインが依存するプラグインを自動インストールする機能があれば、状況は変わってくるのではないでしょうか?現状では、クライアントは特定の方法で物事を望んでおり、利用可能なプラグインは 90% あるものの、残りの 10% を柔軟に更新できないため、通常、必要な機能の多くを最初から作成する必要があります。
WordPress コミュニティをリードする人たちには、StackExchange サイトで良い回答が報われるのと同じように、ベスト プラクティス (他の開発者用のフックを追加するなど) に従うプラグインにも確実に報われる方法を見つけてほしいと願っています。
から例を挙げてみましょう 別の質問:
例:誰かが記事をリツイートしたときにプラグインで何かをしたいと考えています。人気のリツイート プラグインにフックして起動できるカスタム フックがあれば、それは素晴らしいことでしょう。存在しないので、プラグインを変更してそれを含めることはできますが、それは私のコピーでのみ機能するため、それを再配布するつもりはありません。
関連している
他のヒント
スクリプト/CSSをロードします wp_enqueue_script
と wp_enqueue_style
プラグインは、JS / CSSファイルの重複バージョン、特にjQueryやWP Coreに含まれるその他のJSファイルのロード /試みを読み込んではいけません。
プラグインは常に使用する必要があります wp_enqueue_script
と wp_enqueue_style
JSおよびCSSファイルをリンクして直接介してリンクするとき <script>
タグ。
関連している
I18Nサポート
すべての出力文字列は、開発者が独自のプラグインを翻訳することに関心がない場合でも、利害関係者による国際化を可能にするために、適切なテキストドメインにリンクする必要があります。
中に言語ファイルをロードすることが非常に重要であることに注意してください init
アクションユーザーがアクションに接続できるように。
コーデックスを参照してください: WordPress開発者のI18N
また、この記事: WP言語のロードは正しくファイルをファイルします.
WordPress 4.6+以来
WP 4.6は負荷順序を変更し、チェックされた場所で、開発者とユーザーにとってはるかに簡単になりました。
TextDomain 'My-Plugin'を備えたプラグインを考慮すると、WordPressは最初に翻訳ファイルを次のように探します。
/wp-content/languages/plugins/my-plugin-en_us.mo
そこにあるものを見つけられない場合、プラグインが見た目を指示するものを探します(Codexに従う場合は、Pluignsの「言語」フォルダーの通常のフォルダーでは通常):
/wp-content/plugins/my-plugin/languages/my-plugin-en_us.mo
最後に、言語ファイルが見つからない場合、次のデフォルトの場所を確認します。
/wp-content/languages/my-plugin-en_us.mo
最初のチェックは4.6に追加され、開発者が言語ファイルを追加する場所を知る必要がある前に、ユーザーが言語ファイルを追加するための定義済みの場所を提供します。これは、ユーザーがプラグインのテキストドメインを知る必要があるだけです。/wp-content/languages/plugins/textdomain-local.mo
以下は古い方法です(WP 4.6+以降は関係ありません)
[...]
最後に、私はそれが重要であることを指摘したいと思います wp_lang_dirからのカスタムユーザー言語ファイルをロードする前に、プラグインを使用して出荷する言語ファイルをロードする前に. 。同じドメインに複数のMOファイルがロードされると、最初に見つかった翻訳が使用されます。このようにして、プラグインによって提供される言語ファイルは、ユーザーによって翻訳されていない文字列のフォールバックとして機能します。
public function load_plugin_textdomain()
{
$domain = 'my-plugin';
// The "plugin_locale" filter is also used in load_plugin_textdomain()
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
load_textdomain(
$domain,
WP_LANG_DIR . '/my-plugin/' . $domain . '-' . $locale . '.mo'
);
load_plugin_textdomain(
$domain,
FALSE,
dirname( plugin_basename(__FILE__) ) . '/languages/'
);
}
プラグインがwp_debugでエラーを生成しないようにします
常にプラグインをテストしてください WP_DEBUG
電源を入れ、理想的には開発プロセスを通してオンになります。プラグインはエラーをスローしてはいけません WP_DEBUG
の上。これには、非推奨通知と未チェックインデックスが含まれます。
デバッグをオンにするには、編集します wp-config.php
そのようにファイル WP_DEBUG
定数が設定されています true
. 。を参照してください デバッグのコーデックス 詳細については。
最初に、WordPress Coreで既存の機能を使用します
できれば: WordPress Coreに含まれる既存の関数を使用します 自分で書く代わりに。 WordPressコアに適切な既存の関数がない場合にのみ、カスタムPHP関数を開発します。
1つの利点は、使用できることです 「控除された通知を記録する」 交換する必要がある機能を簡単に監視する。もう1つの利点は、ユーザーがコーデックスで関数ドキュメントを表示し、経験豊富なPHP開発者でなくてもプラグインが何をするかをよりよく理解できることです。
関連している
アンインストールするには、プラグインのすべてのデータを削除する必要があります
WordPressのインストールから削除されたら、 プラグインは、すべてのファイル、フォルダー、データベースエントリ、テーブルを削除する必要があります それだけでなく作成しました オプション値 それは作成しました。
プラグインは、設定をエクスポート/インポートするオプションを提供する場合があり、削除前に設定をWordPressの外側に保存できるようにすることができます。
関連している
入力データを使用したSQLインジェクションを防ぎます
プラグイン したほうがいい 直接または間接的に取得されたすべてのユーザー入力を消毒する(例: $_POST
また $_GET
)入力値を使用してMySQLデータベースを照会する前に。
見る: SQLステートメントのフォーマット.
すべてのグローバルネームスペースアイテムをプレフィックスします
プラグインは、すべてのグローバルネームスペースアイテム(定数、関数、クラス、変数、カスタム分類法、投稿タイプ、ウィジェットなどのようなもの)を適切に接頭する必要があります。たとえば、呼ばれる関数を作成しないでください init()
;代わりに、そのようなものに名前を付けてください jpb_init()
.
その共通は、名前の前に3つまたは4文字のプレフィックスを使用するか、 PHPネームスペース機能. 。比較: PHPクラス定数のシングルレタープレフィックス?
関連している
クラスとオブジェクト指向のPHP5コードを使用します
クリーンでオブジェクト指向のPHP5コードを書かない理由はありません。 PHP4サポートは、次のリリース後に段階的に廃止されます(WP 3.1)。もちろん、すべての関数名をプレフィックスにして、終了することなくedlingly_long_function_names_with_lots_of_underscoresで終わることができますが、単純なクラスを書いてすべてをバンドルする方がはるかに簡単です。また、クラスを別のファイルに入れて、それに応じて名前を付けて、簡単に拡張して維持できるようにします。
// in functions.php
require 'inc/class-my-cool-plugin.php';
new MyCoolPlugin();
// in inc/class-my-cool-plugin.php
class MyCoolPlugin {
function __construct() {
// add filter hooks, wp_enqueue_script, etc.
// To assign a method from your class to a WP
// function do something like this
add_action('admin_menu', array($this, "admin"));
}
public function admin() {
// public methods, for use outside of the class
// Note that methods used in other WP functions
// (such as add_action) should be public
}
private function somethingelse() {
// methods you only use inside this class
}
}
非アクティブ化はデータロスを引き起こすべきではありません
プラグイン いけない そのデータのいずれかを削除します 非アクティブ化.
関連している
必要なファイルのみを含める...
フロントエンドにいる場合は、管理エリアに関連するコードを含めないでください。
プラグインのアンインストールでデータロスを発表します
アンインストール時に プラグイン したほうがいい ユーザーにデータを削除するように促します そして、ユーザーがそうする前にデータを削除しても大丈夫であることとプラグインを受け取っていることを受け取ります したほうがいい また ユーザーにデータを保持するオプションを許可します アンインストール時に。 (@eamannからのこのアイデア。)
関連している
プラグインのフォルダー名を変更します
/プラグイン/プラグインネーム/{さまざま}
フォルダーに使用される「プラグインネーム」は、常に変更可能である必要があります。
これは通常、定数を定義し、プラグイン全体で一貫して使用することによって処理されます。
言うまでもなく、多くの人気のあるプラグインは罪人です。
関連している:
plugins_url()
プラグインに含まれるリソースに簡単にリンクするため。
WordPress(組み込み)エラー処理を使用します
ただしないでください return;
一部のユーザー入力が間違っていた場合。間違って行われたという情報を提供します。
function some_example_fn( $args = array() )
{
// If value was not set, build an error message
if ( ! isset( $args['some_value'] ) )
$error = new WP_Error( 'some_value', sprintf( __( 'You have forgotten to specify the %1$s for your function. %2$s Error triggered inside %3$s on line %4$s.', TEXTDOMAIN ), '$args[\'some_value\']', "\n", __FILE__, __LINE__ ) );
// die & print error message & code - for admins only!
if ( isset( $error ) && is_wp_error( $error ) && current_user_can( 'manage_options' ) )
wp_die( $error->get_error_code(), 'Theme Error: Missing Argument' );
// Elseif no error was triggered continue...
}
すべての1つのエラー(オブジェクト)
ブートストラップ中に、テーマまたはプラグインのグローバルエラーオブジェクトを設定できます。
function bootstrap_the_theme()
{
global $prefix_error, $prefix_theme_name;
// Take the theme name as error ID:
$theme_data = wp_get_theme();
$prefix_theme_name = $theme_data->Name;
$prefix_error = new WP_Error( $theme_data->Name );
include // whatever, etc...
}
add_action( 'after_setup_theme', 'bootstrap_the_theme' );
後で、需要のない無制限のエラーを追加できます。
function some_theme_fn( $args )
{
global $prefix_error, $prefix_theme_name;
$theme_data = wp_get_theme();
if ( ! $args['whatever'] && current_user_can( 'manage_options' ) ) // some required value not set
$prefix_error->add( $prefix_theme_name, sprintf( 'The function %1$s needs the argument %2$s set.', __FUNCTION__, '$args[\'whatever\']' ) );
// continue function...
}
その後、テーマの最後にすべてを取得できます。これにより、ページのレンダリングを中断せず、開発のためのすべてのエラーを出力できます
function dump_theme_errors()
{
global $prefix_error, $prefix_theme_name;
// Not an admin? OR: No error(s)?
if ( ! current_user_can( 'manage_options' ) ! is_wp_error( $prefix_error ) )
return;
$theme_errors = $prefix_error->get_error_messages( $prefix_theme_name );
echo '<h3>Theme Errors</h3>';
foreach ( $theme_errors as $error )
echo "{$error}\n";
}
add_action( 'shutdown', 'dump_theme_errors' );
詳細情報を見つけることができます このq. 。の「一緒に作業」を修正するための関連チケット WP_Error
と wp_die()
そこからリンクされ、別のチケットが続きます。コメント、批評家などは感謝されています。
グローバルネームスペースに追加された名前を最小化します
プラグイン したほうがいい その衝撃を減らします できるだけ グローバルネームスペースに追加する名前の数を最小化する.
これは、プラグインの機能をクラスにカプセル化するか、 PHPネームスペース機能. 。すべてのプレフィックスも同様に役立ちますが、それほど柔軟ではありません。
関数とクラスの隣、プラグイン いけない グローバル変数を紹介します。通常、クラスを使用すると、それらが廃止され、プラグインのメンテナンスが簡素化されます。
関連している
phpdocを使用したコメント
ベストプラクティスは、PHPDOCスタイルに近いものです。 「Eclipse」のようなIDEを使用しない場合は、ご覧ください phpdocマニュアルで.
これがどのように機能するかを正確に知る必要はありません。プロの開発者はとにかくコードを読むことができ、これを要約として必要とするだけです。趣味のコーダーとユーザーは、同じ知識レベルでそれを説明する方法を高く評価するかもしれません。
プラグインユーザーのプライバシーを保護します
(以前:匿名API通信)
プラグインが外部システムまたはAPI(いくつかのWebサービスなど)と通信する場合、プラグインのユーザーに関連するデータが2番目のパーティに漏れないことを保証する匿名オプションをユーザーに提供するか、ユーザーに提供する必要があります。
wordpress.orgのホストプラグイン
使用 SVN リポジトリ wordpress.orgに提供されます プラグインをホストするため。これにより、ユーザーの経験が容易になり、SVNをこれまで使用したことがない場合、それを正当化するコンテキストでそれを使用することで実際に理解することができます。
権限を使用してアクセス制御を提供します
多くの場合、ユーザーは、特に複数の複雑な操作を行うプラグインを使用して、誰もがプラグインによって作成された領域にアクセスできるようにしたい場合があります。単一のハードコーディング機能チェックでは十分ではありません。
少なくとも、プラグインを使用できるさまざまな種類のすべての手順の適切な機能チェックがあります。
プラグインの設定をインポート /エクスポートします
プラグイン全体でそれほど一般的ではありませんが、プラグインが(一部の)設定がある場合、 したほうがいい 構成やユーザー入力などのデータのインポート /エクスポートを提供する.
インポート/エクスポートは、プラグインの使いやすさを向上させます。
このようなインポートおよびエクスポート機能を備えた(および元に戻すメカニズムを持っている例プラギンは Breadcrumb Navxt(WordPressプラグイン) (完全な開示:そこには私による小さなコードがありますが、ほとんどがMtekkによって行われました)。
関連している
コードを整理します
取得した順序で書かれていないコードを読むのは常に難しいです。最初に、/要求、定義、wp_enqueue_style&_scriptなどを含める、次にプラグイン/テーマが必要とする関数、そして最後にビルダー(例えば管理画面、テーマに統合されるものなど)が必要です。
独自のフォルダーでCSSやJSなどを分離してみてください。また、アレイフラットナーなどのヘルパーのみである関数でこれを行うようにしてください。 「メイン」ファイルを可能な限り清潔で読みやすい状態に保つことは、1年で更新しようとし、コードを長い間見ていないときに、ユーザー、開発者、およびあなたを支援する方法です。
頻繁に繰り返す構造を持っていることも良いので、いつもあなたの道を見つけることができます。さまざまなプロジェクトで既知の構造で開発することで、それを改善する時間が得られ、クライアントが別の開発者に切り替えても、「彼がカオスを離れた」と聞くことはありません。これはあなたの評判を築き、長期的な目標であるべきです。
スタイルで死ぬ
まともな方法で死ぬすべてのプラグイン(およびテーマ)機能は使用する必要があります wp_die()
重要な場所では、ユーザーに何が起こったかについて少し情報を提供します。 PHPエラーは迷惑です wp_die
プラグイン(または彼ら)が間違ったことについて、ユーザーに素敵なスタイルのメッセージを与えることができます。さらに、ユーザーがデバッグをデバッグした場合、プラグインは壊れます。
使用 wp_die()
また、プラグイン /テーマが WordPress TestSuite.
ユーザーにヘルプ画面を提供します
質問に何度も答えなければならないよりも、RTFM(ヘルプをクリックする)と答えてもいいです。
/**
* Add contextual help for this screen
*
* @param $rtfm
* @uses get_current_screen
*/
function ContextualHelp( /*string*/ $rtfm)
{
$current_screen = get_current_screen();
if ($current_screen->id == $this->_pageid)
{
$rtfm .= '<h3>The WordPress Plugin - Screen A</h3>';
$rtfm .= '<p>Here are some tips: donate to me ' .
}
return $rtfm;
}
add_action('contextual_help', array($this,'ContextualHelp'),1,1);
更新 /注: (Kaiserからのコメントを参照):上記の例はクラスで使用されます
拡張可能なフォームを提供します
プラグインがデータを入力する可能性を提供する場合、「送信」および/または「リセット」ボタンの直前に、常に最後にフックを使用する必要があるため、開発者はフィールドだけでなくボタンも簡単にフォームを拡張できます。
見る: 設定API
関連している
直接ではなく、常にフック経由で機能を含めます。
例:
new withouthookを介してプラグインのクラスを含めることを使用しないでください
フックプラグインを使用してください
// add the class to WP function my_plugin_start() { new my_plugin(); } add_action( 'plugins_loaded', 'my_plugin_start' );
アップデート:小さなライブの例: プラグインSVN-Trunk-Pageと擬似の例
//avoid direct calls to this file where wp core files not present
if (!function_exists ('add_action')) {
header('Status: 403 Forbidden');
header('HTTP/1.1 403 Forbidden');
exit();
}
if ( !class_exists( 'plugin_class' ) ) {
class plugin_class {
function __construct() {
}
} // end class
function plugin_start() {
new plugin_class();
}
add_action( 'plugins_loaded', 'plugin_start' );
} // end class_exists
Multisite-installでMu_plugins_loadedを介してロードすることもできます。アクションリファレンスについては、Codexを参照してください。 http://codex.wordpress.org/plugin_api/action_referenceまた、このフックでWPをどのようにinlcudeしているかはここにありますか: http://adambrown.info/p/wp_hooks/hook/plugins_loaded?version=2.1&file=wp-settings.php私はこれを非常に頻繁に使用していますが、それほど硬くて早く、困難な新しいクラスとしてより良いです()。
プラグインの説明は、プラグインの機能を正確に詳しく説明する必要があります。注目のポストプラグインが10個あります。それらはすべて機能の投稿を表示しますが、多くの機能が異なる機能を持っています。説明を読んで、プラグインと同様のプラグインを簡単に比較するのは簡単です。
プラグインが本当に基本的でない限り、プラグインがどれほどシンプルであるかについて自慢することを避ける必要があります。設定へのリンクなど、説明に有用なリンクを含める必要があります。
リモートデータソースとウェブサービスの副作用を最小限に抑えます
プラグイン したほうがいい キャッシュ/シールドウェブサービス および/または キャッシュ/データプロバイダーレイヤーを介したXMLRPC/SOAP要求 それらを使用する場合、(遅い)ウェブサービス応答を待っているフロントリクエストを作成しないようにします。
これには、RSSフィードやその他のページのダウンロードが含まれます。バックグラウンドでデータを要求するプラグインを設計します。
考えられるステップの1つは(例としてping.fmに投稿する):バッファテーブルを作成します。
- Ping.fmに更新を送信するたびに、このテーブルに追加します。
- 次に、このデータを処理するためのプラグインを作成する必要があります。このプラグインはCrontab経由で実行され、まだ提出されていないすべてのアップデートを確認します
- このテーブルがあるため、ping.fmに送信されたすべてのメッセージをリストし、各投稿のステータスを確認することもできます。 ping.fmの側に問題がある場合に備えて、再サブリットできます。
プラグインをテストします
プラグイン開発環境には、いくつかのテストツールが確実にある必要があります。
に基づく この答え に イーサン・セイファート テストの質問にとって、これらは従うべき良い実践です。
- ユニットテストでは、クラスが実行できる最小の動作をテストする必要があります。
- 機能テストのレベルに達すると、これはWordPress依存関係でコードをテストできる場所です。
- プラグインが何をするかに応じて、IDを使用してDOM内のデータの存在をテストするセレンベースのテストを使用することを検討してください