目录
重构
构造函数
辅助方法
1。初始条件
2.检查 $_POST 数组
2.删除元数据
3.消毒和保存
结论
首页 后端开发 php教程 重构:增强 WordPress 元框以实现长期维护

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

Aug 30, 2023 pm 08:37 PM

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

在本系列中,我们专注于构建可维护的 WordPress 元框。我的意思是,我们一直在努力创建一个组织良好、遵循 WordPress 编码标准的 WordPress 插件,并且随着项目的不断进展,可以轻松调整和维护。

尽管我们已经实施了一些好的实践,但仍然有重构的空间。对于这个系列,这是设计使然的。每当您为客户或大公司开发项目时,您必须维护现有代码库的可能性相当高。因此,我希望我们能够返回到我们的代码库,以便改进我们编写的一些代码。

请注意,本文不会按照其他文章的格式编写 - 也就是说,不会采用“首先我们这样做,然后我们这样做”的开发方法。相反,我们将突出显示需要重构的几个领域,然后独立于我们正在进行的其他更改来处理它们。

重构

需要明确的是,重构行为(按照维基百科的定义)是:

重构改进了软件的非功能属性。优点包括提高代码可读性和降低复杂性以提高源代码可维护性,并创建更具表现力的内部架构或对象模型以提高可扩展性。

简而言之,它使代码更具可读性、更简单、更易于遵循,并且从最终用户的角度来看,这一切都无需改变代码的行为。

这可以通过多种不同的方式来实现,每种方式对于给定的项目都是独特的。在我们的例子中,我们将考虑重构我们的构造函数、一些保存方法、一些辅助方法等等。

最终,我们的目标是展示一些可以在您未来的 WordPress 工作中使用的策略。我的目标是在本文中尽可能详细地介绍;但是,请注意,可能存在未涵盖的其他重构机会。

如果是这样的话,那就太好了!请随意在您自己的代码库实例上制作它们。话虽如此,让我们开始吧。

构造函数

如果您看一下我们的构造函数:

<?php 
    	
public function __construct( $name, $version ) {

	$this->name = $name;
	$this->version = $version;

	$this->meta_box = new Authors_Commentary_Meta_Box();

	add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
	add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );

}
登录后复制

请注意,它当前正在执行两件事:

  1. 初始化名称和版本等属性
  2. 使用 WordPress 注册挂钩

在 WordPress 插件的构造函数上下文中查看钩子设置是常见的做法,但这并不是一个很好的地方。

应该使用构造函数来初始化与给定类相关的所有属性,以便当用户实例化一个类时,他/她拥有使用该类所需的一切。

由于他们可能不想在初始化类时注册钩子,因此我们需要将其抽象为自己的 initialize_hooks 方法。我们的代码现在应该如下所示:

<?php

public function __construct( $name, $version ) {

    $this->name = $name;
    $this->version = $version;

    $this->meta_box = new Authors_Commentary_Meta_Box();

}

public function initialize_hooks() {
	
	add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
	add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
	
}
登录后复制

之后,我们需要确保更新authors-commentary.php的核心代码,以便它正确实例化并注册钩子。

<?php

function run_author_commentary() {
    
	$author_commentary = new Author_Commentary_Admin( 'author-commentary', '1.0.0' );
	$author_commentary->initialize_hooks();
	
}
run_author_commentary();
登录后复制

这里,主要区别在于我们更新了传递给主类的版本号,并且我们还在 initialize_hooks 函数“内联”>run_author_commentary 函数“内联”>run_author_commentary。

如果您现在执行代码,一切都应该与重构之前完全一样。

我还想补充一点,您可以有一个单独的类负责协调挂钩和回调,以便该责任位于单独的类中。尽管我很喜欢这种方法,但这超出了本文的范围。

接下来,让我们对 class-authors-commentary-meta-box.php 执行相同的操作。我们可以简单地重命名构造函数,而不是创建一个新函数,因为构造函数实际上并不执行任何操作。这意味着我们的代码应该如下所示:

<?php 

public function __construct() {

    add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
    add_action( 'save_post', array( $this, 'save_post' ) );

}
登录后复制

对此:

<?php

public function initialize_hooks() {

    add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
    add_action( 'save_post', array( $this, 'save_post' ) );

}
登录后复制

我们需要做的最后一个更改是更新主类中的构造函数,以便它现在读取我们在主插件类中创建的 initialize_hooks 函数的内部。

<?php

public function initialize_hooks() {

    $this->meta_box->initialize_hooks();

    add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
    add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );

}
登录后复制

再次刷新页面,您的插件应该仍然可以像重构之前一样正常运行。

辅助方法

Authors_Commentary_Meta_Box 类中,我们在 save_post 函数中有许多非常多余的条件。发生这种情况时,通常意味着大部分功能可以抽象为辅助函数,然后从最初放置它们的函数内调用。

让我们看一下现在的代码:

<?php
    
public function save_post( $post_id ) {

	/* If we're not working with a 'post' post type or the user doesn't have permission to save,
	 * then we exit the function.
	 */
	if ( ! $this->is_valid_post_type() || ! $this->user_can_save( $post_id, 'authors_commentary_nonce', 'authors_commentary_save' ) ) {
		return;
	}

	// If the 'Drafts' textarea has been populated, then we sanitize the information.
	if ( ! empty( $_POST['authors-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 {

		if ( '' !== get_post_meta( $post_id, 'authors-commentary-drafts', true ) ) {
			delete_post_meta( $post_id, 'authors-commentary-drafts' );
		}

	}

	// If the 'Resources' inputs exist, iterate through them and sanitize them
	if ( ! empty( $_POST['authors-commentary-resources'] ) ) {

		$resources = $_POST['authors-commentary-resources'];
		$sanitized_resources = array();
		foreach ( $resources as $resource ) {

			$resource = esc_url( strip_tags( $resource ) );
			if ( ! empty( $resource ) ) {
				$sanitized_resources[] = $resource;
			}

		}

		update_post_meta( $post_id, 'authors-commentary-resources', $sanitized_resources );

	} else {

		if ( '' !== get_post_meta( $post_id, 'authors-commentary-resources', true ) ) {
			delete_post_meta( $post_id, 'authors-commentary-resources' );
		}

	}

	// If there are any values saved in the 'Published' input, save them
	if ( ! empty( $_POST['authors-commentary-comments'] ) ) {
		update_post_meta( $post_id, 'authors-commentary-comments', $_POST['authors-commentary-comments'] );
	} else {

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

	}

}
登录后复制

除了开始的方法太长之外,我们还可以清理一些东西:

  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

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

会话如何劫持工作,如何在PHP中减轻它? 会话如何劫持工作,如何在PHP中减轻它? Apr 06, 2025 am 12:02 AM

会话劫持可以通过以下步骤实现:1.获取会话ID,2.使用会话ID,3.保持会话活跃。在PHP中防范会话劫持的方法包括:1.使用session_regenerate_id()函数重新生成会话ID,2.通过数据库存储会话数据,3.确保所有会话数据通过HTTPS传输。

在PHP API中说明JSON Web令牌(JWT)及其用例。 在PHP API中说明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

描述扎实的原则及其如何应用于PHP的开发。 描述扎实的原则及其如何应用于PHP的开发。 Apr 03, 2025 am 12:04 AM

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

如何在系统重启后自动设置unixsocket的权限? 如何在系统重启后自动设置unixsocket的权限? Mar 31, 2025 pm 11:54 PM

如何在系统重启后自动设置unixsocket的权限每次系统重启后,我们都需要执行以下命令来修改unixsocket的权限:sudo...

在PHPStorm中如何进行CLI模式的调试? 在PHPStorm中如何进行CLI模式的调试? Apr 01, 2025 pm 02:57 PM

在PHPStorm中如何进行CLI模式的调试?在使用PHPStorm进行开发时,有时我们需要在命令行界面(CLI)模式下调试PHP�...

解释PHP中的晚期静态绑定(静态::)。 解释PHP中的晚期静态绑定(静态::)。 Apr 03, 2025 am 12:04 AM

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

如何用PHP的cURL库发送包含JSON数据的POST请求? 如何用PHP的cURL库发送包含JSON数据的POST请求? Apr 01, 2025 pm 03:12 PM

使用PHP的cURL库发送JSON数据在PHP开发中,经常需要与外部API进行交互,其中一种常见的方式是使用cURL库发送POST�...

See all articles