WordPress coding standards: WPCS, PHPCS setup, security, i18n and PHP support

By: Irina Shvaya | October 1, 2026
This guide is part of our WordPress resource hub: costs and hosting, the block editor, plugins, SEO and speed, security, maintenance, WooCommerce, development, comparisons and migrations.

The WordPress coding standards are the project's official rules for how PHP, JavaScript, CSS and HTML should be written, plus an accessibility commitment for new code. Core contributions must follow them, and most serious plugin and theme teams adopt them too, because consistent code is easier to review, secure and hand over.

You do not enforce them by memory. The WordPress Coding Standards project (WordPressCS, often shortened to WPCS) packages the rules as sniffs for PHP_CodeSniffer (PHPCS), so a single command flags formatting problems, unescaped output, unsanitized input, missing nonces and internationalization mistakes. As of October 2026, the latest WPCS release is 3.4.1 (July 2026). For JavaScript and CSS, the @wordpress/scripts package provides matching lint commands.

This guide covers the standards that matter most, how to set up PHPCS with WPCS, the security rules (escaping, sanitizing, nonces and capability checks), internationalization, the Plugin Check tool and how WordPress decides which PHP versions it supports.

Key Takeaways

  • Install WPCS per project with Composer (wp-coding-standards/wpcs, version 3.x) and commit a phpcs.xml.dist that sets your text domain, prefixes and minimum WordPress version.
  • Choose a ruleset: WordPress (everything), WordPress-Core, WordPress-Extra (Core plus best practices) or WordPress-Docs (inline documentation).
  • Escape late on output, sanitize early on input, verify nonces for intent and check capabilities for permission; nonces are never authorization.
  • Use literal text domains that match your plugin or theme slug, and translator comments for placeholders.
  • WordPress 7.0 raised the minimum PHP version to 7.4; 8.3 or later is recommended, and 7.1 is compatible through PHP 8.5.

What the WordPress coding standards cover

The coding standards handbook has language-specific standards for CSS, HTML, JavaScript and PHP, inline documentation standards, and an accessibility section stating that WordPress "is committed to meeting the Web Content Accessibility Guidelines (WCAG) at level AA for all new and updated code." Third-party libraries bundled in a project are explicitly exempt.

The handbook's reason for having standards is practical: they "help avoid common coding errors, improve the readability of code, and simplify modification," so that files "appear as if they were created by a single person." For agencies and plugin vendors, that consistency is what makes code review and long-term maintenance affordable.

PHP rules you will meet first

The PHP coding standards are the most detailed. These are the rules newcomers trip over:

RuleWhat it meansExample
IndentationReal tabs, not spaces (spaces allowed for mid-line alignment)A tab before each nested line
NamingLowercase with underscores for functions, variables and hooks; capitalized words with underscores for classesfunction some_name( $some_variable ) {}, class WP_HTTP {}
SpacingSpaces inside parentheses and around operatorsif ( $a === $b ) {
ArraysLong array syntax is requiredarray( 1, 2, 3 ), not [ 1, 2, 3 ]
Yoda conditionsConstants, literals or function calls on the left of ==, !=, === and !==if ( true === $the_force ) {
Strict comparisonsAvoid loose comparisons unless absolutely necessary0 === strpos( $text, 'WordPress' )
Control structureselseif, not else if; braces always} elseif ( $x ) {
DatabasePrefer WordPress functions; when writing SQL, use $wpdb->prepare() with %d, %f, %s and %i placeholders, unquoted$wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $title, $id )
No shorthand tagsAlways <?php, never <?<?php echo esc_html( $x ); ?>

The handbook also warns that since PHP 8.0 named arguments, "renaming a function parameter should be considered a breaking change," so name parameters carefully in public APIs. Prefix every global function, class, constant and hook name with something unique to your plugin or theme; WPCS's PrefixAllGlobals sniff enforces it once you configure your prefixes.

Setting up PHPCS with WordPressCS

The WordPressCS README recommends a per-project Composer install. You need PHP 7.2 or later (with a few common extensions) and Composer.

  1. Allow the installer plugin: composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
  2. Install WPCS: composer require --dev wp-coding-standards/wpcs:"^3.0". This pulls in PHP_CodeSniffer and registers the WordPress rulesets automatically.
  3. Run it: vendor/bin/phpcs -ps . --standard=WordPress
  4. Auto-fix what can be fixed: vendor/bin/phpcbf . --standard=WordPress handles whitespace and formatting; security findings need a human.
  5. Update later: composer update wp-coding-standards/wpcs --with-dependencies

Then add a phpcs.xml.dist to the project root so everyone (and your CI) runs the same checks without command-line flags. Based on the sample ruleset shipped with WPCS, a typical file:

  • includes the WordPress-Extra and WordPress-Docs rulesets (or WordPress for everything);
  • sets <config name="minimum_wp_version" value="7.0"/> so deprecated-function checks match the versions you support;
  • configures WordPress.WP.I18n with your text_domain and WordPress.NamingConventions.PrefixAllGlobals with your prefixes;
  • excludes vendor and node_modules folders and build output;
  • adds PHPCompatibilityWP with a testVersion matching your minimum PHP version (for example 7.4-), after installing phpcompatibility/phpcompatibility-wp with Composer. The WPCS README says it is "specifically crafted to prevent false positives" in WordPress projects.

Most code editors can run PHPCS on save, and the WPCS wiki documents GitHub Actions setups. Running it in CI on every pull request is where it pays off; our plugin testing and QA guide shows where linting fits in a release pipeline.

Security: escaping, sanitizing, nonces and capabilities

Many WPCS errors are security findings, not style. In its README example, WPCS flags a $_SERVER value as "not unslashed before sanitization," a "non-sanitized input variable," and output that should "be run through an escaping function." The underlying rules come from the Security APIs handbook.

Escape late, on output

The escaping handbook says to escape "as late as possible, ideally as data is being outputted," because late escaping is easier to audit and more robust. Match the function to the context:

  • esc_html() for text inside HTML elements: <h4><?php echo esc_html( $title ); ?></h4>
  • esc_attr() for attribute values: class="<?php echo esc_attr( $class ); ?>"
  • esc_url() for URLs in href and src, and esc_url_raw() when storing URLs
  • esc_textarea() inside textarea, esc_js() for inline JavaScript, esc_xml() for XML
  • wp_kses_post() or wp_kses() with an allow-list when output must contain HTML

Sanitize and validate early, on input

Unslash superglobals with wp_unslash(), then sanitize with the function that matches the data: sanitize_text_field(), sanitize_textarea_field(), sanitize_email(), sanitize_key(), absint() or sanitize_url(). Validate where you can (an allowed list of values is stronger than any sanitizer). For example: $title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';

Nonces for intent, capabilities for permission

Add wp_nonce_field( 'my_plugin_save' ) to forms and verify with check_admin_referer( 'my_plugin_save' ) for admin screens, check_ajax_referer() for admin-ajax requests, or wp_verify_nonce() elsewhere. Nonces last one day by default. The handbook is explicit that nonces "should never be relied on for authentication, authorization, or access control," so always pair them with current_user_can( 'manage_options' ) or a more specific capability. REST endpoints follow the same principle through permission_callback, as covered in our REST API guide.

Security matters most in plugins, where, according to Patchstack's 2026 report, 91% of the 11,334 new WordPress ecosystem vulnerabilities found in 2025 were located. Our posts on building a secure WordPress plugin and security practices for developers go deeper.

Internationalization (i18n)

The plugin internationalization handbook sets a few rules that WPCS checks:

  • The text domain must match the plugin slug, use dashes rather than underscores and be lowercase.
  • Use a literal string for the text domain. The handbook says not to use variables or constants, because translation tools parse code without running it.
  • Use placeholders for variables, with a translator comment: /* translators: %s: Name of a city */ printf( esc_html__( 'Your city is %s.', 'my-plugin' ), esc_html( $city ) );
  • Combine translation and escaping with esc_html__(), esc_html_e(), esc_attr__() and esc_attr_e(), so translated strings cannot inject markup.
  • Loading translations: since WordPress 4.6, plugins translated on translate.wordpress.org do not need load_plugin_textdomain(), provided readme.txt declares Requires at least 4.6 or higher.

In JavaScript, use @wordpress/i18n (__(), _n(), sprintf()) and set "textdomain" in block.json for blocks, as described in our custom blocks guide.

JavaScript, CSS and block code

For block and admin JavaScript, @wordpress/scripts bundles linting that follows the WordPress JavaScript and CSS standards. Projects scaffolded with @wordpress/create-block already have npm run lint:js, npm run lint:css and npm run format. Run them in CI next to PHPCS. The same principles apply on the front end: escape on output in PHP templates (render.php, patterns) and avoid building HTML from untrusted strings in JavaScript.

Plugin Check and Theme Check

The official Plugin Check plugin (version 2.1.0, 10,000+ active installs as of October 2026) runs most of the checks used for new submissions to the WordPress.org plugin directory and flags best-practice problems from internationalization to accessibility, performance and security. Run it from Tools, then Plugin Check, or from WP-CLI with wp plugin check my-plugin; the plugin notes that only static checks run from WP-CLI by default. The Theme Check plugin plays the same role for themes.

These tools complement PHPCS rather than replace it. Use WPCS during development, Plugin Check before every release, and a human review for anything security-sensitive. Our WP-CLI guide covers the command-line side.

PHP version support policy

WordPress publishes its PHP support decisions on Make WordPress Core:

  • Minimum: WordPress 7.0 dropped PHP 7.2 and 7.3; the minimum is now PHP 7.4. The announcement explains that the project "has used 5% as the baseline usage percentage" a PHP version must fall below before retirement, and PHP 7.2 and 7.3 had dropped below 4% combined.
  • Older sites: sites still on PHP 7.2 or 7.3 remain on the 6.9 branch.
  • Recommended: PHP 8.3 or greater, per the WordPress requirements page.
  • Compatibility: the hosting handbook says WordPress 7.1 is "fully compatible with PHP 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 and 8.5," with 7.4, 8.0 and 8.1 supported "for backward compatibility only" because they are end-of-life.

For your own code, declare Requires at least and Requires PHP in the plugin header and readme.txt, set PHPCompatibilityWP's testVersion to the same minimum, and test on both the minimum and the newest PHP version you support. A plugin that requires the Abilities API, for instance, needs Requires at least: 6.9 and a fallback notice for older sites.

Conclusion

The WordPress coding standards are less about tabs and Yoda conditions than about producing code that any WordPress developer can review and trust. Install WPCS with Composer, commit a phpcs.xml.dist with your text domain, prefixes and minimum versions, add PHPCompatibilityWP, run Plugin Check before releases and treat every escaping, sanitization and nonce finding as a security issue. For more developer guides, visit our WordPress hub. eSEOspace's plugin development team builds to these standards on client projects.

Frequently asked questions

What is the difference between WPCS and PHPCS?

PHP_CodeSniffer (PHPCS) is the general tool that checks PHP files against rules. WordPressCS (WPCS) is a set of WordPress-specific rules for PHPCS. Installing WPCS with Composer installs PHPCS as a dependency.

Which ruleset should a plugin use?

WordPress-Extra plus WordPress-Docs is a common choice for plugins and themes; the full WordPress ruleset includes everything. Configure text domain, prefixes and minimum_wp_version in phpcs.xml.dist either way.

Do I have to use long array syntax?

Under the WordPress PHP standards, yes: "Arrays must be declared using long array syntax." Many private projects relax specific rules in their ruleset, but code contributed to core must follow it.

Is a nonce enough to protect a form?

No. A nonce shows the request was intended, but the handbook says nonces must never be used for authorization. Always check a capability with current_user_can() as well, and sanitize the submitted data.

What PHP version should my plugin require?

At least PHP 7.4 if you support WordPress 7.0 and later, since that is core's minimum. Requiring a newer version is allowed, but declare it in Requires PHP so WordPress can warn users before they install.

Put this into action with eSEOspace

We help businesses grow with website design that actually performs. Explore the services behind this guide:

Book a free strategy call →

Get a FREE Audit

We'll perform a comprehensive SEO, AEO, GEO & CRO audit of your website — completely free — and show you exactly how to outrank your competitors.

Don't have a site yet? Get in touch →

Get a FREE GEO/AEO/SEO Audit

We'll analyze your site's SEO, GEO, AEO & CRO — completely free — and show you exactly how to get found across Google and AI answers.

Don't have a site yet? Get in touch →

You Might Also like to Read