WordPress PHP Coding Standards Make WordPress Core

2013 年 12 月 8 日6640

Handbook

PHP Coding Standards

Permalink

Log in to leave a Comment

Contents

Some parts of the WordPress code structure for PHP markup are inconsistent in their style. WordPress is working to gradually improve this by helping users maintain a consistent style so the code can become clean and easy to read at a glance.

Keep the following points in mind when writing PHP code for WordPress, whether for core programming code, plugins, or themes. The guidelines are similar to Pear standards in many ways, but differ in some key respects.

PHP

Single and Double Quotes

Use single and double quotes when appropriate. If you’re not evaluating anything in the string, use single quotes. You should almost never have to escape quotes in a string, because you can just alternate your quoting style, like so:





echo '<a href="/static/link" title="Yeah yeah!">Link name</a>';



echo "<a href='$link' title='$linktitle'>$linkname</a>";



Text that goes into attributes should be run through esc_attr() so that single or double quotes do not end the attribute value and invalidate the HTML and cause a security issue. See Data Validation in the Codex for further details.

Indentation

Your indentation should always reflect logical structure. Use real tabs and not spaces, as this allows the most flexibility across clients.

Exception: if you have a block of code that would be more readable if things are aligned, use spaces:





[tab]$foo = 'somevalue';



[tab]$foo2 = 'somevalue2';



[tab]$foo34 = 'somevalue3';



[tab]$foo5 = 'somevalue4';



For associative arrays, values should start on a new line. Note the comma after the last array item: this is recommended because it makes it easier to change the order of the array, and makes for cleaner diffs when new items are added.





$my_array = array(



[tab]'foo' => 'somevalue',



[tab]'foo2' => 'somevalue2',



[tab]'foo3' => 'somevalue3',



[tab]'foo34' => 'somevalue3',



);



Rule of thumb: Tabs should be used at the beginning of the line for indentation, while spaces can be used mid-line for alignment.

Brace Style

Braces shall be used for all blocks in the style shown here:





if ( condition ) {



action1();



action2();



} elseif ( condition2 && condition3 ) {



action3();



action4();



} else {



defaultaction();



}



Furthermore, if you have a really long block, consider whether it can be broken into two or more shorter blocks or functions. If you consider such a long block unavoidable, please put a short comment at the end so people can tell at glance what that ending brace ends – typically this is appropriate for a logic block, longer than about 35 rows, but any code that’s not intuitively obvious can be commented.

Braces should always be used, even when they are not required:





if ( condition ) {



action0();



}







if ( condition ) {



action1();



} elseif ( condition2 ) {



action2a();



action2b();



}







foreach ( $items as $item ) {



process_item( $item );



}



Regular Expressions

Perl compatible regular expressions (PCRE, preg_ functions) should be used in preference to their POSIX counterparts. Never use the /e switch, use preg_replace_callback instead.

It’s most convenient to use single-quoted strings for regular expressions since, contrary to double-quoted strings, they have only two metasequences: \' and \\.

No Shorthand PHP Tags

Important: Never use shorthand PHP start tags. Always use full PHP tags.

Correct:





<?php ... ?>



<?php echo $var; ?>



Incorrect:





<? ... ?>



<?= $var ?>



Remove Trailing Spaces

Remove trailing whitespace at the end of each line of code. Omitting the closing PHP tag at the end of a file is preferred. If you use the tag, make sure you remove trailing whitespace.

Space Usage

Always put spaces after commas, and on both sides of logical, comparison, string and assignment operators.





x == 23



foo && bar



! foo



array( 1, 2, 3 )



$baz . '-5'



$term .= 'X'



Put spaces on both sides of the opening and closing parenthesis of if, elseif, foreach, for, and switch blocks.





foreach ( $foo as $bar ) { ...



When defining a function, do it like so:





function my_function( $param1 = 'foo', $param2 = 'bar' ) { ...



When calling a function, do it like so:





my_function( $param1, func_param( $param2 ) );



When performing logical comparisons, do it like so:





if ( ! $foo ) { ...



When , do it like so:





foreach ( (array) $foo as $bar ) { ...







$foo = (boolean) $bar;



When referring to array items, only include a space around the index if it is a variable, for example:





$x = $foo['bar']; // correct



$x = $foo[ 'bar' ]; // incorrect







$x = $foo[0]; // correct



$x = $foo[ 0 ]; // incorrect







$x = $foo[ $bar ]; // correct



$x = $foo[$bar]; // incorrect



Formatting SQL statements

When formatting SQL statements you may break it into several lines and indent if it is sufficiently complex to warrant it. Most statements work well as one line though. Always capitalize the SQL parts of the statement like UPDATE or WHERE.

Functions that update the database should expect their parameters to lack SQL slash escaping when passed. Escaping should be done as close to the time of the query as possible, preferably by using $wpdb->prepare()

$wpdb->prepare() is a method that handles escaping, quoting, and int-casting for SQL queries. It uses a subset of the sprintf() style of formatting. Example :





$var = "dangerous'"; // raw data that may or may not need to be escaped



$id = some_foo_number(); // data we expect to be an integer, but we're not certain







$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_title = %s WHERE ID = %d", $var, $id ) );



%s is used for string placeholders and %d is used for integer placeholders. Note that they are not ‘quoted’! $wpdb->prepare() will take care of escaping and quoting for us. The benefit of this is that we don’t have to remember to manually use esc_sql(), and also that it is easy to see at a glance whether something has been escaped or not, because it happens right when the query happens.

See Data Validation in the Codex for more information.

Database Queries

Avoid touching the database directly. If there is a defined function that can get the data you need, use it. Database abstraction (using functions instead of queries) helps keep your code forward-compatible and, in cases where results are cached in memory, it can be many times faster.

If you must touch the database, get in touch with some developers by posting a message to the . They may want to consider creating a function for the next WordPress version to cover the functionality you wanted.

Naming Conventions

Use lowercase letters in variable, action, and function names (never camelCase). Separate words via underscores. Don’t abbreviate variable names un-necessarily; let the code be unambiguous and self-documenting.





function some_name( $some_variable ) { [...] }



Class names should use capitalized words separated by underscores. Any acronyms should be all upper case.





class Walker_Category extends Walker { [...] }



class WP_HTTP { [...] }



Files should be named descriptively using lowercase letters. Hyphens should separate words.





my-plugin-name.php



Class file names should be based on the class name with class- prepended and the underscores in the class name replaced with hyphens, for example WP_Error becomes:





class-wp-error.php



This file-naming standard is for all current and new files with classes. There is one exception for three files that contain code that got ported into BackPress: class.wp-dependencies.php, class.wp-scripts.php, class.wp-styles.php. Those files are prepended with class., a dot after the word class instead of a hyphen.

Files containing template tags in wp-includes should have -template appended to the end of the name so that they are obvious.





general-template.php



Self-Explanatory Flag Values for Function Arguments

Prefer string values to just true and false when calling functions.





// Incorrect



function eat( $what, $slowly = true ) {



...



}



eat( 'mushrooms' );



eat( 'mushrooms', true ); // what does true mean?



eat( 'dogfood', false ); // what does false mean? The opposite of true?



Since PHP doesn’t support named arguments, the values of the flags are meaningless, and each time we come across a function call like the examples above, we have to search for the function definition. The code can be made more readable by using descriptive string values, instead of booleans.





// Correct



function eat( $what, $speed = 'slowly' ) {



...



}



eat( 'mushrooms' );



eat( 'mushrooms', 'slowly' );



eat( 'dogfood', 'quickly' );



Ternary Operator

Ternary operators are fine, but always have them test if the statement is true, not false. Otherwise, it just gets confusing. (An exception would be using ! empty(), as testing for false here is generally more intuitive.)

For example:





// (if statement is true) ? (do this) : (else, do this);



$musictype = ( 'jazz' == $music ) ? 'cool' : 'blah';



// (if field is not empty ) ? (do this) : (else, do this);



Yoda Conditions





if ( true == $the_force ) {



$victorious = you_will( $be );



}



When doing logical comparisons, always put the variable on the right side, constants or literals on the left.

In the above example, if you omit an equals sign (admit it, it happens even to the most seasoned of us), you’ll get a parse error, because you can’t assign to a constant like true. If the statement were the other way around ( $the_force = true ), the assignment would be perfectly valid, returning 1, causing the if statement to evaluate to true, and you could be chasing that bug for a while.

A little bizarre, it is, to read. Get used to it, you will.

Clever Code

In general, readability is more important than cleverness or brevity.





isset( $var ) || $var = some_function();



Although the above line is clever, it takes a while to grok if you’re not familiar with it. So, just write it like this:





if ( ! isset( $var ) ) {



$var = some_function();



}



Credits

PHP standards: Pear standards

Major Changes

November 13, 2013: Braces should always be used, even when they are optional

lwoods

8:34 pm on June 23, 2013

| Log in to Reply

I recommend discouraging the use of the PHP increment and decrement operators except where necessary, such as in the ‘for’ comment:

If you are not familiar with this operator:

$i = 5;

echo ++$i; // display 6

echo $i–; // display 6 again

echo $i; // display 5

In debugging code it is very easy to miss the effect of these operators.

On the other hand, it is common and encouraged to use these operators in the ‘for’ loop:

for ( $j=0; $j<5; $j++ ){

.

.

.

}

lwoods

8:38 pm on June 23, 2013

| Log in to Reply

I disagree with the following under “Brace Style”:

Single line blocks can omit braces for brevity:

if ( condition )

action1();

elseif ( condition2 )

action2();

else

action3();

ALL IF statements should be braced! Although they are not needed in the above example the absence of braces can be very confusing if you start nesting IF statements. I have seen multiple single line blocks in nested IF statements that were near to impossible to debug.

Dayjo

2:00 pm on July 10, 2013

| Log in to Reply

I agree with @lwoods.

I find that the “Clever Code” part of this document contradicts “Yoda Conditions”.

I find reading Yoda Conditions much slower than normal conditions. It seems that Yoda Conditions are just there to prevent you from writing broken code, which you should just not do. Learn to use the correct numbe of = instead.

This also applies to the example in the Ternary Operator section which uses a Yoda Condition.

To me, ( ‘jazz’ == $music ) … would return true.. because jazz is music. Whereas ( $music == ‘jazz’ ), or even ( $music_genre == ‘jazz’ ) makes so much more sense.

Andrew Nacin

2:49 pm on July 11, 2013

| Log in to Reply

Yoda conditions are a programming best practice, and not overly clever. They’re going to remain part of the standard. Thanks for your input.

markparolisi

12:14 pm on July 21, 2013

| Log in to Reply

I wouldn’t call them a programming best practice since many languages wouldn’t even let you declare variables inside a condition. The best way to avoid this problem is to avoid declaring variables in that way. It serves no purpose but to save yourself one line of code.

Gary Jones

10:57 am on July 24, 2013

| Log in to Reply

It’s not declaring anything. It’s trying to avoid accidental assignment to a variable.

Jon Brown

6:41 am on July 11, 2013

| Log in to Reply

Regarding braces and php tags, I run into this where php tags get thier own line often:





function do_stuff() {



if ( condition ) {



?>



<ul>



<li>something1</li>



<li>something2</li>



<ul>



<?php



}



}



personally, I prefer this:





function do_stuff() {



if ( condition ) { ?>



<ul>



<li>something1</li>



<li>something2</li>



<ul>



<?php }



}



I’m really not sure which is right/wrong in the WordPress universe. Reviewing core, I think I’m right? Which is the WP way?

Andrew Nacin

2:52 pm on July 11, 2013

| Log in to Reply

I don’t think WordPress is particularly consistent either way. At the moment, it depends on what is most readable for that situation. (Also, in general, we use if/endif when we are forced to break into HTML.)

Jon Brown

6:00 am on July 16, 2013

| Log in to Reply

Thanks Nacin. Personally I hate if/endif. I find my later example much more readable, but that’s probably more familiarity with that style than an objective opinion.

lesterbuck

4:57 pm on July 17, 2013

| Log in to Reply

I am new to PHP and WordPress, so I looked for tools that do the formatting and checking for me. I have exactly zero interest or opinion in what the format should be. I just want to match the standard, and I want a tool to check/fix that automatically as I check in to my source repository. (Computers are good at that, and I have better places to apply my mental energy.)

I am not using a commercial IDE, such as Coda, which has reformatting built in. After some searching, I found wp-phptidy for reformatting, and PHP Codesniffer with the WordPress standard addon. Great, huh? Well, not exactly. wp-phptidy wants to indent the switch and case statements so they are at the same indent, while PHP Codesniffer with the WordPress standard complains if the case statements are not indented further than the switch statement.

Note: I couldn’t care less which it is, I just want an automated tool to reformat it automatically if I indent something incorrectly, and check for valid format as I am committing the file to my repository.

Ok, one of these tools is “wrong”, right? I consult the WordPress PHP coding standard and find … nothing about indenting switch statements. Well, I’ll just look at WordPress core and see what they use, right? Well, that doesn’t work either. Just look at wp-includes/functions.php and note that in one file there are multiple uses of both indent styles.

Lots of tools exist to indent code to a given standard, automatically, and there is a document entitled “WordPress Coding Standards”, but the existing code base can’t be bothered to actually follow a consistent style, any style?

J.D. Grimes

9:24 pm on August 17, 2013

| Log in to Reply

My preference is to indent case within the switch, and then to put a break at the end of the case on the same level as the case:





switch ( $var ) {



case 'a':



echo 'Apple';



break;







case 'b':



// ...



}



Are there anything like this within the standards?

J.D. Grimes

9:17 pm on August 17, 2013

| Log in to Reply

I noticed this type of spacing today (in wp-db.php):

case 'string' : // note space before colon

Is this part of the spacing standards, or just a random act of code?

hjchin

5:03 pm on August 25, 2013

| Log in to Reply

I might be being silly. In the Yoda Conditions, why would I want to compare a variable to a boolean at the first? Isn’t it simpler and straightforward to write it as following? Please correct me if i’m wrong.

if ( $the_force ) {

$victorious = you_will( $be );

}

J.D. Grimes

4:17 pm on August 26, 2013

| Log in to Reply

You’re right, in that example, it doesn’t really make sense. It should be a strict check with ===.

Reply

You must be logged in to post a comment.

0 0