在上一教程中 ,我们回顾了自动加载器的原始状态,然后经历了面向对象的分析和设计过程。 这样做的目的是使我们可以将本系列和入门系列中介绍的所有内容结合在一起。
其次,在自己的教程中进行此操作的目的是使我们可以将剩下的时间花在遍历我们的类上,了解每个部分如何配合在一起,在插件中实现它,然后了解如何应用面向对象的编程和单一责任原则可以导致更集中,更可维护的解决方案。
开始之前
在这一点上,我假设您一直在关注本系列。 如果没有,请复习第一部分和第二部分。 假设您到目前为止一直在关注。
如果您是初学者,我也建议您完整阅读初始系列 。 一旦陷入困境,您就应该处于一个良好的位置,以完成本系列,因为我们将得出本教程涵盖的其余源代码。
到目前为止我们所做的
为了提供快速摘要并确保我们都在同一页面上,我们在本系列中介绍了以下主题:
- 回顾了类接口的定义
- 看到了类如何实现接口
- 回顾了单一责任原则
- 分析了我们现有的自动装带器
- 为我们的自动加载器的面向对象版本创建了路线图
- 并为自动加载器的面向对象版本设计了基本实现
至此,我们已经准备好将现有的自动加载器换成基于对象的代码。 但是请注意,这不是更改文件的简单问题。
我们需要做什么
相反,我们将需要创建文件,确保它们遵循WordPress编码标准 ,对其进行实施,测试其实施以确保插件仍然有效,然后删除现有的自动加载器。
这听上去需要做很多工作,但是如果我们对上一教程的分析和设计正确完成并证明是准确的,那么上面列出的所有内容都应该毫无问题。
您的开发环境
在开始实施之前,我想快速介绍一下您应该在系统上拥有的开发环境。 从技术上讲,这是您应该已经按照先前教程中的说明运行的东西,但是我希望尽可能完整。
- 适用于您的操作系统的本地开发环境
- WordPress 4.6.1所在的目录
- 文本编辑器或IDE
- WordPress插件API的知识
话虽如此,让我们开始吧。
面向对象的实现
在本节中,我们将重新访问在上一教程中回顾的所有代码。 但是,我们将查看每个单独的文件以及完整的文档。
另外,我们将把它包含在我们的项目中,以便在本教程结束时,我们将能够使用此代码代替我们先前使用的基于过程的单个代码。
请注意,以下每个文件应按列出的名称命名,并应包含在inc
目录中。 此外,所有这些都可以通过使用本文侧边栏中的蓝色按钮下载。
class-autoloader.php
namespace_validator = new NamespaceValidator();
$this->file_registry = new FileRegistry();
}
/**
* Attempts to load the specified filename.
*
* @param string $filename The path to the file that we're attempting to load.
*/
public function load( $filename ) {
if ( $this->namespace_validator->is_valid( $filename ) ) {
$this->file_registry->load( $filename );
}
}
}
class-namespace-validator.php
class-file-investigator.php
get_file_name( $file_parts, $current, $i );
if ( count( $file_parts ) - 1 !== $i ) {
$filepath = trailingslashit( $filepath );
}
}
return $filepath;
}
/**
* Retrieves the location of part of the filename on disk based on the current index of the
* array being examined.
*
* @access private
* @param array $file_parts The array of all parts of the file name.
* @param string $current The current part of the file to examine.
* @param int $i The current index of the array of $file_parts to examine.
* @return string The name of the file on disk.
*/
private function get_file_name( $file_parts, $current, $i ) {
$filename = '';
if ( count( $file_parts ) - 1 === $i ) {
if ( $this->is_interface( $file_parts ) ) {
$filename = $this->get_interface_name( $file_parts );
} else {
$filename = $this->get_class_name( $current );
}
} else {
$filename = $this->get_namespace_name( $current );
}
return $filename;
}
/**
* Determines if the specified file being examined is an interface.
*
* @access private
* @param array $file_parts The parts of the filepath to examine.
* @return bool True if interface is contained in the filename; otherwise, false.
*/
private function is_interface( $file_parts ) {
return strpos( strtolower( $file_parts[ count( $file_parts ) - 1 ] ), 'interface' );
}
/**
* Retrieves the filename of the interface based on the specified parts of the file passed
* into the autoloader.
*
* @access private
* @param array $file_parts The array of parts of the file to examine.
* @return string The filename of the interface.
*/
private function get_interface_name( $file_parts ) {
$interface_name = explode( '_', $file_parts[ count( $file_parts ) - 1 ] );
$interface_name = $interface_name[0];
return "interface-$interface_name.php";
}
/**
* Generates the name of the class filename on disk.
*
* @access private
* @param string $current The current piece of the file name to examine.
* @return string The class filename on disk.
*/
private function get_class_name( $current ) {
return "class-$current.php";
}
/**
* Creates a mapping of the namespace to the directory structure.
*
* @access private
* @param string $current The current part of the file to examine.
* @return string The path of the namespace mapping to the directory structure.
*/
private function get_namespace_name( $current ) {
return '/' . $current;
}
}
class-file-registry.php
investigator = new FileInvestigator();
}
/**
* Uses the file investigator to retrieve the location of the file on disk. If found, then
* it will include it in the project; otherwise, it will throw a WordPress error message.
*
* @param string $filepath The path to the file on disk to include in the plugin.
*/
public function load( $filepath ) {
$filepath = $this->investigator->get_filetype( $filepath );
$filepath = rtrim( plugin_dir_path( dirname( __FILE__ ) ), '/' ) . $filepath;
if ( file_exists( $filepath ) ) {
include_once( $filepath );
} else {
wp_die(
esc_html( 'The specified file does not exist.' )
);
}
}
}
包括文件,启动自动装带器
现在我们已经创建了文件,我们需要再进行两个小更改:
- 我们需要将所有类都包含在inc目录中。
- 我们需要摆脱旧的自动加载器代码。
- 我们需要将新的自动加载器与
spl_autoload_register
函数一起使用。
最终,autoload.php的最终版本应如下所示:
它将完全完成我们上面概述的工作。
但是,等等,我遇到了错误!
至此,您已经完成了很多工作。 您已经重构了整个自动装带器,以使用面向对象的编程。 您已经记录了类和函数。 您已经创建了新文件,从旧文件中删除了代码,并且可以确保一切正常。
因此,就像任何开发人员一样,您启动浏览器窗口以刷新页面,仅显示一条错误消息:
幸运的是,这很容易解决。 问题在于我们试图过早添加元框。 为了解决这个问题,我们将更新Meta_Box
类中的init
方法以包括以下内容:
然后,我们将介绍一个函数,该函数将与我们刚刚完成的工作挂钩:
display, 'render' ),
'post',
'side',
'high'
);
}
此时,您应该能够毫无问题,没有警告,没有通知,也没有错误地执行新代码。
结论
完成所有这些工作似乎很多,而且确实如此! 但令人高兴的是,它在三个教程中涵盖了很多基础知识, 并且它是建立在上一个系列的基础上的。 在这方面,涵盖了许多新主题并学习了新技术。
请注意,我定期为Envato Tuts +撰写文章,您可以在个人资料页面上找到我以前的所有教程。 此外,我经常在我的博客和Twitter 上讨论WordPress上下文中的软件开发,因此随时随地关注我。
如此说来,请研究我们在本系列文章(可能是之前的文章)中介绍的代码,并查看您是否无法在现有或将来的工作中采用其中的某些技术。
翻译自: https://code.tutsplus.com/tutorials/object-oriented-autoloading-in-wordpress-part-3--cms-27515