>백엔드 개발 >PHP 튜토리얼 >리팩터링: 장기간 유지 관리를 위해 WordPress 메타박스 강화

리팩터링: 장기간 유지 관리를 위해 WordPress 메타박스 강화

王林
王林원래의
2023-08-30 20:37:02919검색

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

이 시리즈에서는 유지 관리가 가능한 WordPress 메타 박스를 구축하는 데 중점을 둡니다. 내 말은 우리가 잘 정리되어 있고, WordPress 코딩 표준을 준수하며, 프로젝트가 계속 진행됨에 따라 쉽게 조정하고 유지 관리할 수 있는 WordPress 플러그인을 만들기 위해 열심히 노력했다는 것입니다.

몇 가지 모범 사례를 구현했지만 여전히 리팩토링의 여지가 있습니다. 이 시리즈에서는 의도적으로 설계된 것입니다. 클라이언트나 대기업을 위한 프로젝트를 개발할 때마다 기존 코드 기반을 유지해야 할 가능성이 상당히 높습니다. 따라서 우리가 작성한 코드 중 일부를 개선하기 위해 코드 기반으로 돌아갈 수 있기를 바랍니다.

이 기사는 다른 기사의 형식으로 작성되지 않습니다. 즉, 개발에 대해 "먼저 이렇게 하고 다음에는 이렇게 합니다"라는 접근 방식을 취하지 않을 것입니다. 대신 리팩토링이 필요한 몇 가지 영역을 강조한 다음 현재 진행 중인 다른 변경 사항과 별도로 해당 영역을 다루겠습니다.

리팩터링

분명히 말하면 리팩토링 행위(Wikipedia에서 정의)는 다음과 같습니다.

리팩토링은 소프트웨어의 비기능적 속성을 개선합니다. 이점에는 코드 가독성 향상, 복잡성 감소로 소스 코드 유지 관리 용이성 향상, 표현력이 풍부한 내부 스키마 또는 개체 모델 생성으로 확장성이 향상된다는 점 등이 있습니다.

즉, 최종 사용자의 관점에서 코드 동작을 변경하지 않고도 코드를 더 읽기 쉽고, 간단하고, 따르기 쉽게 만듭니다.

이는 해당 프로젝트마다 고유한 다양한 방법으로 달성할 수 있습니다. 우리의 경우 생성자, 일부 저장 메서드, 일부 도우미 메서드 등을 리팩터링하는 것을 고려해 보겠습니다.

궁극적으로 우리의 목표는 향후 WordPress 작업에 사용할 수 있는 몇 가지 전략을 보여주는 것입니다. 내 목표는 이 기사에서 가능한 한 자세히 설명하는 것입니다. 그러나 다루지 않은 다른 리팩토링 기회가 있을 수 있다는 점에 유의하세요.

그렇다면 정말 좋습니다! 자신의 코드베이스 인스턴스에서 자유롭게 만들어 보세요. 그 말을 듣고 시작하겠습니다.

생성자

생성자를 보면:

으아아아

현재 두 가지 작업을 수행하고 있습니다.

  1. 이름, 버전 등의 속성을 초기화하세요
  2. WordPress 등록 후크 사용

WordPress 플러그인 생성자의 맥락에서 후크 설정을 살펴보는 것이 일반적인 관행이지만 시작하기에 좋은 곳은 아닙니다.

생성자는 사용자가 클래스를 인스턴스화할 때 해당 클래스를 사용하는 데 필요한 모든 것을 갖출 수 있도록 특정 클래스와 관련된 모든 속성을 초기화하는 데 사용해야 합니다.

클래스를 초기화할 때 후크를 등록하고 싶지 않을 수 있으므로 이를 자체 initialize_hooks 메서드로 추상화해야 합니다. 이제 코드는 다음과 같아야 합니다:

으아아아

이후에는 Authors-commentary.php의 핵심 코드를 업데이트하여 후크를 올바르게 인스턴스화하고 등록해야 합니다.

으아아아

여기서 주요 차이점은 메인 클래스에 전달된 버전 번호를 업데이트하고 initialize_hooks 函数“内联”>run_author_commentary 함수 "inline" >run_author_commentary를 명시적으로 호출한다는 것입니다.

지금 코드를 실행하면 모든 것이 리팩토링 전과 완전히 동일해야 합니다.

또한 후크와 콜백 조정을 담당하는 별도의 클래스를 두어 책임이 별도의 클래스에 있을 수 있다는 점을 추가하고 싶습니다. 나는 이 접근 방식을 좋아하지만 이 기사의 범위를 벗어납니다.

다음에는 class-authors-commentary-meta-box.php로 같은 작업을 해보겠습니다. 새 함수를 만드는 대신 생성자가 실제로 아무 작업도 수행하지 않으므로 간단히 생성자의 이름을 바꿀 수 있습니다. 이는 우리 코드가 다음과 같아야 함을 의미합니다.

으아아아

이것에:

으아아아

마지막으로 변경해야 할 사항은 이제 메인 플러그인 클래스에서 생성한 initialize_hooks함수 내부를 읽을 수 있도록 메인 클래스의 생성자를 업데이트하는 것입니다.

으아아아

페이지를 다시 새로 고치면 플러그인이 리팩토링 전처럼 계속 작동할 것입니다.

도우미 방법

Authors_Commentary_Meta_Box 类中,我们在 save_post 함수에는 매우 중복되는 조건이 많이 있습니다. 이런 일이 발생하면 일반적으로 많은 기능을 도우미 함수로 추상화한 다음 원래 배치된 함수 내에서 호출할 수 있음을 의미합니다.

이제 코드를 살펴보겠습니다.

으아아아

시작 방법이 너무 긴 것 외에도 정리할 수 있는 몇 가지 사항이 있습니다.

  1. 논리 not 和逻辑 OR 연산자를 사용한 초기 조건
  2. 배열에 정보가 존재하는지 $_POST확인하는 조건
  3. 관련 메타데이터에 대한 정리, 업데이트 및/또는 삭제 기능

그럼 각각을 개별적으로 살펴보고 이 기능을 리팩토링해 보겠습니다.

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.