ホームページ >バックエンド開発 >PHPチュートリアル >リファクタリング: 長期メンテナンスのために WordPress メタボックスを強化する

リファクタリング: 長期メンテナンスのために WordPress メタボックスを強化する

王林
王林オリジナル
2023-08-30 20:37:02919ブラウズ

重构:增强 WordPress 元框以实现长期维护

このシリーズでは、保守可能な WordPress メタ ボックスの構築に焦点を当てます。私が言いたいのは、私たちは、よく整理され、WordPress コーディング標準に準拠し、プロジェクトの進行に合わせて簡単に調整および保守できる WordPress プラグインを作成するために懸命に取り組んできたということです。

いくつかの優れたプラクティスを実装しましたが、リファクタリングの余地はまだあります。このシリーズでは、それは仕様によるものです。クライアントや大企業向けにプロジェクトを開発するときは、既存のコード ベースを保守する必要がある可能性が非常に高くなります。したがって、コードベースに戻って、作成したコードの一部を改善できればと思います。

この記事は他の記事の形式では書かれないことに注意してください。つまり、「最初にこれを行い、次にこれを行う」という開発アプローチは採用しません。代わりに、リファクタリングが必要ないくつかの領域を強調表示し、加えている他の変更とは独立してそれらに取り組みます。

復興

明確にするために、リファクタリングの行為 (Wikipedia による定義) は次のとおりです:

リファクタリングは、ソフトウェアの非機能的な特性を改善します。利点としては、コードの可読性の向上と複雑さの軽減によるソース コードの保守性の向上、より表現力豊かな内部スキーマまたはオブジェクト モデルの作成によるスケーラビリティの向上などが挙げられます。

つまり、エンドユーザーの観点から見たコードの動作を変えることなく、コードがより読みやすく、よりシンプルになり、理解しやすくなります。

これはさまざまな方法で実現できますが、それぞれの方法は特定のプロジェクトに固有です。私たちのケースでは、コンストラクター、いくつかの保存メソッド、いくつかのヘルパー メソッドなどのリファクタリングを検討します。

最終的に、私たちの目標は、今後の WordPress の取り組みで使用できるいくつかの戦略を示すことです。この記事ではできるだけ詳しく説明することを目標としていますが、カバーされていない他のリファクタリングの機会がある可能性があることに注意してください。

もしそうなら、それは素晴らしいことです!独自のコードベース インスタンス上で自由に作成してください。それを踏まえて、始めましょう。

###コンストラクタ###

コンストラクターを見ると:

リーリー

現在 2 つのことを行っていることに注意してください:

名前やバージョンなどの属性を初期化する
  1. WordPress 登録フックの使用
  2. WordPress プラグインのコンストラクターのコンテキストでフック設定を表示するのが一般的ですが、ここから始めるのは適切ではありません。

コンストラクターは、ユーザーがクラスをインスタンス化するときに、そのクラスを使用するために必要なものがすべて揃うように、特定のクラスに関連するすべてのプロパティを初期化するために使用する必要があります。

クラスの初期化時にフックを登録したくない場合があるため、それを独自の

initialize_hooks

メソッドに抽象化する必要があります。コードは次のようになります: リーリー その後、フックを正しくインスタンス化して登録できるように、authors-commentary.php のコア コードを更新する必要があります。

リーリー

ここでの主な違いは、メイン クラスに渡されるバージョン番号を更新することと、initialize_hooks<p> 関数 "inline">run_author_commentary<code class="的上下文中显式调用"> を明示的に呼び出すことです。 = 。

ここでコードを実行すると、すべてがリファクタリング前とまったく同じに見えるはずです。

また、フックとコールバックの調整を担当する別のクラスを用意して、その責任を別のクラスに持つことができることも付け加えておきます。私はこのアプローチが気に入っていますが、この記事の範囲を超えています。

次に、

class-authors-commentary-meta-box.php

で同じことをやってみましょう。コンストラクターは実際には何もしないため、新しい関数を作成する代わりに、コンストラクターの名前を変更するだけで済みます。これは、コードが次のようになることを意味します: リーリー ###に関して:### リーリー 必要な最後の変更は、メイン クラスのコンストラクターを更新して、メイン プラグイン クラスで作成した

initialize_hooks

関数の内部を読み取るようにすることです。

リーリー

ページを再度更新すると、プラグインはリファクタリング前と同じように機能するはずです。

補助メソッド

Authors_Commentary_Meta_Box

クラスの

save_post

関数には非常に冗長な条件がたくさんあります。これが起こる場合、通常、機能の多くがヘルパー関数に抽象化され、それらが元々配置されていた関数内から呼び出すことができることを意味します。

現在のコードを見てみましょう: リーリー 開始メソッドが長すぎることに加えて、いくつかのことをクリーンアップすることもできます:

論理

not

および論理

OR
    演算子を使用した初期条件
  1. チェック $_POST 配列に情報が存在するかどうかの条件
  2. 関連するメタデータのクリーニング、更新、および/または削除機能
  3. それでは、それぞれを個別に見て、この関数のリファクタリングに取り組んでみましょう。
  4. 1。初始条件

    第一个条件检查的目的是确保当前用户能够将数据保存到给定的帖子。现在,我们实际上是在检查当前帖子类型是否是有效的帖子类型,以及用户是否有权保存给定 WordPress 传递的当前随机数值。

    现在,代码如下:

    如果这不是有效的帖子类型或用户没有保存权限,则退出此功能。

    这并不是很糟糕,但绝对可以改进。让我们将其合并到单个评估中,而不是使用 OR ,使其显示为:

    如果用户没有保存权限,则退出此功能。

    幸运的是,这是一个相对容易的修复。由于保存的帖子类型有助于确定用户是否有权保存帖子,因此我们可以将该逻辑移至 user_can_save 函数中。

    因此,让我们将 is_valid_post_type 函数移至 user_can_save 函数中:

    <?php
    
    private function user_can_save( $post_id, $nonce_action, $nonce_id ) {
    
        $is_autosave = wp_is_post_autosave( $post_id );
        $is_revision = wp_is_post_revision( $post_id );
        $is_valid_nonce = ( isset( $_POST[ $nonce_action ] ) && wp_verify_nonce( $_POST[ $nonce_action ], $nonce_id ) );
    
        // Return true if the user is able to save; otherwise, false.
        return ! ( $is_autosave || $is_revision ) && $this->is_valid_post_type() && $is_valid_nonce;
    
    }
    

    现在,负责确定用户是否可以保存帖子元数据的所有逻辑都封装在专门设计用于精确评估的函数中。

    我们从这个开始:

    <?php
        
    if ( ! $this->is_valid_post_type() || ! $this->user_can_save( $post_id, 'authors_commentary_nonce', 'authors_commentary_save' ) ) {
    	return;
    }
    

    现在我们有这个:

    <?php
        
    if ( ! $this->user_can_save( $post_id, 'authors_commentary_nonce', 'authors_commentary_save' ) ) {
    	return;
    }
    

    阅读起来容易多了,不是吗?

    2.检查 $_POST 数组

    接下来,在开始清理、验证和保存(或删除)元数据之前,我们将检查 $_POST 集合以确保数据确实存在。

    我们可以编写一个小的辅助函数来为我们处理这个评估。虽然我们本质上是编写了一些代码,使我们的评估更加冗长,但与我们直接保留它们相比,条件语句读起来会更清晰一些。

    首先,引入以下函数(注意它接受一个参数):

    <?php
    
    /**
     * Determines whether or not a value exists in the $_POST collection
     * identified by the specified key.
     *
     * @since   1.0.0
     *
     * @param   string    $key    The key of the value in the $_POST collection.
     * @return  bool              True if the value exists; otherwise, false.
     */
    private function value_exists( $key ) {
        return ! empty( $_POST[ $key ] );
    }
    

    接下来,重构最初调用 的所有调用!空( $_POST[ ... ] ) 以便他们利用此功能。

    例如,函数调用应如下所示:

    if ( $this->value_exists( 'authors-commentary-comments' ) ) {
        // ...
    } else {
    	// ...
    }
    

    2.删除元数据

    请注意,在该函数中放置的整个条件中,如果值不存在,则每次删除帖子元数据的评估看起来都完全相同。

    例如,我们每次都会看到这样的东西:

    <?php
    
    if ( '' !== get_post_meta( $post_id, 'authors-commentary-comments', true ) ) {
        delete_post_meta( $post_id, 'authors-commentary-comments' );
    }
    

    这显然是重构代码的机会。因此,让我们创建一个名为 delete_post_meta 的新函数,并让它封装所有这些信息:

    <?php
    
    /**
     * Deletes the specified meta data associated with the specified post ID 
     * based on the incoming key.
     *
     * @since    1.0.0
     * @access   private
     * @param    int    $post_id    The ID of the post containing the meta data
     * @param    string $meta_key   The ID of the meta data value
     */
    private function delete_post_meta( $post_id, $meta_key ) {
        
    	if ( '' !== get_post_meta( $post_id, $meta_key, true ) ) {
    		delete_post_meta( $post_id, '$meta_key' );
    	}
    	
    }
    

    现在我们可以返回并替换所有 else 条件评估以调用此单个函数,使其读取如下内容:

    <?php
        
    // If the 'Drafts' textarea has been populated, then we sanitize the information.
    if ( $this->value_exists( 'authirs-commentary-drafts' ) ) {
    
    	// We'll remove all white space, HTML tags, and encode the information to be saved
    	$drafts = trim( $_POST['authors-commentary-drafts'] );
    	$drafts = esc_textarea( strip_tags( $drafts ) );
    
    	update_post_meta( $post_id, 'authors-commentary-drafts', $drafts );
    
    } else {
    	$this->delete_post_meta( $post_id, 'authors-commentary-drafts' );
    }
    

    此时,我们实际上只有这部分代码的另一个方面需要重构。

    3.消毒和保存

    现在,保存帖子元数据的方式是通过评估 $_POST 集合中数据是否存在的过程来完成的,并根据信息类型对其进行清理,然后将其保存到帖子元数据中。

    理想情况下,我们希望在自己的函数中清理数据,并将帖子元数据保存在自己的函数中。因此,我们需要引入新的功能。

    首先,让我们进行消毒工作。因为我们正在处理 textareas 和数组,所以我们需要通过几种方法来处理清理调用。由于我们要么使用数组,要么不使用数组,所以我们可以创建一个函数,该函数接受一个可选参数,表示我们是否正在使用数组。

    如果我们不使用数组,那么我们会将传入的数据视为文本;否则,我们会将其视为数组:

    <?php
        
    /**
     * Sanitizes the data in the $_POST collection identified by the specified key
     * based on whether or not the data is text or is an array.
     *
     * @since    1.0.0
     * @access   private
     * @param    string        $key                      The key used to retrieve the data from the $_POST collection.
     * @param    bool          $is_array    Optional.    True if the incoming data is an array.
     * @return   array|string                            The sanitized data.
     */
    private function sanitize_data( $key, $is_array = false ) {
    
    	$sanitized_data = null;
    
    	if ( $is_array ) {
    
    		$resources = $_POST[ $key ];
    		$sanitized_data = array();
    
    		foreach ( $resources as $resource ) {
    
    			$resource = esc_url( strip_tags( $resource ) );
    			if ( ! empty( $resource ) ) {
    				$sanitized_data[] = $resource;
    			}
    
    		}
    
    	} else {
    
    		$sanitized_data = '';
    		$sanitized_data = trim( $_POST[ $key ] );
    		$sanitized_data = esc_textarea( strip_tags( $sanitized_data ) );
    
    	}
    
    	return $sanitized_data;
    
    }
    

    接下来,我们可以更新清理调用以使用此方法。但在此之前,我们还需要编写一个小助手,负责使用经过净化的输入更新帖子元数据:

    <?php
    
    private function update_post_meta( $post_id, $meta_key, $meta_value ) {
        
        if ( is_array( $_POST[ $meta_key ] ) ) {
            $meta_value = array_filter( $_POST[ $meta_key ] );
    	}
    
        update_post_meta( $post_id, $meta_key, $meta_value );
    }
    

    现在我们可以更新之前在函数中使用的所有条件,如下所示:

    <?php
        
    public function save_post( $post_id ) {
    
    	if ( ! $this->user_can_save( $post_id, 'authors_commentary_nonce', 'authors_commentary_save' ) ) {
    		return;
    	}
    
    	if ( $this->value_exists( 'authors-commentary-drafts' ) ) {
    
    		$this->update_post_meta(
    			$post_id,
    			'authors-commentary-drafts',
    			$this->sanitize_data( 'authors-commentary-drafts' )
    		);
    
    	} else {
    		$this->delete_post_meta( $post_id, 'authors-commentary-drafts' );
    	}
    
    	if ( $this->value_exists( 'authors-commentary-resources' ) ) {
    
    		$this->update_post_meta(
    			$post_id,
    			'authors-commentary-resources',
    			$this->sanitize_data( 'authors-commentary-resources', true )
    		);
    
    	} else {
    		$this->delete_post_meta( $post_id, 'authors-commentary-resources' );
    	}
    
    	if ( $this->value_exists( 'authors-commentary-comments' ) ) {
    
    		$this->update_post_meta(
    			$post_id,
    			'authors-commentary-comments',
    			$_POST['authors-commentary-comments']
    		);
    
    	} else {
    		$this->delete_post_meta( $post_id, 'authors-commentary-comments' );
    	}
    
    }
    

    请注意,我们实际上可以进一步重构这个特定的部分,这样就没有那么多的条件,但是考虑到文章的长度、时间的长度,并且还尝试引入一些其他策略,这将是留作练习,在您自己的时间完成。

    结论

    到目前为止,我们已经完成了我们的插件。我们编写了一个插件,引入了一个元框,为撰写博客文章的作者提供选项。

    此外,我们还采用了 WordPress 编码标准、一些强大的文件组织策略,并创建了许多辅助方法和抽象,这将帮助我们在未来的开发中维护这个特定的插件。

    由于突出显示每一个重构机会并不容易,因此可能还需要进行其他更改。在您自己的时间里,请随意尝试自己实现其中一些。

    总的来说,我希望您喜欢本系列并从中学到很多东西,并且我希望它能帮助您在未来基于 WordPress 的项目中编写更好、更易于维护的代码。

以上がリファクタリング: 長期メンテナンスのために WordPress メタボックスを強化するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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