任何事情都需要实践,不能纸上谈兵,下面我们来聊聊关于Wordpress插件开发实践。以下是一些帮助您组织代码的最佳实践,以便它可以与 WordPress 核心和其他 WordPress 插件很好地配合使用。
当您的插件与另一个插件使用相同的变量、函数或类的名称时,就会发生命名冲突。
幸运的是,您可以使用以下方法避免命名冲突。
默认情况下,所有变量、函数和类都定义在全局命名空间中,这意味着你的插件可以覆盖其他插件设置的变量、函数和类,反之亦然。在函数或类内部定义的变量不受影响。
所有全局可访问的代码都应以唯一标识符作为前缀。前缀可以防止与其他插件冲突,并防止它们覆盖你的变量以及意外调用你的函数和类。
为了避免与其他插件冲突,您的前缀至少应包含 4 个字母,但我们建议使用 5 个字母。您应该避免使用常见的英文单词,而应选择一些与您的插件相关的专有名称。仅在 WordPress.org 上,我们就托管了数万个插件。我们的服务器之外还有数十万个插件。您肯定会遇到冲突。
一个好方法是使用前缀。例如,如果你的插件名为“Easy Custom Post Types”,那么你可以使用如下名称:
function ecpt_save_post() define( ‘ECPT_LICENSE’, true ); class ECPT_Admin{} namespace EasyCustomPostTypes; update_option( 'ecpt_settings', $settings );
由于您正在编写WordPress项目的代码,因此您必须避免使用可能与 WordPress 核心冲突的前缀。这些前缀包括但不限于:(__双下划线)、wp_、WordPress或_(单下划线)。
如果您正在为“子”插件(例如 WooCommece 扩展)编写代码,您同样需要避免使用任何常规/通用前缀(即 Woo、WooCommerce)。
您可以在类或命名空间中使用它们,但不能作为独立的函数/命名空间/类。
如果您使用_n()或__()进行翻译,那没问题。我们只讨论您为插件创建的功能,而不是 WordPress 的核心功能。事实上,正是这些核心功能才导致您不应该在自己的插件中使用这些前缀!您肯定不想让 WordPress 的用户感到困扰。
记住:好的前缀名称必须是独一无二的,并且与你的插件相区别。这将有助于你和其他人进行调试,并避免冲突。
必须加前缀的代码包括:
函数(除非有命名空间)
类、接口和特征(除非有命名空间)
命名空间
全局变量
选项和瞬态
PHP 提供了许多函数来验证变量、函数、类和常量的存在。如果实体存在,这些函数都会返回 true。
变量: isset() (包括数组、对象等)
函数: function_exists()
类: class_exists()
常量: defined()
请记住,(!function_exists(‘NAME ‘)) {
绕过所有函数和类听起来是个好主意,直到你意识到其中的致命缺陷。如果其他程序有同名函数,并且它们的代码先加载,你的插件就会崩溃。使用 if-exists 来替换/覆盖函数或类应该只用于共享库。
// Create a function called "wporg_init" if it doesn't already exist if ( ! function_exists( 'wporg_init' ) ) { function wporg_init() { register_setting( 'wporg_settings', 'wporg_option_foo' ); } } // Create a function called "wporg_get_foo" if it doesn't already exist if ( ! function_exists( 'wporg_get_foo' ) ) { function wporg_get_foo() { return get_option( 'wporg_option_foo' ); } }
解决命名冲突问题的一个更简单的方法是使用一个类作为插件的代码。
您仍然需要检查您想要的类的名称是否已被使用,但其余部分将由 PHP 处理。
if ( ! class_exists( 'WPOrg_Plugin' ) ) { class WPOrg_Plugin { public static function init() { register_setting( 'wporg_settings', 'wporg_option_foo' ); } public static function get_foo() { return get_option( 'wporg_option_foo' ); } } WPOrg_Plugin::init(); WPOrg_Plugin::get_foo(); }
插件目录的根目录应该包含你的plugin-name.php文件以及(可选)uninstall.php文件。所有其他文件应尽可能组织到子文件夹中。
清晰的文件夹结构可以帮助您和其他使用您的插件的人将类似的文件保存在一起。
以下是供参考的示例文件夹结构:
/plugin-name plugin-name.php uninstall.php /languages /includes /admin /js /css /images /public /js /css /images
您为插件选择的架构或代码组织可能取决于插件的大小。
对于与 WordPress 核心、主题或其他插件交互有限的小型、单一用途的插件,设计复杂的类没有什么好处;除非您知道该插件以后会大大扩展。
对于包含大量代码的大型插件,请从类开始考虑。将样式和脚本文件,甚至与构建相关的文件分开。这将有助于代码组织和插件的长期维护。
将管理员代码与公共代码分开很有帮助。使用条件is_admin()。您仍然必须执行权限检查,因为这并不表明用户已通过身份验证或拥有管理员级别的访问权限。请参阅检查用户权限。
例如:
if ( is_admin() ) { // we are in admin mode require_once __DIR__ . '/admin/plugin-name-admin.php'; }
ABSPATH出于安全考虑,如果未定义全局变量,则建议禁止访问。这仅适用于包含类或函数定义之外代码的文件,例如主插件文件。
您可以通过在文件顶部包含此代码来实现这一点:
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
虽然存在多种可能的架构模式,但大致可以分为三种:
单个插件文件,包含函数
单个插件文件,包含一个类、实例化对象和可选函数
主插件文件,然后是一个或多个类文件
上述更复杂的代码组织的具体实现已经写成教程和幻灯片:
Slash – 单例、加载器、动作、屏幕、处理程序
在 WordPress 插件中实现 MVC 模式
与其每次都从头开始编写新插件,不如先从样板开始。使用样板的一个好处是可以保证插件之间的一致性。如果您使用别人熟悉的样板,样板也能让他们更轻松地为您的代码做出贡献。
这些也作为不同但可比较的架构的进一步例子。
WordPress 插件样板:WordPress 插件开发的基础,旨在为构建插件提供清晰一致的指南。
WordPress 插件引导程序:使用 Grunt、Compass、GIT 和 SVN 开发 WordPress 插件的基本引导程序。
WP Skeleton 插件:专注于单元测试和使用作曲家进行开发的 Skeleton 插件。
WP CLI Scaffold:WP CLI 的 Scaffold 命令创建一个带有 CI 配置文件等选项的骨架插件
当然,您可以采用这些和其他方面的不同方面来创建您自己的自定义样板。