Loading...
Loading...
Compare original and translation side by side
plugin-project-name/ # Root project directory
├── composer.json # Dev dependencies (phpcs, phpunit, phpstan)
├── phpcs.xml # WordPress-Extra ruleset
├── phpcs_sec.xml # Security-specific checks
├── phpstan.neon.dist # Static analysis config
├── phpunit.xml.dist # PHPUnit configuration
├── tests/ # Tests at root level
│ ├── bootstrap.php # PHPUnit bootstrap
│ ├── Unit/ # Unit tests
│ └── Integration/ # Integration tests
├── vendor/ # Composer dev dependencies
└── plugin-name/ # Actual plugin directory
├── plugin-name.php # Main plugin file
├── composer.json # Plugin-specific dependencies
├── src/ # Namespaced source code
│ ├── Core/
│ │ └── Main.php # Main initialization class
│ ├── Admin/
│ │ └── AdminPage.php
│ ├── Data/
│ └── REST/
│ └── DiagnosticsEndpoint.php
├── vendor/ # Plugin dependencies
├── languages/ # Translation files
└── README.mdplugin-project-name/ # 根项目目录
├── composer.json # 开发依赖(phpcs, phpunit, phpstan)
├── phpcs.xml # WordPress-Extra规则集
├── phpcs_sec.xml # 安全专项检查
├── phpstan.neon.dist # 静态分析配置
├── phpunit.xml.dist # PHPUnit配置
├── tests/ # 根级别的测试目录
│ ├── bootstrap.php # PHPUnit引导文件
│ ├── Unit/ # 单元测试
│ └── Integration/ # 集成测试
├── vendor/ # Composer开发依赖
└── plugin-name/ # 实际插件目录
├── plugin-name.php # 主插件文件
├── composer.json # 插件专属依赖
├── src/ # 命名空间源代码
│ ├── Core/
│ │ └── Main.php # 主初始化类
│ ├── Admin/
│ │ └── AdminPage.php
│ ├── Data/
│ └── REST/
│ └── DiagnosticsEndpoint.php
├── vendor/ # 插件依赖
├── languages/ # 翻译文件
└── README.mdfullworks-support-diagnostics/src/fullworks-support-diagnostics/src/<?php
/**
* Plugin Name: Your Plugin Name
* Description: Brief description
* Version: 1.0.0
* Author: Your Name
* License: GPL-2.0+
* Text Domain: plugin-text-domain
* Requires at least: 5.8
* Requires PHP: 7.4
*/
// Prevent direct access
if (!defined('WPINC')) {
die;
}
// Define plugin constants
define('PREFIX_PLUGIN_VERSION', '1.0.0');
define('PREFIX_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('PREFIX_PLUGIN_URL', plugin_dir_url(__FILE__));
// Load Composer autoloader
require_once PREFIX_PLUGIN_DIR . 'vendor/autoload.php';
// Initialize the plugin
function prefix_initialize_plugin() {
new \Vendor\PluginName\Core\Main();
}
add_action('plugins_loaded', 'prefix_initialize_plugin', 5);<?php
/**
* Plugin Name: 你的插件名称
* Description: 简要描述
* Version: 1.0.0
* Author: 你的名字
* License: GPL-2.0+
* Text Domain: plugin-text-domain
* Requires at least: 5.8
* Requires PHP: 7.4
*/
// 禁止直接访问
if (!defined('WPINC')) {
die;
}
// 定义插件常量
define('PREFIX_PLUGIN_VERSION', '1.0.0');
define('PREFIX_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('PREFIX_PLUGIN_URL', plugin_dir_url(__FILE__));
// 加载Composer自动加载器
require_once PREFIX_PLUGIN_DIR . 'vendor/autoload.php';
// 初始化插件
function prefix_initialize_plugin() {
new \Vendor\PluginName\Core\Main();
}
add_action('plugins_loaded', 'prefix_initialize_plugin', 5);<?php
namespace Vendor\PluginName\Core;
use Vendor\PluginName\Admin\AdminPage;
use Vendor\PluginName\REST\DiagnosticsEndpoint;
class Main {
const VERSION = '1.0.0';
const OPTION_NAME = 'prefix_settings';
private $settings;
private $admin_page;
public function __construct() {
$this->settings = get_option(self::OPTION_NAME, []);
$this->init_components();
$this->setup_hooks();
}
private function init_components() {
$this->admin_page = new AdminPage($this->settings);
}
private function setup_hooks() {
add_action('admin_menu', [$this->admin_page, 'add_admin_menu']);
}
}<?php
namespace Vendor\PluginName\Core;
use Vendor\PluginName\Admin\AdminPage;
use Vendor\PluginName\REST\DiagnosticsEndpoint;
class Main {
const VERSION = '1.0.0';
const OPTION_NAME = 'prefix_settings';
private $settings;
private $admin_page;
public function __construct() {
$this->settings = get_option(self::OPTION_NAME, []);
$this->init_components();
$this->setup_hooks();
}
private function init_components() {
$this->admin_page = new AdminPage($this->settings);
}
private function setup_hooks() {
add_action('admin_menu', [$this->admin_page, 'add_admin_menu']);
}
}Vendor\PluginName\Feature\ClassNameprefix_function_name()ClassName.phpif ( true === $value )if ( condition ) {Vendor\PluginName\Feature\ClassNameprefix_function_name()ClassName.phpif ( true === $value )if ( condition ) {<rule ref="WordPress-Extra">
<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase"/>
<exclude name="Generic.WhiteSpace"/>
<exclude name="PEAR.NamingConventions"/>
<exclude name="Universal.Files.SeparateFunctionsFromOO"/>
<exclude name="Universal.Operators.StrictComparisons"/>
</rule>composer phpcs # Full WPCS check
composer check # PHP compatibility + WPCS
composer phpcbf # Auto-fix issues<rule ref="WordPress-Extra">
<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase"/>
<exclude name="Generic.WhiteSpace"/>
<exclude name="PEAR.NamingConventions"/>
<exclude name="Universal.Files.SeparateFunctionsFromOO"/>
<exclude name="Universal.Operators.StrictComparisons"/>
</rule>composer phpcs # 完整WPCS检查
composer check # PHP兼容性检查 + WPCS检查
composer phpcbf # 自动修复问题sanitize_text_field()sanitize_email()sanitize_url()absint()intval()wp_kses()wp_kses_post()sanitize_text_field()sanitize_email()sanitize_url()absint()intval()wp_kses()wp_kses_post()esc_html()esc_attr()esc_url()esc_js()wp_kses_post()esc_html()esc_attr()esc_url()esc_js()wp_kses_post()// Creating nonce
wp_nonce_field( 'action_name', 'nonce_field_name' );
// Verifying nonce
if ( ! isset( $_POST['nonce_field_name'] ) ||
! wp_verify_nonce( $_POST['nonce_field_name'], 'action_name' ) ) {
wp_die( 'Security check failed' );
}// 创建nonce
wp_nonce_field( 'action_name', 'nonce_field_name' );
// 验证nonce
if ( ! isset( $_POST['nonce_field_name'] ) ||
! wp_verify_nonce( $_POST['nonce_field_name'], 'action_name' ) ) {
wp_die( '安全检查失败' );
}if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Unauthorized access' );
}if ( ! current_user_can( 'manage_options' ) ) {
wp_die( '未授权访问' );
}$wpdb->prepare()$wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}table WHERE id = %d AND name = %s",
$id,
$name
) );$wpdb->prepare()$wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}table WHERE id = %d AND name = %s",
$id,
$name
) );// Use unique prefixes to avoid conflicts
add_action( 'init', 'prefix_init_function' );
add_filter( 'the_content', 'prefix_modify_content', 10, 1 );
// Always specify priority (default: 10) and accepted args
add_action( 'save_post', 'prefix_save_post_action', 10, 2 );
// Remove actions/filters when needed
remove_action( 'init', 'prefix_init_function' );// 使用唯一前缀避免冲突
add_action( 'init', 'prefix_init_function' );
add_filter( 'the_content', 'prefix_modify_content', 10, 1 );
// 始终指定优先级(默认:10)和接受的参数数量
add_action( 'save_post', 'prefix_save_post_action', 10, 2 );
// 必要时移除动作/过滤器
remove_action( 'init', 'prefix_init_function' );plugins_loadedinitadmin_initwp_enqueue_scriptsadmin_enqueue_scriptsplugins_loadedinitadmin_initwp_enqueue_scriptsadmin_enqueue_scripts// Get option with default
$value = get_option( 'prefix_option_name', 'default_value' );
// Update option
update_option( 'prefix_option_name', $value );
// Autoload consideration
add_option( 'prefix_option_name', $value, '', 'no' ); // Don't autoload// 获取选项并设置默认值
$value = get_option( 'prefix_option_name', 'default_value' );
// 更新选项
update_option( 'prefix_option_name', $value );
// 自动加载设置
add_option( 'prefix_option_name', $value, '', 'no' ); // 不自动加载$wpdb->prefixdbDelta()$wpdb->prefixdbDelta()// Text domain should match plugin slug
__( 'Text to translate', 'plugin-text-domain' );
_e( 'Text to echo', 'plugin-text-domain' );
esc_html__( 'Text to translate and escape', 'plugin-text-domain' );
esc_html_e( 'Text to echo and escape', 'plugin-text-domain' );
// With variables
sprintf(
/* translators: %s: user name */
__( 'Hello, %s!', 'plugin-text-domain' ),
$user_name
);// 文本域需与插件slug匹配
__( '待翻译文本', 'plugin-text-domain' );
_e( '直接输出的待翻译文本', 'plugin-text-domain' );
esc_html__( '待翻译并转义的文本', 'plugin-text-domain' );
esc_html_e( '直接输出的待翻译并转义的文本', 'plugin-text-domain' );
// 包含变量的情况
sprintf(
/* translators: %s: 用户名 */
__( '你好,%s!', 'plugin-text-domain' ),
$user_name
);add_action( 'rest_api_init', 'prefix_register_routes' );
function prefix_register_routes() {
register_rest_route( 'plugin/v1', '/endpoint', array(
'methods' => 'POST',
'callback' => 'prefix_endpoint_callback',
'permission_callback' => 'prefix_permission_check',
) );
}add_action( 'rest_api_init', 'prefix_register_routes' );
function prefix_register_routes() {
register_rest_route( 'plugin/v1', '/endpoint', array(
'methods' => 'POST',
'callback' => 'prefix_endpoint_callback',
'permission_callback' => 'prefix_permission_check',
) );
}// Use WP_Error for error handling
if ( is_wp_error( $result ) ) {
return $result;
}
// Create errors
return new WP_Error( 'error_code', __( 'Error message', 'text-domain' ) );// 使用WP_Error进行错误处理
if ( is_wp_error( $result ) ) {
return $result;
}
// 创建错误
return new WP_Error( 'error_code', __( '错误信息', 'text-domain' ) );set_transient()get_transient()wp_cache_*set_transient()get_transient()wp_cache_*@wordpress/env@wordpress/envundefinedundefinedundefinedundefinedundefinedundefinedundefinedundefinedphpunit.xml.disttests/Unit/tests/Integration/phpunit.xml.disttests/Unit/tests/Integration/tests/bootstrap.phpWP_PHPUNIT__TESTS_CONFIGtests/bootstrap.phpWP_PHPUNIT__TESTS_CONFIG<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\AssertEqualsCanonicalizing;
class SampleTest extends TestCase {
use AssertEqualsCanonicalizing;
public function test_sample() {
$this->assertTrue(true);
}
}<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\AssertEqualsCanonicalizing;
class SampleTest extends TestCase {
use AssertEqualsCanonicalizing;
public function test_sample() {
$this->assertTrue(true);
}
}composer phpstan # Run static analysisphpstan.neon.distszepeviktor/phpstan-wordpresscomposer phpstan # 运行静态分析phpstan.neon.distszepeviktor/phpstan-wordpresscomposer buildzippedzipped/composer buildzippedzipped/composer phpcscomposer checkcomposer phpcbfcomposer phpstancomposer testcomposer buildcomposer phpcscomposer checkcomposer phpcbfcomposer phpstancomposer testcomposer buildcomposer testcomposer checkcomposer phpstancomposer buildcomposer testcomposer checkcomposer phpstancomposer build