如何在不使用php条件语句的情况下使插件成为wp主题中必需的,当从该插件调用单个函数时?

时间:2012-01-19 作者:unfulvio

我的Wordpress主题之一需要几个第三方插件才能正常运行。

大多数时候,我都会使用以下条件语句从第三方插件调用函数

    if(function_exist(\'plugin_function\')) {
             plugin_function() // do something
    }
假设虽然我需要在我的主题的许多文件中广泛使用一个插件。。。我想避免使用许多IF条件。。。有没有合适的方法来要求在WP中安装特定的插件,或者如果在激活主题之前缺少插件,就更好地安装它们?

谢谢

4 个回复
SO网友:scribu

is_plugin_active() 它相当脆弱:当插件作者重命名主文件或用户重命名插件的目录或主文件时,它将崩溃。最好检查是否存在某种公共功能。

为了避免每次需要插件的某些功能时都必须进行检查,您可以在管理区域显示一条消息:

add_action( \'admin_notices\', \'my_theme_dependencies\' );

function my_theme_dependencies() {
  if( ! function_exists(\'plugin_function\') )
    echo \'<div class="error"><p>\' . __( \'Warning: The theme needs Plugin X to function\', \'my-theme\' ) . \'</p></div>\';
}
另一种选择是使用http://tgmpluginactivation.com/

SO网友:mrwweb

虽然这不能防止插件被禁用时主题被破坏,但我会看这篇关于"How to Display an Admin Notice for Required Themes" 插件。我从来都不习惯用一个主题来强制安装一个插件,所以这似乎是下一个最好的选择。

另一个快速思考:我从未尝试过这个,但我想知道您是否可以想出一些聪明的方法,在一个条件中容纳多个挂钩。也许您可以将不同文件中的所有条件函数分离出来,并且只在以下情况下需要它if( function_exists( \'plugin_function\' ) ) 退货true (理解为这是一个不完美的检查。

SO网友:kaiser

如果你只需要一个插件页面,那么is_plugin_active(). 如果您在外部需要它,最好将核心功能复制/粘贴到主题中,然后重用它:

if ( ! is_admin() )
{
/**
 * Check whether the plugin is active by checking the active_plugins list.
 *
 * @since 2.5.0
 *
 * @param string $plugin Base plugin path from plugins directory.
 * @return bool True, if in the active plugins list. False, not in the list.
 */
function is_plugin_active( $plugin ) {
    return in_array( $plugin, (array) get_option( \'active_plugins\', array() ) ) || is_plugin_active_for_network( $plugin );
}
}
通过双重定义函数,条件避免了任何错误。

SO网友:kaiser

Note: 这个答案只是为了让@scribu和@kaiser之间的讨论更容易。Mods:请不要删除。用户/读者:请不要投票。如果要关注讨论,请查看修订/编辑日志。如果要加入讨论,请编辑答案。如果讨论有结果,则将标记为有结果。谢谢你

场景也有不同的场景,它们的权重也不同,您可能有插件依赖关系。(这些例子只是虚构的)。“父插件”一词可以从父插件的角度与“主题”交换。

(硬)一个子插件,仅扩展现有插件的功能或更改其显示(及类似内容),因此没有父插件就无法存在示例:BuddyPress»BuddyPress FunkyCommentDisplay

  • (正常)当子插件激活时具有扩展功能的插件示例:jQueryAttachmentCarousel»jQuerySlideDeck(软)一个只添加功能的插件示例:迪士尼乐园(DisneyWonderlandTheme)>MickeysSocialLinks
  • 在下面的示例中,我试图勾勒出当您更新“other”插件并且检查不再起作用时会发生什么。

    没有BuddyPress激活,插件就不可能存在。东西完全坏了

    A.文件夹是否存在\'active_plugins\' - 是否存在Internal Link Checker Plugin 例如,它不提供公共API,也不打算进行扩展,那么我认为(作为作者)没有理由不按需或随意更改内部函数命名。所以,若有人想利用这个插件,那个么在更新时,东西就会被破坏(取决于捆绑的功能和紧密程度)。文件名也是如此。我没有真正的理由(除了插件在更新时会被停用)不更改文件名。唯一阻止我更改文件夹名称的是更新检查;如果文件名位于官方回购协议中,则通知会针对文件名运行。

    所以我想说,从最薄弱(易于更改)到最困难(很多人反对更改)的(父)插件部分应该是:

    函数»主文件名»文件夹

    当我说功能检查比使用is_plugin_active() 我假设所讨论的函数是插件作者明确鼓励的函数。这方面的最终例子是wp_pagenavi() WP PageNavi插件提供的模板标记。

    定义依赖关系的困难在于,没有标准的方法来唯一地标识不涉及文件名的插件。

    关于该主题的更多想法:

    http://wordpress.org/support/topic/plugin-plugin-dependencies-unreliable-plugin-namingidentifying-scheme

    <人力资源>

    I guess we can so far sum it up in three points:

    <我们讨论了一些稍有不同的主题,我们同意,没有什么可靠的方法可以绕过我所认为的主题。从你对这个问题的理解来看,你提供了一种有效的方法,这是我能想到的(到目前为止)最聪明的方法,我已经在一些插件中看到了:

    // inside the plugin file:
    add_action( \'plugin_custom_hook\', \'plugin_trigger\' );
    // inside some template:
    do_action( \'plugin_custom_hook\' );
    
    不用想太多细节,但我想你可以把你的通知挂在“所有”过滤器上,然后检查内部current filter 如果是在shutdown

    使用挂钩对于“正常”和“弱”依赖关系都很有效。唯一的缺点是您仍然需要使用function_exists()is_plugin_active() 如果不满足依赖项,则要停止。IMO.使用“all”过滤器来实现这一点太贵了。

    @scibu这是针对“你的”主题。(我已经放弃谈论我的)。:)

    因此,基本上,如果您需要依赖项,并且您有一个很好的作者,那么他可以提供一个钩子来代替模板标记。因为插件只有在钩子存在的情况下才会钩住它,或者什么都不做。另一方面,当插件不存在时,您不会出现错误。

    这里有一个困难的部分(或更多的问题):要写一个管理员通知,通知用户“您需要安装»DisneyWonderLinks«”,您可以检查array_keys( $GLOBALS[\'wp_filter\'][\'template_tag_like_hook\'] ). 我不确定这是否可行,但afaik阵列应该可以在两侧(公共/管理)访问。

    那是行不通的。回调注册到挂钩并不意味着挂钩会在预期的时候触发。唯一需要做的就是使用“关机”挂钩,您之前提到过:

    add_action( \'shutdown\', function() {
      if ( !did_action( \'template_tag_like_hook\' ) )
        echo \'Problem.\';
    } );
    
    当然,在</html> 标签,位于前端(因为这是通常使用模板标签的地方),这没有多大用处。

    您可以尝试将消息存储在wp\\u选项中,然后将其显示在管理区域,但这将打开一个全新的蠕虫:失效、缓存插件等。

    结束

    相关推荐

    将目录路径传递给plugins_url()安全吗?

    plugins_url() 函数接受插件slug或文件路径来构建URL。我有以下目录结构:/wp-content/mu-plugins/someplugin/css/file.css /wp-content/mu-plugins/someplugin/includes/file.php 我需要建立URL到file.css 在里面file.php. 我不能通过__FILE__ 因为这将是一个层次太深。plugins_url(\'css/file.css\', __FILE__ )