Proposal: Disallow assignments in conditions and remove the Yoda condition requirement for PHP

After discussion with several coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. committers and WordPress leads, the title and the contents of the text were changed to clarify that this is a proposal and not a decision set in stone.

This proposal is the continuation of the long discussion on the WordPress Coding Standards (WPCS) repo.

Yoda conditions (or Yoda notation) is the programming style where the parts of an expression in the condition are reversed from the ‘typical’ order.

In a large part of the world, the natural reading order is left to right (LTR). This is what most programming languages adhere to. That means the variable assignments or echo/print statements are written with the variable first:

$post_type = 'post';

echo $post_type;

With the same idea in mind, conditions can also be written left to right, like:

if ( $post_type == 'post' ) {
    $category = get_the_category();
}

With Yoda conditions applied, the above condition would be written as:

if ( 'post' == $post_type ) {
    $category = get_the_category();
}

The idea behind it is that writing the value on the left side of the condition will prevent accidentally assigning the value to the variable since assignments can’t be made to values.

if ( $post_type = 'post' ) {
    $category = get_the_category();
}

While seemingly helpful at first glance, the obvious problem with them is the decreased readability of code, especially for people with reading disabilities such as dyslexia.

How we got here

When the handbook rule about Yoda conditions was introduced there was barely any static analysis tooling available in the PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher world. The only ‘foolproof’ way to prevent accidental assignment in conditions was to invert the order of the value being checked and the variable.

Automated checking for assignments in conditions via PHP_CodeSniffer (PHPCSPHP Code Sniffer PHP Code Sniffer, a popular tool for analyzing code quality. The WordPress Coding Standards rely on PHPCS.), the underlying tooling for WPCSWPCS The collection of PHP_CodeSniffer rules (sniffs) used to format and validate PHP code developed for WordPress according to the WordPress Coding Standards. May also be an acronym referring to the Accessibility, PHP, JavaScript, CSS, HTML, etc. coding standards as published in the WordPress Coding Standards Handbook., became available in 2017. Moreover, the current sniffsniff A module for PHP Code Sniffer that analyzes code for a specific problem. Multiple stiffs are combined to create a PHPCS standard. The term is named because it detects code smells, similar to how a dog would "sniff" out food. enforcing Yoda condition in the WPCS doesn’t protect against accidental assignments in conditions.

Today there is tooling in place that can help with identifying assignments in conditions, making the Yoda rules obsolete.

Keep in mind that strict comparisons (===) are already strongly encouraged and a part of the WordPress-Core ruleset (warning), making accidental assignments even less likely.

A thorough analysis was made by Lucas Bustamante in the WPCS ticketticket Created for both bug reports and feature development on the bug tracker. on the impact this could have on the plugins in the WordPress directory. The analysis showed that Yoda conditions are used in 18.02% of the plugins, so the majority of pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party developers are using non-Yoda conditions.

What to do next?

The discussion in the WPCS ticket is long and opinionated, but comes down to these points:

Disallow Yoda condition

  • Drop the handbook rule that requires Yoda conditions and instead explicitly disallow using them.

Remove Yoda condition as a requirement

  • Discourage, but don’t disallow Yoda conditions. Just don’t report if the code is or is not using Yoda conditions. The rule would also be dropped from the handbook.

In both cases, assignments in conditions will still be checked for and forbidden.

Impact on the Core code

Disallowing Yoda conditions for WordPress Core would mean that all existing patches on open tickets for Core would need to be revisited and fixed accordingly, which could burden the contributors.

Running the same analysis as Lucas did for plugins, over the WordPress Core, there were 5427 Yoda conditions, and 312 non-Yoda conditions.

Luckily, these are violations that can be automatically fixed using phpcbf tool, but care should be taken to check if all the violations were correctly fixed.

If Yoda conditions are discouraged (option 2), and the existing Yoda conditions in the Core code remain, that would mean less work for the Core contributorsCore Contributors Core contributors are those who have worked on a release of WordPress, by creating the functions or finding and patching bugs. These contributions are done through Trac. https://core.trac.wordpress.org., but also would add lots of inconsistencies in the Core code (mixed Yoda and non-Yoda conditions).

Next steps

The chosen way forward is to remove the Yoda condition as a requirement (remove it from the handbook) but not disallow it for the time being.

For WPCS, that would mean the removal of the Yoda conditions requirement (and sniff) in WPCS 3.0, with a notice that non-Yoda conditions will start to be required in WPCS 4.0 version.

Work is currently actively ongoing to prepare for the WPCS 3.0.0 release. There will be a minimum of six months between the 3.0.0 and the 4.0.0 release to allow time for Core and other projects to adjust.

Once WPCS 4.0.0 version is released, a one-time-only auto-fix of all the remaining Yoda conditions in Core will be made, and any patches to the Core which go in after that will have to use non-Yoda.

How to enforce the non-Yoda conditions in your code

If you are a WordPress plugin or theme developer, and you’d like to enforce non-Yoda conditions in your code, you can use the Generic.ControlStructures.DisallowYodaConditions sniff. In your phpcs.xml.dist file you should add the following sniff:

<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Example Project" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/squizlabs/PHP_CodeSniffer/master/phpcs.xsd">

    <!-- Your custom rules. -->

    <!-- Disallow Yoda conditions in your codebase. -->
    <rule ref="Generic.ControlStructures.DisallowYodaConditions"/>

</ruleset>

If you want to change the Yoda conditions to non-Yoda conditions, use the phpcbf tool (part of PHPCS) with the Slevomat coding standards. Specifically, the SlevomatCodingStandard.ControlStructures.DisallowYodaComparison sniff that has the fixer for the Yoda conditions.

Props to Juliette Reinders Folmer and Gary Jones for the proofreading and adding valuable feedback on the text. Also, a big props to Lucas Bustamante for the impact analysis on WordPress plugins.

#codingstandards, #php, #wpcs

Updating the Coding standards for modern PHP

Until May last year, contributions to WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. were bound to PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher 5.2 syntax and most plugins and themes stuck to the PHP 5.2 minimum requirement as well.

However, with the change to PHP 5.6 as the minimum PHP version for WordPress Core, new PHP features have become available for use in WP Core and with the outlook of a minimum version of PHP 7.x in the (near) future, even more interesting language features will soon become available for use in WordPress Core, plugins and themes.

With that in mind, we’d like to define coding standards for a number of these constructs and propose to implement automated checking for these in the WordPress Coding StandardsWordPress Coding Standards The Accessibility, PHP, JavaScript, CSS, HTML, etc. coding standards as published in the WordPress Coding Standards Handbook. May also refer to The collection of PHP_CodeSniffer rules (sniffs) used to format and validate PHP code developed for WordPress according to the PHP coding standards. tooling in the near future.

While it may still be a while before some of these features will actually be adopted for use in WordPress Core, defining the coding standards in advance will allow for a consistent code base when they do get adopted and will allow for plugins and themes, which are not necessarily bound to the PHP 5.6 minimum, to safeguard their code consistency when they start using more modern PHP already.

To be honest, none of these proposals are terribly exciting and some may not even seem worth mentioning. Most follow either prior art in WordPress Core or industry standards for the same, but in the spirit of openness, we’d like to verify our take on these before implementing them.

Continue reading

#modernizewp, #codingstandards, #php, #wpcs

PHP Coding Standards Changes

This is a follow-up to several changes proposed a few months ago.

While reading these changes, it’s important to keep in mind that they only apply to WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.: you can (and should) choose practices that best suits your development style for your own plugins and themes. The coding standards are intentionally opinionated, and will always lean towards readability and accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) over being able to use every possible language feature.

Closures (Anonymous Functions)

There was quite a lot of discussion around this proposal, particularly with regards to allowing closures as hook callbacks. Thank you everyone for your input, and for keeping disagreements respectful. 🙂

We do need a decision, however, and there were several key points that led to this:

  • It’s currently difficult to remove closures as hook callbacks. #46635 has several interesting proposals to address this in an entirely backward compatible manner.
  • While WordPress Core should strive to allow any callback to be unhooked, plugins have no such restriction.
  • The WordPress JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. Coding Standards allow for closures to be used, we should be aiming to bring the PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher standards in line with that.
  • The broader PHP world has embraced closures for many years, and have found ways to use them responsibly. We shouldn’t ignore PHP usage outside of WordPress.

With these points in mind, a conservative, but practical step is to allow closures as function callbacks, but not as hook callbacks in Core. Ultimately, we should be able to allow any sort of complex callback to be attached to hooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same., but the Core APIs aren’t quite ready for it yet.

Coding Standards Change

Where appropriate, closures may be used as an alternative to creating new functions to pass as callbacks.

Closures must not be passed as filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. or action callbacks, as they cannot be removed by remove_action() / remove_filter() (see #46635 for a proposal to address this).

Short Array Syntax

A little less controversial, but still with varying opinions, was the proposal to require short array syntax ( [ 1, 2, 3 ] ) instead of long array syntax ( array( 1, 2, 3 ) ) for declaring arrays.

While I’m personally partial to short array syntax, there were two particularly convincing arguments for using long array syntax:

  • It’s easier to distinguish from other forms of braces, particularly for those with vision difficulties.
  • It’s much more descriptive for beginners.

So, this change to the coding standards is the opposite of what was originally proposed, but is ultimately the more inclusive option.

Coding Standards Change

Arrays must be declared using long array syntax in WordPress Core.

Short Ternary Operator

The original proposal was to allow the short ternary operator, but this change reverses that. There’s a good argument that it looks too much like the null coalesce operator, especially as they perform different functions.

Take the following example from Core:

$height = isset( $data['height'] ) ? $data['height'] : 0;

It’s not possible to reduce this line with the short ternary operator, but it can be trivially reduced with the null coalesce operator:

$height = $data['height'] ?? 0;

The vast majority of other ternary operators in Core (which don’t have an isset() test) look something like this:

$class = $thumb ? ' class="has-media-icon"' : '';

This also can’t be reduced using the short ternary operator.

As the null coalesce operator is a useful addition (which we’ll be able to use once the minimum PHP version bumps to 7+), whereas the short ternary operator can only be used in a handful of cases in Core, it’s better to avoid the potential confusion, and not use the short ternary operator.

Coding Standards Change

The short ternary operator must not be used.

Assignments Within Conditionals

Particularly when there are multiple conditions, it can be quite difficult to spot assignments occurring in a conditional. This arguably falls under the Clever Code guidelines, but hasn’t been formalised.

I got a little ahead of myself with this one, and have already removed all assignments in conditionals from Core. Adding this change to the standard formalises the practice.

Coding Standards Change

Assignments within conditionals must not be used.

#php, #wpcs

Coding Standards Updates for PHP 5.6

With the minimum PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher version increasing to 5.6 as of WordPress 5.2, now’s a good time to be reviewing the WordPress Coding StandardsWordPress Coding Standards The Accessibility, PHP, JavaScript, CSS, HTML, etc. coding standards as published in the WordPress Coding Standards Handbook. May also refer to The collection of PHP_CodeSniffer rules (sniffs) used to format and validate PHP code developed for WordPress according to the PHP coding standards..

Here is a set of changes that I’d like to propose.

Anonymous Functions (Closures)

Anonymous functions are a useful way to keep short logic blocks inline with a related function call. For example, this preg_replace_callback() call could be written like so:

$caption = preg_replace_callback(
	'/<[a-zA-Z0-9]+(?: [^<>]+>)*/',
	function ( $matches ) {
		return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] );
	},
	$caption
);

This improves the readability of the codebase, as the developer doesn’t need to jump around the file to see what’s happening.

Coding Standards Proposal

Where the developer feels is appropriate, anonymous functions may be used as an alternative to creating new functions to pass as callbacks.

Anonymous functions must not be passed as filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. or action callbacks in WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress., as they cannot be removed by remove_action() / remove_filter() (see #46635 for a proposal to address this). Outside of Core, developers may pass anonymous functions as filter or action callbacks at their own discretion.

Namespaces

Namespaces are a neat way to encapsulate functionality, and are a common feature in modern PHP development practices. As we’ve discovered in the past, however, introducing namespaces to the WordPress codebase is a difficult problem, which will require careful architecture and implementation.

Side note: there’s currently no timeline for introducing namespaces to WordPress Core, expressions of interest are welcome. 🙂

Coding Standards Proposal

At this time, namespaces must not be used in WordPress Core.

Short Array Syntax

Rather than declaring arrays using the array( 1, 2, 3 ) syntax, they can now be shortened to [ 1, 2, 3 ]. This matches how arrays are declared in the WordPress JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. Coding Standards.

To allow for plugins and themes that support older versions of WordPress, I’d like to propose that WordPress Core switches to short array syntax immediately, but plugins and themes may choose which they use. A future iteration would make short array syntax a requirement.

Coding Standards Proposal

Arrays must be declared using short array syntax in WordPress Core. Arrays may be declared using short array syntax outside of Core.

Short Ternary Syntax

A fairly common pattern when setting a variable’s value looks something like this:

$a = $b ? $b : $c;

The short ternary syntax allows this to be shortened, like so:

$a = $b ?: $c;

It’s important to note that this is different to the null coalesce operator, which was added in PHP 7. If $b is undefined, the short ternary syntax will emit a notice.

Coding Standards Proposal

Short ternary syntax may be used where appropriate.

Assignments within conditionals

While this isn’t directly related to the PHP version bump, I’d like to propose disallowing assignments within conditionals. Particularly when there are multiple conditions, it can be quite difficult to spot assignments occurring in a conditional. This arguably falls under the Clever Code guidelines, but hasn’t been formalised.

For example, this if statement would be written like so:

$sticky_posts = get_option( 'sticky_posts' );
if ( 'post' === $post_type && $sticky_posts ) {
	// ...
}

Coding Standards Proposal

Assignments within conditionals are not allowed.

Other New Features

Any other new features available in PHP 5.6 can be used, though we should continue to carefully consider their value and (in the case of newer PHP modules) availability on all hosts.


How do you feel about these changes? Are there other changes related to PHP 5.6 that you’d like to suggest?

#php, #wpcs