WordPress Coding Standards & Conventions
Quick-reference for WordPress PHP development. Rules are distilled from the official WordPress Coding Standards (WPCS) sniffs and WordPress core documentation.
1. Naming Conventions
All names use
for functions, variables, and properties. Classes use
with underscores (
). Hook names are all-lowercase with underscores, prefixed with your plugin slug.
| Element | Convention | Example |
|---|
| Functions | | |
| Variables | | |
| Classes | (underscored) | |
| Constants | | |
| Files | | |
| Hook names | | |
| Post type slugs | , , max 20 chars | |
File naming rules: All lowercase, hyphens as separators,
prefix for single-class files.
Global prefix rule: ALL plugin/theme globals (functions, classes, constants, hooks, namespaces) must start with a unique prefix (min 4 chars). Blocked prefixes:
,
,
,
.
Post type slugs: Max 20 chars, no reserved names (
,
,
, etc.), no
prefix.
<!-- Detailed code examples: resources/naming-best-practices.md -->
2. PHP Best Practices (WordPress-Specific)
Yoda conditions: Place literals on the LEFT side of
,
,
,
comparisons.
Strict comparisons: Always pass
as third arg to
,
,
.
Forbidden functions:
| Function | Why | Alternative |
|---|
| Pollutes local scope unpredictably | Destructure manually |
| (error suppression) | Hides errors | Check return values; use |
| Breaks interoperability | Use WP constants (, etc.) |
Development-only functions (remove before shipping):
,
,
,
,
,
, and related debug functions.
Use WordPress functions over PHP natives:
| PHP Native | WordPress Alternative |
|---|
| |
| |
| / |
| (remote) | |
| |
| |
| / | |
| , | methods |
Note:
for local files (using
,
,
) is acceptable.
Type casts: Use short forms:
,
,
,
. Never
,
, or
.
<!-- Detailed code examples: resources/naming-best-practices.md -->
3. Hooks & Actions
3.1 Registration Patterns
php
// Actions: side effects (send email, save data, enqueue assets)
add_action( 'init', 'acme_register_post_types' );
add_action( 'wp_enqueue_scripts', 'acme_enqueue_assets' );
add_action( 'admin_menu', 'acme_add_admin_page' );
// Filters: modify and return a value
add_filter( 'the_content', 'acme_append_cta' );
add_filter( 'excerpt_length', 'acme_custom_excerpt_length' );
3.2 Priority and Argument Count
php
// Default priority is 10, default accepted args is 1
add_filter( 'the_title', 'acme_modify_title', 10, 2 );
function acme_modify_title( $title, $post_id ) {
// Always declare the correct number of parameters
return $title;
}
3.3 Removing Hooks
Must match the exact callback, priority, and (for objects) the same instance:
php
// Remove a function callback
remove_action( 'wp_head', 'wp_generator' );
// Remove with matching priority
remove_filter( 'the_content', 'acme_append_cta', 10 );
// Remove an object method (must be same instance)
remove_action( 'init', array( $instance, 'init' ) );
3.4 Hook Naming Conventions
php
// Plugin hooks should be prefixed and use underscores
do_action( 'acme_before_render', $context );
$value = apply_filters( 'acme_output_format', $default, $post );
// Dynamic hooks: prefix the static part
do_action( "acme_process_{$type}", $data );
4. Internationalization (i18n)
4.1 Core Functions
| Function | Purpose |
|---|
| Return translated string |
| Echo translated string |
_x( $text, $context, $domain )
| Return with disambiguation context |
_ex( $text, $context, $domain )
| Echo with disambiguation context |
_n( $single, $plural, $number, $domain )
| Pluralization |
_nx( $single, $plural, $number, $context, $domain )
| Plural + context |
esc_html__( $text, $domain )
| Return translated + HTML-escaped |
esc_html_e( $text, $domain )
| Echo translated + HTML-escaped |
esc_attr__( $text, $domain )
| Return translated + attribute-escaped |
esc_attr_e( $text, $domain )
| Echo translated + attribute-escaped |
esc_html_x( $text, $context, $domain )
| Return translated + escaped + context |
esc_attr_x( $text, $context, $domain )
| Return translated + escaped + context |
4.2 Rules
- Text domain must match your plugin/theme slug exactly.
- All user-facing strings must be wrapped in a translation function.
- Prefer combined escape+translate over separate calls:
php
// BAD - separate escape and translate
echo esc_html( __( 'Hello', 'acme-plugin' ) );
// GOOD - combined function
echo esc_html__( 'Hello', 'acme-plugin' );
If you pass two parameters to
or
, you probably meant
/
.
4.3 Translator Comments
Add translator comments for ambiguous strings, sprintf placeholders, or context:
php
// BAD
printf( __( '%s: %s', 'acme-plugin' ), $label, $value );
// GOOD
/* translators: 1: field label, 2: field value */
printf( __( '%1$s: %2$s', 'acme-plugin' ), $label, $value );
4.4 sprintf Placeholder Rules
- With 2+ placeholders, use ordered placeholders: , (not , ).
- Do NOT use if there is only one placeholder (use ).
- The number of placeholders must match the number of arguments.
5. Enqueuing Assets
5.1 Never Use Direct Tags
php
// BAD - direct output
echo '<script src="my-script.js"></script>';
echo '<link rel="stylesheet" href="my-style.css">';
// GOOD - proper enqueue
function acme_enqueue_assets() {
wp_enqueue_script(
'acme-main',
plugin_dir_url( __FILE__ ) . 'js/main.js',
array( 'jquery' ),
'1.2.0',
true // in_footer
);
wp_enqueue_style(
'acme-styles',
plugin_dir_url( __FILE__ ) . 'css/styles.css',
array(),
'1.2.0'
);
}
add_action( 'wp_enqueue_scripts', 'acme_enqueue_assets' );
5.2 Required Parameters
| Parameter | Required? | Notes |
|---|
| Yes | Unique identifier |
| Conditional | Omit only when registering dependency-only handle |
| Recommended | Array of dependency handles |
| Yes (when src given) | Must be non-false; use explicit version string. = WP core version (bad for cache busting). = no version query string (also discouraged). |
| (scripts) | Yes | Explicitly set (footer) or (header). Defaults to header if omitted. |
| (styles) | Optional | Default |
php
// BAD - missing version, missing in_footer
wp_enqueue_script( 'acme-main', $url );
// GOOD
wp_enqueue_script( 'acme-main', $url, array(), '1.0.0', true );
5.3 Conditional Loading
Load assets only where needed:
php
function acme_admin_assets( $hook ) {
if ( 'toplevel_page_acme-settings' !== $hook ) {
return;
}
wp_enqueue_style( 'acme-admin', ... );
}
add_action( 'admin_enqueue_scripts', 'acme_admin_assets' );
function acme_frontend_assets() {
if ( ! is_singular( 'acme_portfolio' ) ) {
return;
}
wp_enqueue_script( 'acme-portfolio', ... );
}
add_action( 'wp_enqueue_scripts', 'acme_frontend_assets' );
6. WordPress API Usage
Key rules for WordPress API calls. Use capabilities (not roles) in
. Cron intervals must be 15+ minutes. Limit
(no
). Never overwrite WP globals (
,
). Always pass
to
. Avoid
current_time( 'timestamp' )
-- use
for UTC or
for formatted local time.
Common capabilities:
,
,
,
,
,
,
,
.
applies to:
,
,
,
,
,
,
,
.
<!-- Detailed code examples: resources/api-deprecated-formatting.md -->
7. Deprecated Functions (Common Replacements)
Common deprecated functions and their replacements. WPCS flags usage as an error if the function was deprecated before your configured minimum WP version, and a warning otherwise.
| Deprecated | Since | Replacement |
|---|
| 4.5 | |
| 6.2 | |
| 3.0 | |
| 3.0 | |
| 2.1 | |
| 3.0 | |
| 3.0 | |
| 3.0 | |
| 4.6 | |
| 4.0 | |
| 4.0 | |
| 4.4 | |
| 4.4 | |
| 5.7 | |
wp_make_content_images_responsive()
| 5.5 | |
| 5.5 | |
remove_option_whitelist()
| 5.5 | |
wp_get_loading_attr_default()
| 6.3 | wp_get_loading_optimization_attributes()
|
| 6.0.2 | |
| 5.9 | |
| 2.8 | |
| 2.8 | |
| 2.8 | |
| 3.0 | |
| 6.9 | |
current_user_can_for_blog()
| 6.7 | current_user_can_for_site()
|
<!-- Full table also in: resources/api-deprecated-formatting.md -->
8. Formatting
Spacing: WordPress uses spaces inside parentheses, brackets, and around operators. Control structures always have spaces after keywords and inside parens:
,
.
Indentation: Use tabs, not spaces. Multi-line arrays: one item per line, trailing comma.
Operator spacing: Spaces around
,
,
,
, etc. No spaces around
or
.
Cast spacing: Space after cast, no space inside:
.
<!-- Detailed code examples: resources/api-deprecated-formatting.md -->
9. Testing
PHP: Use PHPUnit with
. Install via
composer require --dev phpunit/phpunit
or
. Test files in
, named
.
JavaScript: Use
(bundles Jest):
npx wp-scripts test-unit-js
. E2E via
@wordpress/e2e-test-utils
.
Linting: vendor/bin/phpcs --standard=WordPress src/
for PHP.
and
npx wp-scripts lint-style
for JS/CSS.
<!-- Detailed code examples: resources/testing-patterns.md -->
10. Quick Reference Tables
Control Structure Spacing
| Pattern | BAD | GOOD |
|---|
| if | | |
| elseif | | |
| foreach | | |
| for | | for ( $i = 0; $i < 10; $i++ )
|
| switch | | |
| while | | |
Naming Quick Reference
| Element | Convention | Example |
|---|
| Functions | | |
| Variables | | |
| Classes | (underscored) | |
| Constants | | |
| Files | | |
| Hook names | | |
| Post type slugs | , | |
WordPress i18n Functions at a Glance
| Need | Function |
|---|
| Return translated string | |
| Echo translated string | |
| Return + HTML escape | |
| Echo + HTML escape | |
| Return + attr escape | |
| Echo + attr escape | |
| With context | , , |
| Singular/plural | |
| Singular/plural + context | |