WordPress中的面向对象自动加载,第3部分

在上一教程中 ,我们回顾了自动加载器的原始状态,然后经历了面向对象的分析和设计过程。 这样做的目的是使我们可以将本系列和入门系列中介绍的所有内容结合在一起。

其次,在自己的教程中进行此操作的目的是使我们可以将剩下的时间花在遍历我们的类上,了解每个部分如何配合在一起,在插件中实现它,然后了解如何应用面向对象的编程和单一责任原则可以导致更集中,更可维护的解决方案。

开始之前

在这一点上,我假设您一直在关注本系列。 如果没有,请复习第一部分和第二部分。 假设您到目前为止一直在关注。

如果您是初学者,我也建议您完整阅读初始系列 。 一旦陷入困境,您就应该处于一个良好的位置,以完成本系列,因为我们将得出本教程涵盖的其余源代码。

到目前为止我们所做的

为了提供快速摘要并确保我们都在同一页面上,我们在本系列中介绍了以下主题:

  • 回顾了类接口的定义
  • 看到了类如何实现接口
  • 回顾了单一责任原则
  • 分析了我们现有的自动装带器
  • 为我们的自动加载器的面向对象版本创建了路线图
  • 并为自动加载器的面向对象版本设计了基本实现

至此,我们已经准备好将现有的自动加载器换成基于对象的代码。 但是请注意,这不是更改文件的简单问题。

我们需要做什么

相反,我们将需要创建文件,确保它们遵循WordPress编码标准 ,对其进行实施,测试其实施以确保插件仍然有效,然后删除现有的自动加载器。

这听上去需要做很多工作,但是如果我们对上一教程的分析和设计正确完成并证明是准确的,那么上面列出的所有内容都应该毫无问题。

您的开发环境

在开始实施之前,我想快速介绍一下您应该在系统上拥有的开发环境。 从技术上讲,这是您应该已经按照先前教程中的说明运行的东西,但是我希望尽可能完整。

  • 适用于您的操作系统的本地开发环境
  • WordPress 4.6.1所在的目录
  • 文本编辑器或IDE
  • WordPress插件API的知识

话虽如此,让我们开始吧。

面向对象的实现

在本节中,我们将重新访问在上一教程中回顾的所有代码。 但是,我们将查看每个单独的文件以及完整的文档。

另外,我们将把它包含在我们的项目中,以便在本教程结束时,我们将能够使用此代码代替我们先前使用的基于过程的单个代码。

请注意,以下每个文件应按列出的名称命名,并应包含在inc目录中。 此外,所有这些都可以通过使用本文侧边栏中的蓝色按钮下载。

class-autoloader.php

<?php
/**
 * Dynamically loads the class attempting to be instantiated elsewhere in the
 * plugin.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */

/**
 * The primary point of entry for the autoloading functionality. Uses a number of other classes
 * to work through the process of autoloading classes and interfaces in the project.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */
class Autoloader {

    /**
     * Verifies the file being passed into the autoloader is of the same namespace as the
     * plugin.
     *
     * @var NamespaceValidator
     */
    private $namespace_validator;

    /**
     * Uses the fully-qualified file path ultimately returned from the other classes.
     *
     * @var FileRegistry
     */
    private $file_registry;

    /**
     * Creates an instance of this class by instantiating the NamespaceValidator and the
     * FileRegistry.
     */
    public function __construct() {

        $this->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

<?php
/**
 * Looks at the incoming class or interface determines if it's valid.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */

/**
 * Looks at the incoming class or interface determines if it's valid.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */
class NamespaceValidator {

    /**
     * Yields the deciding factor if we can proceed with the rest of our code our not.
     *
     * @param  string $filename The path to the file that we're attempting to load.
     * @return bool             Whether or not the specified file is in the correct namespace.
     */
    public function is_valid( $filename ) {
        return ( 0 === strpos( $filename, 'Tutsplus_Namespace_Demo' ) );
    }
}

class-file-investigator.php

<?php
/**
 * This class looks at the type of file that's being passed into the autoloader.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */

/**
 * This class looks at the type of file that's being passed into the autoloader.
 *
 * It will determine if it's a class, an interface, or a namespace and return the fully-qualified
 * path name to the file so that it may be included.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */
class FileInvestigator {

    /**
     * Returns the fully-qualified path to the file based on the incoming filename.
     *
     * @param  string $filename The incoming filename based on the class or interface name.
     * @return string           The path to the file.
     */
    public function get_filetype( $filename ) {

        $file_parts = explode( '\\', $filename );

        $filepath = '';
        $length   = count( $file_parts );
        for ( $i = 1; $i < $length; $i++ ) {

            $current = strtolower( $file_parts[ $i ] );
            $current = str_ireplace( '_', '-', $current );

            $filepath .= $this->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

<?php
/**
 * Includes the file from the plugin.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */

/**
 * This will use the fully qualified file path ultimately returned from the other classes
 * and will include it in the plugin.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */
class FileRegistry {

    /**
     * This class looks at the type of file that's being passed into the autoloader.
     *
     * @var FileInvestigator
     */
    private $investigator;

    /**
     * Creates an instance of this class by creating an instance of the FileInvestigator.
     */
    public function __construct() {
        $this->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.' )
            );
        }
    }
}

包括文件,启动自动装带器

现在我们已经创建了文件,我们需要再进行两个小更改:

  1. 我们需要将所有类都包含在inc目录中。
  2. 我们需要摆脱旧的自动加载器代码。
  3. 我们需要将新的自动加载器与spl_autoload_register函数一起使用。

最终,autoload.php的最终版本应如下所示:

<?php
/**
 * Loads all of the classes in the directory, instantiates the Autoloader,
 * and registers it with the standard PHP library.
 *
 * @package Tutsplus_Namespace_Demo\Inc
 */

foreach ( glob( dirname( __FILE__ ) . '/class-*.php' ) as $filename ) {
    include_once( $filename );
}

$autoloader = new Autoloader();
spl_autoload_register( array( $autoloader, 'load' ) );

它将完全完成我们上面概述的工作。

但是,等等,我遇到了错误!

至此,您已经完成了很多工作。 您已经重构了整个自动装带器,以使用面向对象的编程。 您已经记录了类和函数。 您已经创建了新文件,从旧文件中删除了代码,并且可以确保一切正常。

因此,就像任何开发人员一样,您启动浏览器窗口以刷新页面,仅显示一条错误消息:

未定义的功能错误消息

幸运的是,这很容易解决。 问题在于我们试图过早添加元框。 为了解决这个问题,我们将更新Meta_Box类中的init方法以包括以下内容:

<?php

/**
 * Registers the add_meta_box function with the proper hook in the WordPress page
 * lifecycle.
 */
public function init() {
    add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
}

然后,我们将介绍一个函数,该函数将与我们刚刚完成的工作挂钩:

<?php

/**
 * Registers this meta box with WordPress.
 *
 * Defines a meta box that will render inspirational questions at the top
 * of the sidebar of the 'Add New Post' page in order to help prompt
 * bloggers with something to write about when they begin drafting a post.
 */
public function add_meta_box() {

    add_meta_box(
	    'tutsplus-post-questions',
	    'Inspiration Questions',
	    array( $this->display, 'render' ),
	    'post',
	    'side',
	    'high'
    );
}

此时,您应该能够毫无问题,没有警告,没有通知,也没有错误地执行新代码。

结论

完成所有这些工作似乎很多,而且确实如此! 但令人高兴的是,它在三个教程中涵盖了很多基础知识, 并且它是建立在上一个系列的基础上的。 在这方面,涵盖了许多新主题并学习了新技术。

请注意,我定期为Envato Tuts +撰写文章,您可以在个人资料页面上找到我以前的所有教程。 此外,我经常在我的博客Twitter 讨论WordPress上下文中的软件开发,因此随时随地关注我。

如此说来,请研究我们在本系列文章(可能是之前的文章)中介绍的代码,并查看您是否无法在现有或将来的工作中采用其中的某些技术。

翻译自: https://code.tutsplus.com/tutorials/object-oriented-autoloading-in-wordpress-part-3--cms-27515

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值