从该插件调用单个函数时,如何不使用php条件语句而使wp主题中需要插件?


9

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

大多数时候,我曾经使用条件语句从第三方插件调用函数

    if(function_exist('plugin_function')) {
             plugin_function() // do something
    }

假设尽管我需要通过主题的多个文件广泛使用一个插件...我想避免使用许多IF条件...是否有适当的方法要求将某些特定的插件安装在WP中,甚至更好地安装它们如果在激活主题之前缺少它们?

谢谢

Answers:


7

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/的东西


如果插件作者更改了您向其询问的函数名称function_exists,那么普通用户将仅收到一条消息,即他尚未安装另一个插件依赖的插件。问题是,用户实际上安装该插件,然后想知道为什么它不起作用。哦,我不会为此而投票。
kaiser 2012年

如果您关心投票,那么您应该投票给Q本身,因为它是一个很好的选择。
kaiser 2012年

如果插件作者更改了函数名称,那么与更改文件名相比,他将收到更多用户的投诉。
scribu 2012年

我不赞成你的回答,因为它不能解决问题,IMO。还是您希望我在没有提供任何解释的情况下暗中投票?
scribu 2012年

我只是在谈论低票,而不是评论。评论本身还可以,因为这个主题需要讨论。我将添加另一个答案,因为我的想法超出了评论的范围。请只编辑答案,这样我们就可以将讨论结果保留在修订本中,以供大家遵循。谢谢。
kaiser 2012年

1

虽然这并不能防止在禁用插件时破坏主题,但我会看一下有关“如何显示所需主题的管理通知”插件的文章。我从来没有对主题强制安装插件的想法感到满意,因此这似乎是下一个最佳选择。

另一个很快的想法:我从未尝试过这种方法,但是我想知道您是否可以找到一种巧妙的方法来在单个条件中容纳多个钩子。也许您可以将所有条件函数放在一个不同的文件中,并且仅在if( function_exists( 'plugin_function' ) )返回时才需要它true(但要了解这是不完善的检查。)


0

如果只需要一个插件页面,则有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 );
}
}

有条件的避免了双重定义函数的任何错误。


这并不能真正回答问题。它仅仅取代if(function_exist('plugin_function'))if(is_plugin_active('plugin-file.php'))
scribu

0

注意:此答案仅用于简化@scribu和@kaiser之间的讨论。Mods:请不要删除。用户/读者:请不要投票。如果要关注讨论,请查看修订/编辑日志。如果要加入讨论,请编辑答案。如果讨论有结果,那么它将被标记为这样。谢谢。


情境

在某些情况下,权重也有所不同,您可能会有插件依赖性。(这些示例只是虚构的)。从父母的角度来看,“(父母)插件”一词可以与“主题”交换。

  1. (硬)子插件,仅扩展功能或更改现有插件的显示(或类似显示),因此如果没有父插件,子插件将不存在。示例: BuddyPress»BuddyPress-FunkyCommentDisplay
  2. (正常)激活子插件时具有扩展功能的插件。示例: jQueryAttachmentCarousel»jQuerySlideDeck
  3. (软)仅添加功能的插件。示例:迪士尼乐园主题»MickeysSocialLinks

在下面的内容中,我尝试概述当您更新“其他”插件并且检查不再起作用时会发生什么。

  • 广告1)如果未激活BuddyPress,该插件将不存在»插件已完全损坏。
  • 广告2)该插件无法提供从“轮播”切换到SlideDeck的选项»有线显示(我假设样式已修改为SlideDeck)。
  • 广告3)MickeysSocialLinks消失。

校验

如果您想知道插件是否处于活动状态,可以检查三种可能的恕我直言:

  • 答:文件夹是否存在?
  • B.主文件-选项'active_plugins'- 是否存在?
  • C.是否存在特定功能?

如果现在以我的内部链接检查器插件为例,它不提供公共API并且不打算扩展,那么我将没有理由(作为作者)不按需或随便更改内部函数命名。因此,如果有人尝试搭载此插件,则更新时东西就会断裂(取决于功能和捆绑的紧密程度)。文件名也是如此。我没有真正的理由(除了该插件会在更新时停用),而不更改文件名。唯一使我无法更改文件夹名称的事情是,更新检查和通知将针对文件名运行-如果该文件位于官方存储库中。

因此,我想说(父)插件从最弱(易于更改)到最困难(很多反对更改)的部分是:

功能»主文件名»文件夹


当我说一个函数检查比使用它不那么脆弱时,is_plugin_active()我认为问题函数是插件作者明确鼓励的。最终的示例是wp_pagenavi()WP-PageNavi插件提供的模板标签。

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

关于此主题的更多想法:

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


我想到目前为止,我们可以概括为三点:

  • 我们讨论了略有不同的主题
  • 我们同意,没有防弹方法可以解决我认为的主题
  • 根据您对问题的理解,您提供了有效的解决方法

我可以考虑的(到目前为止)最聪明的方法,已经在一些(太少了)插件中看到了:

// inside the plugin file:
add_action( 'plugin_custom_hook', 'plugin_trigger' );
// inside some template:
do_action( 'plugin_custom_hook' );

无需过多考虑,但我想您可以将通知挂接到“ all”过滤器的检查中,并检查当前过滤器内部是否在shutdown挂机时触发了它...?


对于“正常”和“弱”依赖项,使用钩子效果很好。唯一的缺点是,如果不满足依赖项,您仍将需要使用function_exists()is_plugin_active()停止。为此,使用“全部”过滤器将过于昂贵。

@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_options中,然后在管理区域中显示该消息,但这将打开一堆全新的蠕虫病毒:无效,缓存插件等。


记录下来,这是使用网站功能的一种非常不合常规的方式。它使我想起c2.com/cgi/wiki
scribu

是的。但是我不知道如何在不向以后的读者隐藏的情况下继续讨论。
kaiser 2012年

我不会意识到发布问题会引起很大的讨论:)但这确实很有趣,我感谢您付出的时间和精力,提出建议并进行一些深思熟虑的辩论。我认为scribu(是众多建议中的一种)使用TGM激活类的建议至少可以从实际角度为我的答案提供解决方案,我将对此进行研究。但是,我仍在关注整个讨论,因为在某些情况下建议使用的其他方法也很有意义,并且让我阅读非常有趣,谢谢!
unfulvio
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.