问题描述

这不是一个关于如何构建 WordPress 插件的问题。相反,如果有的话,指南可以应用于如何组合任何插件的文件架构。

一些其他编程语言或库具有非常受控的组织目录和文件的方式。有时这是恼人的,突出了 PHP 提供的自由,但是在 flip-side 上,WordPress 插件以其作者确定的任何方式放在一起。

没有一个正确的答案,但我希望改进我和其他人如何构建插件,使他们对其他开发人员更加友善,更容易调试,更容易导航,并可能更有效率。

最后一个问题:你认为组织插件最好的方法是什么?

以下是几个示例结构,但绝对不是详尽的列表。随意添加您自己的建议。

假设默认结构

  • / wp-content

    • /插件

      • / my-plugin

        •  my-plugin.php

模型视图控制器 (MVC) 方法

  • / wp-content

    • /插件

      • / my-plugin

        • /控制器

          •  Controller.php
        • /模型

          •  Model.php
        • /视图

          •  view.php
        •  my-plugin.php

MVC 的三个部分:

  • 该模型与数据库交互,查询和保存数据,并包含逻辑。
  • 控制器将包含视图将使用的模板标签和功能。
  • 视图负责显示由控制器构造的模型提供的数据。

按类型方式组织

  • / wp-content

    • /插件

      • / my-plugin

        • /管理员

          •  admin.php
        • /资产

          •  css/
          •  images/
        • /班

          •  my-class.php
        • /郎

          •  my-es_ES.mo
        • /模板

          •  my-template.php
        • /部件

          •  my-widget.php
        •  my-plugin.php

松散组织的方法

  • / wp-content

    • /插件

      • / my-plugin

        •  css/
        •  images/
        •  js/
        •  my-admin.php
        •  my-class.php
        •  my-template.php
        •  my-widget.php
        •  my-plugin.php

最佳解决方案

请注意,插件都是 WP 标准的”controllers” 。

这取决于插件应该做什么,但在任何情况下,我尽量将屏幕输出与 PHP 代码分开。

这里有一种方法可以轻松实现 – 首先,定义一个加载模板的函数:

function my_plugin_load_template(array $_vars){

  // you cannot let locate_template to load your template
  // because WP devs made sure you can't pass
  // variables to your template :(
  $_template = locate_template('my_plugin', false, false);

  // use the default one if the theme doesn't have it
  if(!_$template)
    $_template = 'views/template.php';

  // load it
  extract($_vars);
  require $template;
}

现在,如果插件使用小工具来显示数据:

class Your_Widget extends WP_Widget{

  ...
  public function widget($args, $instance){

    $title = apply_filters('widget_title', $instance['title'], $instance, $this->id_base);

    // this widget shows the last 5 "movies"
    $posts = new WP_Query(array('posts_per_page' => 5, 'post_type' => 'movie'));

    if($title)
      print $before_title . $title . $after_title;

    // here we rely on the template to display the data on the screen
    my_plugin_load_template(array(

      // variables you wish to expose in the template
     'posts'    => $posts,
    ));

    print $before_widget;
  }
  ...

}

模板:

<?php while($posts->have_posts()): $posts->the_post(); ?>

<p><?php the_title(); ?></p>

<?php endwhile; ?>

文件:

/plugins/my_plugin/plugin.php           <-- just hooks
/plugins/my_plugin/widget.php           <-- widget class, if you have a widget
/themes/twentyten/my_plugin.php         <-- template
/plugins/my_plugin/views/template.php   <-- fallback template

你把 CSS,JS,图像放在哪里,或者如何设计钩子的容器是不那么重要的。这是我个人喜好的问题。

次佳解决方案

IMHO,最简单,最强大,最可维护的路由是使用 MVC 结构,WP MVC 旨在使 MVC 插件变得非常简单 (我有点偏见,但…) 。使用 WP MVC,您只需使模型,视图和控制器,以及其他一切在幕后处理。

可以为公共和管理部分分开控制器和视图,整个框架利用了许多 WordPress 的本机功能。文件结构和大部分功能与最受欢迎的 MVC 框架 (Rails,CakePHP 等) 完全相同。

更多信息和教程可以在这里找到:

第三种解决方案

这取决于插件。这是我几乎每个插件的基本结构:

my-plugin/
    inc/
        Any additional plugin-specific PHP files go here
    lib/
        Library classes, css, js, and other files that I use with many
        plugins go here
    css/
    js/
    images/
    lang/
        Translation files
    my-plugin.php
    readme.txt

 This 将会在 lib 文件夹中出现。

如果它是特别复杂的插件,具有很多管理区域功能,我将添加一个 admin 文件夹来包含所有这些 PHP 文件。如果插件执行类似替换的 theme files,也可能有一个 templatetheme 文件夹。

因此,目录结构可能如下所示:

my-plugin/
    inc/
    lib/
    admin/
    templates/
    css/
    js/
    images/
    lang/
    my-plugin.php
    readme.txt

第四种方案

我们正在使用所有方法的混合。首先,我们在我们的插件中使用了 Zend Framework 1.11,因此由于自动加载机制,我们不得不为类文件使用类似的结构。

我们的核心插件 (所有我们的插件作为基础使用) 的结构看起来类似于:

webeo-core/
    css/
    images/
    js/
    languages/
    lib/
        Webeo/
            Core.php
        Zend/
            /** ZF files **/
        Loader.php
    views/
    readme.txt
    uninstall.php
    webeo-core.php
  1. WordPress 在插件根文件夹中调用 webeo-core.php 文件。
  2. 在这个文件中,我们将设置 PHP 包含的路径并注册插件的激活和停用钩子。
  3. 我们还在这个文件中有一个 Webeo_CoreLoader 类,它设置一些插件常量,初始化类自动装载器,并调用 lib/Webeo 文件夹内的 Core.php 类的安装方法。它运行在 plugins_loaded 动作钩子上,优先级为 9
  4. Core.php 类是我们的插件引导文件。该名称基于插件名称。

如您所见,我们在 lib 文件夹中有一个子目录,用于所有供应商的软件包 (WebeoZend) 。供应商内的所有子包都由模块本身构成。对于新的 Mail Settings 管理表单,我们将具有以下结构:

webeo-core/
    ...
    lib/
        Webeo/
            Form/
                Admin/
                    MailSettings.php
                Admin.php
            Core.php
            Form.php

我们的 sub-plugins 具有相同的结构,但有一个例外。由于在自动加载事件期间解决命名冲突,我们在供应商文件夹内更深入一级。我们还在 plugins_loaded 钩子的优先级 10 中调用了插件类型为 E.g. Faq.php 的插件。

webeo-faq/ (uses/extends webeo-core)
    css/
    images/
    js/
    languages/
    lib/
        Webeo/
            Faq/
                Faq.php
                /** all plugin relevant class files **/
    views/
    readme.txt
    uninstall.php
    webeo-faq.php

我可能会将 lib 文件夹重命名为 vendors,并将所有公用文件夹 (css,images,js,languages) 移动到下一个版本中名为 public 的文件夹。

第五种方案

像许多这里已经回答了这真的取决于插件应该做什么,但这里是我的基础结构:

my-plugin/
    admin/
        holds all back-end administrative files
        js/
            holds all back-end JavaScript files
        css/
            holds all back-end CSS files
        images/
            holds all back-end images
        admin_file_1.php        back-end functionality file
        admin_file_2.php        another back-end functionality file
    js/
        holds all front end JavaScript files
    css/
        holds all fronted CSS files
    inc/
        holds all helper classes
    lang/
        holds all translation files
    images/
        holds all fronted images
    my-plugin.php               main plugin file with plugin meta, mostly includes,action and filter hooks
    readme.txt
    changelog.txt
    license.txt

第六种方案

我局限于以下插件布局,但是它通常会根据插件的要求而改变。

wp-content/
    plugins/
        my-plugin/
            inc/
                Specific files for only this plugin
                admin/
                    Files for dealing with administrative tasks
            lib/
                Library/helper classes go here
            css/
                CSS files for the plugin
            js/
                JS files
            images/
                Images for my plugin
            lang/
                Translation files
        plugin.php
            This is the main file that calls/includes other files
        README
            I normally put the license details in here in addition to helpful information

我还没有创建一个需要 MVC 风格架构的 WordPress 插件,但是如果我要这样做,我会用一个单独的 MVC 目录来排列,该目录本身包含 views / controllers / models 。

第七种方案

我的逻辑,插件越大,我使用的结构越多。对于大的插件,我倾向于使用 MVC 。我用这个作为起点,跳过什么是不需要的。

controller/
    frontend.php
    wp-admin.php
    widget1.php
    widget2.php
model/
    standard-wp-tables.php // if needed split it up
    custom-tabel1.php
    custom-tabel2.php
view/
    helper.php
    frontend/
        files...php
    wp-admin/
        files...php
    widget1/
        file...php
    widget2/
        file...php
css/
js/
image/
library/  //php only, mostly for Zend Framework, again if needed
constants.php //tend to use it often
plugin.php //init file
install-unistall.php  //only on big plugins

第八种方案

所有我的插件都遵循这个结构,这似乎与其他大多数开发人员的工作非常相似:

plugin-folder/
    admin/
        css/
            images/
        js/
    core/
    css/
        images/
    js/
    languages/
    library/
    templates/
    plugin-folder.php
    readme.txt
    changelog.txt
    license.txt

然后,plugin-folder.php 通常是从核心/文件夹加载所有需要的文件的类。最常见的是 init 或 plugins_loaded 钩子。

我曾经在我的所有文件前缀,但正如上面 @kaiser 所说,这真的是多余的,我最近决定从任何未来的插件中删除它。

库/文件夹保存插件可能依赖的所有外部帮助程序库。

根据插件,插件根目录中可能还有一个 uninstall.php 文件。大部分时间是通过 register_uninstall_hook() 来处理的。

显然,一些插件可能不需要任何管理员文件或模板等,但上面的结构适用于我。最后你只需要找到一个适合你的结构,然后坚持下去。

我也有一个启动器插件,基于上面的结构,我用作所有我的插件的起点。所有我需要做的是做一个搜索/替换功能/类前缀和关闭我去。当我仍然是我的文件前缀,这是一个额外的步骤,我不得不做 (和相当烦人的),但现在我只需要重命名插件文件夹和主要的插件文件。

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。