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

我最近整理了一系列文章,其中介绍了WordPress中的名称空间和自动加载 。 如果您不熟悉以上任何一个术语,那么我建议您阅读该系列文章。

您可以预期学习的要点如下:

在本系列文章中,我们将确切地了解什么是PHP名称空间,为什么有益,以及如何使用它们。 然后,我们将研究如何使用自动加载器自动加载所需的文件,而不必在代码中手动加载它们。

在编写该系列,特别是自动装带器的系列时,我忍不住意识到与我共享代码时引入的许多代码味道。

这并不是说自动装带器是坏的或不起作用。 如果您下载了该插件,运行了该插件,或者紧随其后并编写了自己的自动加载器,那么您知道它确实可以工作。

但是在一个专注于名称空间的系列中(这是面向对象编程的一部分),我忍不住感到不舒服,在系列结束时让自动加载器处于最终状态。

不要误解我的意思:我仍然支持该系列影片,所涵盖的内容以及我们制作的作品的最终结果。 但是从面向对象的角度来看,还有更多工作可以完成。 因此,在此后续系列中,我们将从面向对象编程的角度重新审视自动加载器的概念。

具体来说,我们将讨论以下概念:

  • 介面
  • 接口实现
  • 单一责任原则
  • 以及面向对象编程的核心其他原则和思想

我希望,当我们完成本系列文章时,我们不仅可以将自动加载器重构为更易于维护和易于阅读的东西,而且还可以遵循更大的面向对象的实践。

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

入门

就像我写的几乎每一篇文章一样,我喜欢尝试做两件事:

  1. 定义前进的路线图。
  2. 为您提供启动机器并运行所需的一切。

在开始编写任何代码之前,让我们现在开始。

我们的路线图

在接下来的两篇文章中,我们将研究一些面向对象的概念,这些概念将使我们能够改进上一个系列中构建的插件。

如果您没有该插件的副本,则可以下载该插件的副本 ; 但是,我将在每个教程中共享完整的代码示例,注释和解释。

本系列文章假设您对我们将要讨论的任何概念一无所知 ,因此我们将从头开始。 您需要做的就是在计算机上安装足够的软件来启动和运行WordPress副本,以及一个可以在其中编辑代码的编辑器。

你需要什么

首先,您需要以下工具:

在所有这些都准备好之后(我知道它看起来很多,但实际上并不需要很长的时间来设置),您需要安装上面链接的插件的副本。

完成后,我们准备开始讨论界面和单一责任原则。

定义的接口

根据软件的使用背景,当您听到“界面”一词时,您可能最终会想到用户在屏幕上实际看到的内容。 您知道: 用户界面

但是,当涉及到面向对象设计时,这根本不是我们要谈论的内容。 相反,我们在谈论类接口。 这通常可以描述为类以及它公开给其他类与之通信的公共方法。

有更正式的定义吗? 当然。 维基百科提供了一个:

在计算中,接口是共享边界,计算机系统的两个独立组件将在该边界上交换信息。

实际上,这还不错。 它足够通用,几乎可以应用于任何编程语言,而且技术上也不至于使我们无法理解。

再说一次,我们正在使用PHP。 那么,PHP手册就该主题提供了什么?

对象接口使您可以创建代码,该代码指定类必须实现的方法,而不必定义如何处理这些方法。

我认为这是一个很好的定义。 这很简单。 (就我所知)它与语言无关,并且在大多数(如果不是全部)面向对象的语言中都可以很好地工作。 该手册甚至说:

接口的定义方式与类相同,但是用interface关键字代替了class关键字,并且没有定义任何方法的内容。
接口中声明的所有方法必须是公共的。 这就是界面的本质。

如果要实现自己的接口,尤其是涉及此插件时,我们必须记住两点。 即,我们需要记住以下几点:

  1. 我们像定义类一样定义接口,但是我们使用interface关键字。
  2. 接口中定义的方法必须是公共的(而不是protectedprivate ),因为这可以保证其他类可以访问的功能。

在我们进行下一步之前,WordPress项目中的界面会是什么样? 这是我一直在从事的项目的示例:

<?php

/**
 * Defines a common set of functions that any class responsible for loading
 * stylesheets, JavaScript, or other assets should implement.
 */
interface Assets_Interface {

    public function init();
    public function enqueue();

}

上面的代码应明确其用途,尤其是考虑到位于界面上方的注释。

众所周知,WordPress可以注册和排队两种资产:样式表和JavaScript文件。

由于这两个都是资产,因此当我们为样式表管理或JavaScript管理创建类时,我们有理由将其概括为资产接口,对吗?

此外,我们知道我们想使用init方法初始化文件,以便我们可以将指定的入队功能与适当的WordPress API函数挂钩。 另外,您可能还要做其他一些工作,如果是这种情况,那么您可能要向接口添加另一个方法签名。

无论哪种情况,实现此接口的任何类都必须为以下方法提供功能。 那么实现此接口的类是什么样的呢?

这是一个非常简单的类示例,该类将样式表添加到WordPress的管理区域:

<?php

class CSS_Loader implements Assets_Interface {

    /**
     * Registers the 'enqueue' function with the proper WordPress hook for
     * registering stylesheets.
     */
    public function init() {

        add_action(
            'admin_enqueue_scripts',
            array( $this, 'enqueue' )
        );

    }

    /**
     * Defines the functionality responsible for loading the file.
     */
    public function enqueue() {

        wp_enqueue_style(
            'tutsplus-namespace-demo',
            plugins_url( 'assets/css/admin.css', dirname( __FILE__ ) ),
            array(),
            filemtime( plugin_dir_path( dirname( __FILE__ ) ) . 'assets/css/admin.css' )
        );

    }
}

现在, 如何通过PHP实例化和执行此操作超出了本教程的范围。 当我们开始重构自动装带器时,将会看到很多东西。

但是我想说明的一点是,接口定义了类必须实现的公共方法。 它没有定义实现,但是它保证了一定的功能集将存在并且可以被第三方类公开访问。

单一责任原则

谈论单一责任原则的挑战之一是,它常常被误解为以下含义:

类(或函数或例程)应该只做一件事。

但这有点误导了,不是吗? 我的意思是,即使是简单的for循环也可以做很多事情:它初始化一个值,与值进行比较,然后在循环体完成时迭代该值。

相反,该原则规定如下:

一个班级只有一个改变的理由。

由于我们中有很多开发人员利用Google来帮助我们进行日常工作,因此,我认为了解这一想法的来源很重要。 就是说,这是由众所周知的鲍勃·马丁叔叔(Robert Bob Martin)或罗伯特·马丁(Robert Martin)所著,他曾撰写过许多顶级编程书籍

一类只具有一个改变理由的观念带有很多含义,不是吗? 这是当今自动装带器想到的一个例子。

让我们回顾一下代码(我知道它不是一个类,它是一个函数,但是原理是适用的):

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

spl_autoload_register( 'tutsplus_namespace_demo_autoload' );

/**
 * Dynamically loads the class attempting to be instantiated elsewhere in the
 * plugin by looking at the $class_name parameter being passed as an argument.
 *
 * The argument should be in the form: TutsPlus_Namespace_Demo\Namespace. The
 * function will then break the fully-qualified class name into its pieces and
 * will then build a file to the path based on the namespace.
 *
 * The namespaces in this plugin map to the paths in the directory structure.
 *
 * @param string $class_name The fully-qualified name of the class to load.
 */
function tutsplus_namespace_demo_autoload( $class_name ) {

    // If the specified $class_name does not include our namespace, duck out.
    if ( false === strpos( $class_name, 'Tutsplus_Namespace_Demo' ) ) {
        return;
    }

    // Split the class name into an array to read the namespace and class.
    $file_parts = explode( '\\', $class_name );

    // Do a reverse loop through $file_parts to build the path to the file.
    $namespace = '';
    for ( $i = count( $file_parts ) - 1; $i > 0; $i-- ) {

        // Read the current component of the file part.
        $current = strtolower( $file_parts[ $i ] );
        $current = str_ireplace( '_', '-', $current );

        // If we're at the first entry, then we're at the filename.
        if ( count( $file_parts ) - 1 === $i ) {

            /* If 'interface' is contained in the parts of the file name, then
             * define the $file_name differently so that it's properly loaded.
             * Otherwise, just set the $file_name equal to that of the class
             * filename structure.
             */
            if ( strpos( strtolower( $file_parts[ count( $file_parts ) - 1 ] ), 'interface' ) ) {

                // Grab the name of the interface from its qualified name.
                $interface_name = explode( '_', $file_parts[ count( $file_parts ) - 1 ] );
                $interface_name = $interface_name[0];

                $file_name = "interface-$interface_name.php";

            } else {
                $file_name = "class-$current.php";
            }
        } else {
            $namespace = '/' . $current . $namespace;
        }
    }

    // Now build a path to the file using mapping to the file location.
    $filepath  = trailingslashit( dirname( dirname( __FILE__ ) ) . $namespace );
    $filepath .= $file_name;

    // If the file exists in the specified path, then include it.
    if ( file_exists( $filepath ) ) {
        include_once( $filepath );
    } else {
        wp_die(
            esc_html( "The file attempting to be loaded at $filepath does not exist." )
        );
    }
}

此功能中发生了很多事情。 只是从较高的角度看,我们可以看到它正在执行以下操作:

  • 它确定PHP是否正在尝试调用此函数中的代码。
  • 该函数确定我们是否正在加载接口或类。
  • 然后,自动加载器尝试包含该文件,否则将引发错误。

如果一个类只应该有一个改变的理由,那么上述单个功能可以改变的原因有三个(以上只是一个较高的层次)。 此外,代码也可以更清晰。

我不是要回避代码注释的人,但是上面的代码中发生了很多解释。 当您刚开始编写自动装带器时很好,但是当您进入像我们这样的更高级的领域时,那将无法承受更严格的体系结构。

结合在一起

在这里,接口和单一责任原则可以携手并进。

正如接口为实现者提供的功能提供一组功能签名(或合同)一样,它可以确保实现该接口的任何类都严格遵守其定义。

但这提出了一个有趣的问题:我们应该有多个接口吗? 答案是,这取决于您要创建的解决方案的性质。

就我们而言,我认为这是有道理的。

毕竟,我们希望检查传入的类名称,并确定它是接口还是类,或者是否值得抛出错误。 此外,我们正在努力确保系统的其余部分中包含正确的文件。

但这超出了本教程的主题,在编写更多代码时,我们将不得不更深入地探讨。

结论

至此,我们已经涵盖了必要的概念,以便我们可以开始重构自动装带器。 也就是说,我们将引入一个接口,确保我们的代码遵守该接口,然后确保我们的一个或多个类及其各自的方法遵循单一职责原则。

此外,我们将确保它在插件的上下文中继续正常运行,已正确记录并遵循WordPress编码标准。

同时,如果您有兴趣阅读有关WordPress上下文中的面向对象编程的更多信息,可以在我的个人资料页面上找到我以前的所有教程。 请随时在我的博客上关注我,或在Twitter上关注我,我经常谈论这两者。

与往常一样,如果您正在寻找其他实用程序来帮助您构建不断增长的WordPress工具集,或者例如要学习和精通WordPress的代码,请不要忘记看看我们在Envato Market中提供的功能

话虽如此,本系列的下一篇教程将更加实用。 也就是说,我们将编写代码,重构现有代码,并应用在本教程中学到的所有知识。 在此之前,请不要在评论中留下任何反馈。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现分页Ajax无限功能,可以按照以下步骤进行: 1. 在WordPress主题创建一个新的页面模板,命名为“ajax-pagination.php”(或者其他你喜欢的名字)。 2. 在模板需要分页的内容。 3. 在模板一个按钮或链接,用于更多内容。 4. 使用jQuery编写Ajax代码,将按钮或链接与模板的内容连接起来。 5. 在functions.php文件一个新的函数,用于处理Ajax请求。 6. 编写一个新的WordPress查询,用于获取下一页的内容。 7. 将查询结果返回给Ajax请求,并将其添到页面上。 以下是一个简单的示例代码,演示如何实现分页Ajax无限功能: 在ajax-pagination.php文件,添以下代码: ``` <div id="content"> <?php $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; $args = array( 'post_type' => 'post', 'posts_per_page' => 3, 'paged' => $paged ); $query = new WP_Query($args); if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post(); // 输出文章内容 endwhile; endif; ?> </div> <div id="load-more"> <a href="#">更多</a> </div> ``` 在JavaScript文件,添以下代码: ``` jQuery(document).ready(function($) { $('#load-more a').click(function() { var button = $(this), data = { 'action': 'load_more', 'query': loadmore_params.posts, 'page': loadmore_params.current_page }; $.ajax({ url: loadmore_params.ajaxurl, data: data, type: 'POST', beforeSend: function(xhr) { button.text('正在...'); }, success: function(data) { if (data) { button.text('更多').prev().before(data); loadmore_params.current_page++; if (loadmore_params.current_page == loadmore_params.max_page) button.remove(); } else { button.remove(); } } }); return false; }); }); ``` 在functions.php文件,添以下代码: ``` add_action('wp_ajax_load_more', 'load_more'); add_action('wp_ajax_nopriv_load_more', 'load_more'); function load_more() { $query = json_decode(stripslashes($_POST['query']), true); $query['paged'] = $_POST['page'] + 1; $posts = new WP_Query($query); if ($posts->have_posts()) { while ($posts->have_posts()) { $posts->the_post(); // 输出文章内容 } } die; } ``` 以上代码仅仅是一个示例,你需要根据自己的实际情况进行修改和调整。但是,这个示例可以帮助你了解如何使用WordPress和Ajax来实现分页Ajax无限功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值