在类中使用注册激活挂钩

时间:2017-08-10 作者:Dan Zuzevich

我正在尝试开发一个用于基本SEO目的的插件,因为我认识的很多人都不喜欢使用Yoast。我实际上刚刚启动了插件,并且正在构建当用户激活插件时显示给他们的激活消息。我在OOP和内置Wordpress功能的混合方面遇到了问题,不知道我到底出了什么错。

我唯一能做到这一点的方法是在我的主文件构造函数中创建一个新的SEO\\u Plugin\\u Activation类实例,然后在该类中调用activatePlugin方法。我觉得这没必要。我还认为,我在激活类文件中执行函数的方式也没有多大意义。但这是我现在唯一能让它工作的方法。

我不确定我所做的是因为我没有100%掌握OOP技术,还是因为我没有正确地使用Wordpress API。我按照以下顺序包括了三个代码示例:

主插件文件处理我的激活需求的类文件,这是我真正希望的

seo.php (main plugin file)

<?php
/*
... generic plugin info
*/

require_once(dirname(__FILE__) . \'/admin/class-plugin-activation.php\');

class SEO {
  function __construct() {
    $activate = new SEO_Plugin_Activation();
    $activate->activatePlugin();
  }

}

new SEO();
?>

class-plugin-activation.php

<?php
class SEO_Plugin_Activation {

  function __construct() {
    register_activation_hook(__FILE__ . \'../seo.php\', array($this, \'activatePlugin\'));
    add_action(\'admin_notices\', array($this, \'showSitemapInfo\'));
  }

  function activatePlugin() {
    set_transient(\'show_sitemap_info\', true, 5);
  }

  function showSitemapInfo() {
    if(get_transient(\'show_sitemap_info\')) {
      echo \'<div class="updated notice is-dismissible">\' .
              \'Your sitemap files can be found at these following links: \' .
            \'</div>\';
      delete_transient(\'show_sitemap_info\');
    }
  }

}
?>

seo.php(What I was hoping for)

<?php
/*
 ... blah blah blah
*/

require_once(dirname(__FILE__) . \'/admin/class-plugin-activation.php\');

class SEO {
  function __construct() {
    register_activation_hook(__FILE__, array($this, \'wp_install\'));
  }

  function wp_install() {
    $activate = new SEO_Plugin_Activation();
    // Execute some method(s) here that would take care 
    // of all of my plugin activation bootstrapping
  }

}

new SEO();
?>
我试着按照我在第三个剧本中概述的方式来做,但没有成功。截至目前,消息确实正确显示,没有错误消息。

4 个回复
最合适的回答,由SO网友:Tom J Nowell 整理而成

重读你的问题后,我想我看到了这个问题,它源于对如何register_activation_hook 这是可行的,同时还存在一些关于如何引导代码以及引导意味着什么的困惑

第1部分:register_activation_hook

此函数采用2个参数:

register\\u activation\\u hook(字符串$文件,可调用$函数)

第一个参数,$file 是主插件文件,而不是包含要运行的内容的文件。它的使用方法与plugins_url, 所以你需要__FILE__, 特别是它在根插件文件中的值和插件头。

第二个参数是一个可调用的参数,可以按预期工作,但它实际上只是使用add_action 内部

当插件被激活时,会调用action“activate\\u PLUGINNAME”挂钩。在这个钩子的名称中,PLUGINNAME被替换为插件的名称,包括可选的子目录。例如,当插件位于wp-content/plugins/sampleplugin/sample中时。php,则此挂钩的名称将变为“activate\\u sampleplugin/sample”。php’。

第2部分:引导和__FILE____FILE__ 将在不同的位置具有不同的值,并且您需要特定的值。

您还有一个问题,即引导应该组装对象图,但您没有这样做。您的所有对象都是在定义后立即创建的,或者是在彼此内部创建的,因此很难或不可能将值传递给它们。

例如,我可以编写如下插件:

plugin.php:

<?php
/**
 * Plugin Name: My Plugin
 * Version: 0.1
 */

// loading step
require_once( \'php/app.php\' );

// bootstrapping step
$app = new App( __FILE__ );

// execution step
$app->run();
我在php 子文件夹,并将它们全部加载到同一位置。PHP现在知道我的类是什么,它们的名称等等,但还没有发生任何事情。

然后我创建我的所有对象,传递它们所需的内容,在这种情况下,应用程序需要__FILE__ 所以我把它传下去。请注意,这将在内存中创建对象,但不做任何工作。插件应用程序已经准备就绪,可以投入使用,但它还处于准备阶段。

下一步可能是将这些对象管道化到一组单元测试中,但现在我要运行它们。我已经完成了引导过程,应用程序已经准备好运行,所以我触发run 方法我不需要把任何东西传给run 因为所有必要的东西都已经交给了施工人员。在run 方法,我添加了所有过滤器和挂钩。插件的所有其他部分都是在这些挂钩期间运行的。

但重要的是,我有一个定义的结构,并且我在构建/引导阶段传递必要的内容,并有一个定义的生命周期

SO网友:BenB

您可以设置一个const,该const将指定\\uu FILE\\uuuu值,并在类中的任何位置使用。

示例:

主插件文件。php

<?php
/**
* Plugin Name: Plugin with Classes
*/

define( \'PLUGIN_WITH_CLASSES__FILE__\', __FILE__ );

include( \'my-class.php\' );
我的班级。php

<?php
class myClass {
  function __construct() {
    // Run this on plugin activation
    register_activation_hook( PLUGIN_WITH_CLASSES__FILE__,  [ $this, \'create_plugin_database_table\' ] );
  }

  function create_plugin_database_table(){
    //Create DB Table ...
  }
}

new myClass();

SO网友:Chris Cox

您确实需要在插件类之外注册激活/停用/卸载挂钩,请参见kaiser\'s answer here, 这提供了一个比我能写的更好的主题概述。

如果你想把这个插件作为一个学习练习来编写,这应该涵盖你。如果你想要的只是一个运行良好的SEO插件,而不是像Yoast那样充斥着俗气的广告,我可以高度推荐SEO框架。

SO网友:Gary D

Tom McFarlin创建了一个非常广泛的plugin boilerplate (现在由Devin Vinson维护),都是用OOP编写的,您可以使用它来创建新插件,或者只是研究应用程序流来回答您的问题。我已经将它用于几个自定义插件,我必须说,它让我真正了解了OOP的一些奥秘。

结束