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

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

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

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

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

重构

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

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

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

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

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

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

构造函数

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

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' ) );}

登录后复制

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

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

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

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

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

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的核心代码,以便它正确实例化并注册钩子。

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 函数的内部。

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 函数中有许多非常多余的条件。发生这种情况时,通常意味着大部分功能可以抽象为辅助函数,然后从最初放置它们的函数内调用。

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

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 themif ( ! 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 themif ( ! 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' );}}}

登录后复制

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

使用逻辑 not 和逻辑 OR 运算符的初始条件检查 $_POST 数组中是否存在信息的条件关联元数据的清理、更新和/或删除功能

因此,让我们分别看看其中的每一个,并致力于重构此函数。

1。初始条件

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

现在,代码如下:

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

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

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

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

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

is_valid_post_type() && $is_valid_nonce;}

登录后复制

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

我们从这个开始:

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

登录后复制

现在我们有这个:

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 条件评估以调用此单个函数,使其读取如下内容:

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 );}

登录后复制

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

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 元框以实现长期维护的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/1702657.html

(0)
上一篇 2025年2月19日 14:56:41
下一篇 2025年2月19日 14:56:59

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 15个Java线程并发面试题和答案

    1. 现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行? 这个线程面试题通常在第一轮面试或电话面试时被问到,这道多线程问题为了测试面试者是否熟悉 join 方法的概念。答案也非常…

    2025年5月3日
    000
  • java面试题最容易犯错的8道

    1. static 和 final 的用法 static 的作用从三个方面来谈,分别是静态变量、静态方法、静态类。 静态变量:声明为 static 的静态变量实质上就是全局变量,当声明一个对象时,并不产生static 变量的拷贝,而是该类所…

    2025年5月3日
    000
  • Person p = new Person();在内存中做了哪些事情?

    Person p = new Person();在内存中做了哪些事情? 将Person.class文件加载进内存中。 如果p定义在主方法中,那么,就会在栈空间开辟一个变量空间p。 在堆内存给对象分配空间。 对对象中的成员进行默认初始化。 对…

    2025年5月3日
    000
  • 2020年JAVA最常见面试题汇总(收藏)

    java基础以及多个“比较” 1.collections.sort排序内部原理 在Java 6中Arrays.sort()和Collections.sort()使用的是MergeSort,而在Java 7中,内部实现换成了TimSort,其…

    2025年5月3日
    000
  • 9道常见的java笔试选择题

    1.关于Java编译,下面哪一个正确()(选择一项) A.Java程序经编译后产生machine code B.Java程序经编译后会生产byte code C.Java程序经编译后会产生DLL 立即学习“Java免费学习笔记(深入)”; …

    2025年5月3日
    000
  • java最新基础知识面试题

    java最新基础知识面试题 1、static关键字什么意思?java中是否可以覆盖一个private或者是static的方法? “static”表明一个成员变量或者是成员方法可以在没有所属类的实例变量的情况下访问。 java中static方…

    2025年5月3日
    000
  • java内存溢出面试题

    引起内存溢出的原因有很多种,常见的有以下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据; 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收; 代码中存在死循环或循环产生过多重复的对象实体; 立即学习“Java免费学…

    2025年5月3日
    000
  • Java中高级面试题(附答案)

    1、redis如何跟本地数据同步? 程序实现mysql更新、添加、删除就会同步操作redis 程序查询redis,不存在就查询mysql,自动保存redis 2、redis几种数据结构? set、list、hash、string、zset …

    2025年5月3日
    000
  • java gc 面试题及答案(1~5题)

    1、既然有GC机制,为什么还会有内存泄露的情况? 理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因)。然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因…

    2025年5月3日
    000
  • java笔试常见的选择题

    1.已知表达式int m[] = {0,1,2,3,4,5,6}; 下面那个表达式的值与数组的长度相等() A m.length() B. m.length C. m.length()+1 立即学习“Java免费学习笔记(深入)”; D. …

    2025年5月3日
    000

发表回复

登录后才能评论