PHP Coding Standards

Encourage use of AI

Using AI such as ChatGPT or CoPilot, can significantly save time and provide rapid responses and solutions. Typically, the code offered is of high quality, especially for simple tasks, making it a highly recommended resource.

Formatting.

For coding style, stick to using braces {} with if-else statements, and avoid using if/endif, while/endwhile constructs.

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

if ( condition ) {
    action1();
    action2();
} elseif ( condition2 && condition3 ) {
    action3();
    action4();
} else {
    defaultaction();
}

When using Prettier for code formatting, ensure it’s configured to align with this coding style guide, especially regarding the placement of braces. Prettier is highly customizable, so you can adjust its settings to match your guidelines.

Always ensure there is not an empty line after and before opening and closing brackets.

function greet($name) {
  // Ensure that 'name' is a valid input.
  if ( is_string( $name ) && !empty( $name ) ) {
    // Use the '__()' function for internationalization.
    $greeting = __( 'Hello, ', 'your-text-domain' ) . $name;

    // Return the greeting.
    return $greeting;
  } else {
    // Handle invalid input gracefully.
    return __( 'Invalid input', 'your-text-domain' );
  }
}

Translate output.

Always use WordPress translation functions to translate output text, except for items like usernames or brand names, and similar non-translatable elements.

// Original text to be translated
$original_text = 'This is some text to be translated.';

// Translate the text using WordPress translation functions
$translated_text = __( $original_text, 'fansocial' );

// Output the translated text
echo $translated_text;

Strictly adhere to specific comment formatting guidelines

Ensure thorough documentation with extensive comments in the code.

  1. Employ block comments before functions and classes to provide comprehensive documentation.
  2. Use single-line comments either before or after specific lines of code to offer concise explanations or clarifications for that code.
  3. Include comments to explain each part of the code.
// This is a single-line comment for a brief explanation.
$result = greet( 1 ); // Calls the greet function.
$user_id = get_user_data( 'id' ); // Define the user ID.

// This is a single-line comment for a brief explanation.
function greet(name) {
// Ensure that ‘name’ is a valid input.
if ( typeof name === ‘string’ && name.length > 0 ) {
// Use the ‘__()’ function for internationalization.
const greeting = __( ‘Hello, ‘, ‘your-text-domain’ ) + name;

// Return the greeting.
return greeting;
} else {
// Handle invalid input gracefully.
return __( ‘Invalid input’, ‘your-text-domain’ );
}
}

Incorrect comment formats example:

// calculate the area.
// CALCUALTE AREA
/* Calculate the area */
/* calculate the area */
//Calculate the area.
//Calculate the area
// Calculate the area

Ensure comments are both succinct and adequately descriptive.

Common PHP Code Examples

Maintain a single empty line to separate functions for clarity.

function calculateSum( a, b ) {
    return a + b;
}

function calculateDifference( a, b ) {
    return a - b;
}

function calculateProduct( a, b ) {
    return a * b;
}

Always use Ternary Operator.

Always use ternary operators and test if the statement is true, not false.

// (if statement is true) ? (do this) : (else, do this);
$musictype = ( 'jazz' === $music ) ? 'cool' : 'blah';
// (if field is not empty ) ? (do this) : (else, do this);

Always define variables.

Always ensure that you define a variable before using it to prevent undefined notices. By default, define it as null.

$settings = null;

Do not implement any third-party / vendor libraries.

Adding third-party or vendor PHP libraries is only allowed with approval from the CTO. Once approved, you should place the vendor library in the ‘plugin/vendor/’ directory.

Use Single Quotes.

Use single quotes and use double quotes alternate.

echo '<a href="/static/link" class="button button-primary">Link name</a>';

Unless using new line, which requires double quotes.

echo "\n";

Classes and namespaces.

// Define a namespace called MadLinksCoding
namespace MadLinksCoding;

In PHP, it's a good practice to have each file contain only one class.

The use of namespaces in plugins and themes is strongly encouraged. It is a great way to prefix a lot of your code to prevent naming conflicts with other plugins, themes and/or WordPress Core.

Each part of a namespace name should consist of capitalized words separated by underscores.

Namespace declarations should have exactly one blank line before the declaration and at least one blank line after.

There should be only one namespace declaration per file.

When extending a PHP class, place the extended class in a separate file named class-example-class-extended.php.

In WordPress, always add exit if accessed directly.

 // Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

Validate and sanitize user input and escape on output.

Always priorize using WordPress validation and sanitization functions.

In web development, validating user input involves checking if the data provided by users adheres to expected formats and criteria, while sanitizing entails cleaning and filtering user input to remove potentially harmful characters. Escaping output is the practice of rendering data in a way that prevents security vulnerabilities, such as Cross-Site Scripting (XSS) attacks, by using appropriate escaping functions based on the output context (e.g., esc_html() for HTML rendering). These three practices collectively help maintain data integrity, enhance security, and ensure code compliance with WordPress standards, reducing the risk of malicious input compromising a web application’s functionality or security.

WordPress validation and sanitization functions.

  1. esc_html():
    • Purpose: Escapes a string for safe output in an HTML context, ensuring that any HTML tags or special characters are properly encoded.
    • Example: echo '<p>' . esc_html( $text ) . '</p>';
  2. esc_attr():
    • Purpose: Escapes a string for safe output in HTML attributes, preventing any malicious input from causing issues.
    • Example: <div class="<?php echo esc_attr( $class ); ?>">Content</div>
  3. esc_url():
    • Purpose: Escapes a URL to ensure it’s safe for output in HTML attributes or as a link.
    • Example: <a href="<?php echo esc_url( $url ); ?>">Link</a>
  4. esc_js():
    • Purpose: Escapes a string for safe output in JavaScript, preventing any script injection or other security vulnerabilities.
    • Example: <script>var data = <?php echo esc_js( $data ); ?>;</script>
  5. esc_sql():
    • Purpose: Escapes a SQL query string to prevent SQL injection attacks when interacting with the database.
    • Example: $query = "SELECT * FROM " . esc_sql( $table_name );
  6. sanitize_text_field():
    • Purpose: Sanitizes a text field by removing unwanted characters and ensuring it’s safe for storage in the database or display.
    • Example: $cleaned_text = sanitize_text_field( $_POST['text_field'] );
  7. sanitize_email():
    • Purpose: Sanitizes an email address by validating its format and removing potentially harmful characters.
    • Example: $cleaned_email = sanitize_email( $_POST['email'] );
  8. absint():
    • Purpose: Ensures a value to a positive integer.
    • Example: $sanitized_number = absint( $_POST['numeric_input'] );
  9. wp_kses():
    • Purpose: Allows specific HTML tags and attributes while removing or sanitizing others. Useful for allowing safe user-generated content with controlled formatting.
    • Example: $sanitized_content = wp_kses( $user_content, array( 'a' => array( 'href' => array() ) ) );
  10. wp_kses_post():
    • Purpose: Similar to wp_kses(), but designed for use with post content, applying more liberal filtering.
    • Example: $sanitized_content = wp_kses_post( $post_content );
  11. balanceTags():
    • Purpose: Ensures that HTML tags in a string are properly balanced, helping to prevent broken layouts.
    • Example: $balanced_html = balanceTags( $html_content );

PHP validation and sanitization functions.

Sanitizing Functions:

  1. strip_tags():
    • Purpose: Removes all HTML and PHP tags from a string.
    • Example: $cleaned_text = strip_tags( $html_content );
  2. filter_var():
    • Purpose: Validates and sanitizes various types of data, including URLs and email addresses.
    • Example: $cleaned_email = filter_var( $_POST['email'], FILTER_SANITIZE_EMAIL );
  3. intval():
    • Purpose: Converts a value to an integer and removes any non-numeric characters.
    • Example: $sanitized_number = intval( $_POST[ 'numeric_input' ] );

Validation Functions (filter_var):

  1. FILTER_VALIDATE_EMAIL:
    • Purpose: Validates an email address.
    • Example: filter_var( $email, FILTER_VALIDATE_EMAIL )
  2. FILTER_VALIDATE_URL:
    • Purpose: Validates a URL.
    • Example: filter_var( $url, FILTER_VALIDATE_URL )
  3. FILTER_SANITIZE_STRING:
    • Purpose: Removes HTML tags and special characters from a string.
    • Example: filter_var( $text, FILTER_SANITIZE_STRING )
  4. FILTER_SANITIZE_EMAIL:
    • Purpose: Removes all characters except letters, digits, and !#$%&’*+-/=?^_`{|}~@.[].
    • Example: filter_var( $email, FILTER_SANITIZE_EMAIL )
  5. FILTER_SANITIZE_URL:
    • Purpose: Removes all characters except letters, digits, and $-_.+!*'(),{}|\^~[]`<>=#%;/?:@&.
    • Example: filter_var( $url, FILTER_SANITIZE_URL )
  6. FILTER_SANITIZE_NUMBER_INT:
    • Purpose: Removes all characters except digits and plus/minus signs.
    • Example: filter_var( $numeric_input, FILTER_SANITIZE_NUMBER_INT )
  7. FILTER_SANITIZE_NUMBER_FLOAT:
    • Purpose: Removes all characters except digits, plus/minus signs, and decimal points.
    • Example: filter_var( $float_input, FILTER_SANITIZE_NUMBER_FLOAT )
  8. FILTER_VALIDATE_INT:
    • Purpose: Validates an integer.
    • Example: filter_var( $integer_input, FILTER_VALIDATE_INT )
  9. FILTER_VALIDATE_FLOAT:
    • Purpose: Validates a floating-point number.
    • Example: filter_var( $float_input, FILTER_VALIDATE_FLOAT )
  10. FILTER_VALIDATE_IP:
    • Purpose: Validates an IP address (IPv4 or IPv6).
    • Example: filter_var( $ip_address, FILTER_VALIDATE_IP )
  11. FILTER_VALIDATE_BOOLEAN:
    • Purpose: Validates a boolean (true/false) value.
    • Example: filter_var( $boolean_input, FILTER_VALIDATE_BOOLEAN )
  12. FILTER_SANITIZE_SPECIAL_CHARS:
    • Purpose: Removes all special characters.
    • Example: filter_var( $text, FILTER_SANITIZE_SPECIAL_CHARS )

Space Usage.

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

// Put spaces on both sides of the opening and closing parentheses of control structure blocks.
foreach ( $foo as $bar ) { ...

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

SOME_CONST === 23;
foo() && bar();
! $foo;
array( 1, 2, 3 );
$baz . '-5';
$term .= 'X';
if ( $object instanceof Post_Type_Interface ) {}
$result = 2 ** 3; // 8.

// When defining a function, do it like so:
function my_function( $param1 = 'foo', $param2 = 'bar' ) { ...
function my_other_function() { ..

// When calling a function, do it like so:
my_function( $param1, func_param( $param2 ) );
my_other_function();

// When performing logical comparisons, do it like so:
if ( ! $foo ) { ...

// 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[0]; // Correct.
$x = $foo[ $bar ]; // Correct.

// Unless otherwise specified, parentheses should have spaces inside them.
if ( $foo && ( $bar || $baz ) ) { ...
my_function( ( $x - 1 ) * 5, $y );

// When using increment (++) or decrement (--) operators, there should be no spaces between the operator and the variable it applies to.
for ( $i = 0; $i < 10; $i++ ) {}

Always return true or false.

// Returns true on success, otherwise returns false.
return $result !== false;

Using the statement return $result !== false; is a good practice in programming. It ensures clarity and accuracy in the return value: the code explicitly checks if the result is not false, meaning any value other than false (including zero, null, or an empty string) is considered a successful outcome. It is an effective way to check for failure when running the code.

Use WordPress functions.

In a WordPress environment, it’s advisable to prioritize using existing WordPress functions over creating custom code. For instance, opt for WordPress’s redirect functions rather than directly using the header(); function. This approach ensures better integration with the WordPress framework and often leads to more efficient and reliable outcomes.

WordPress: Use home_url().

When retrieving the site URL on WordPress, for a streamlined approach we use the home_url() function, not site_url(). Additionally, when appending a page path, ensure to include it within the function like so: home_url( '/about/hello-world/' ). Remember to start and end the path with a slash for proper formatting and seamless integration.

home_url()
home_url( '/about/hello-world/' )

In PHP functions, use the $args parameter.

In PHP functions, use associative arrays and use the $args parameter as an array when it’s relevant to your code.

By defining a function with function abc($args) {}, you can utilize $args as an associative array to handle multiple inputs effectively.

Arguments must be descriptive.

// Define a function using the $args parameter as an array.
function exampleFunction( $args ) {
    echo 'User Name: ' . $args[ 'user_name' ] . PHP_EOL;
    echo 'User Age: ' . $args[ 'user_age' ] . PHP_EOL;
    echo 'User Email: ' . $args[ 'user_email' ] . PHP_EOL;
}

// Create an associative array with user details.
$userDetails = array(
    'user_name'    => 'Alice',
    'user_age'     => 30,
    'user_email'   => 'alice@example.com'
);

// Call the function with the $userDetails array.
exampleFunction( $userDetails );

Require vs Include.

Always use require_once for unconditional includes to prevent throwing errors on code dependant on the file. 

Use require_once for PHP class or function files and include_once for template files, you can follow this pattern:

// Include PHP class or function files
require_once 'path/to/your/class_or_function_file.php';

// Include template files
include_once 'path/to/your/template_file.php';
// Correct.
require_once ABSPATH . 'file-name.php';

When you use the require or include functions in your WordPress code, make sure to reference the constant defined in the core plugin file.

FANSOCIAL_PLUGIN_BASENAME
FANSOCIAL_PLUGIN_DIR_PATH
FANSOCIAL_PLUGIN_URL_PATH

Opening and Closing PHP Tags.

When embedding multi-line PHP snippets within an HTML block, the PHP open and close tags must be on a line by themselves.

// Correct Multiline.
function foo() {
    ?>
    <div>
        <?php
        echo esc_html(
            bar(
                $baz,
                $bat
            )
        );
        ?>
    </div>
    <?php
}

// Correct Single Line.
<input name="<?php echo esc_attr( $name ); ?>" />

Naming Conventions.

  1. Use lowercase letters in variable, action/filter, and function names (never camelCase).
  2. Use snake_case.
  3. Separate words via underscores.
  4. Class, trait, interface and enum names should use capitalized words separated by underscores. Any acronyms, such as HTTP, should be all upper case.
  5. Constants should be in all upper-case with underscores separating words.
  6. Files should be named descriptively using lowercase letters. Hyphens should separate words.
  7. 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
  8. Template files should have -template prepended to the begenning of the name so that they are obvious.

Use underscores for variables, constants, and function names.
Be descriptive in your naming to make your code more understandable.
Keep function names succinct and clear in their purpose.

function toggle_login_button_visibility() {}

Indentation.

For associative arrays, each item should start on a new line when the array contains more than one item

$args = array(
	[tab]'post_type'   => 'page',
	[tab]'post_author' => 123,
	[tab]'post_status' => 'publish',
);

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

[tab]$foo   = 'somevalue';
[tab]$foo2  = 'somevalue2';
[tab]$foo34 = 'somevalue3';
[tab]$foo5  = 'somevalue4';

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.

$args = array(
	[tab]'post_type'   => 'page',
	[tab]'post_author' => 123,
	[tab]'post_status' => 'publish',
);

Variable declarations should be placed at the beginning of a function.

function setupUserInterface() {
    // Declare variables at the top of the function, including those for querying DOM elements.
    $userInfoDisplay;
    $userStatusIndicator;
    $userPermissionsList;
    $userIdInput;

    // Initializing variables.
    $userInfoDisplay = get_data( 'userInfoDisplay' );
    $userStatusIndicator = get_data( 'userStatusIndicator' );
    $userPermissionsList = get_data( 'userPermissionsList' );
    $userIdInput = get_data( 'userIdInput' );

    // Rest of the function logic, potentially involving interaction with these elements.
}

Remove Trailing Spaces.

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

Arrays.

When declaring arrays, use the long array syntax:

// Correct.
$array = array( 1, 2, 3 );

// Incorrect
$array = [ 1, 2, 3 ];

Multiline Function Calls.

When splitting a function call over multiple lines, each parameter must be on a separate line. Single line inline comments can take up their own line.

Each parameter must take up no more than a single line. Multi-line parameter values must be assigned to a variable and then that variable should be passed to the function call.

$bar = array(
    'use_this' => true,
    'meta_key' => 'field_name',
);
$baz = sprintf(
    /* translators: %s: Friend's name */
    __( 'Hello, %s!', 'yourtextdomain' ),
    $friend_name
);

$a = foo(
    $bar,
    $baz,
    /* translators: %s: cat */
    sprintf( __( 'The best pet is a %s.' ), 'cat' )
);

Use elseif, not else if.

else if is not compatible with the colon syntax for if|elseif blocks. For this reason, use elseif for conditionals.

Yoda Conditions.

When doing logical comparisons involving variables, always put the variable on the right side and put constants, literals, or function calls on the left side. If neither side is a variable, the order is not important.

This applies to ==!====, and !==. Yoda conditions for <><= or >= are significantly more difficult to read and are best avoided.

if ( true === $the_force ) {
    $victorious = you_will( $be );
}

Error Suppression.

Always seek the CTO’s approval before using the ‘@’ operator to suppress errors.

Database Functions.

Always utilize WordPress’s database functions for accessing, updating, and creating databases. These functions are designed with security in mind. For example:

  1. Accessing Data: Use wpdb->get_results() for reading data. For instance, $results = $wpdb->get_results( "SELECT * FROM your_table" ); fetches all rows from ‘your_table’.
  2. Updating Data: Employ wpdb->update() for modifying existing records. For example, $wpdb->update( 'your_table', array( 'column' => 'new_value' ), array( 'ID' => $id ) ); updates the ‘column’ in rows where ‘ID’ equals $id.
  3. Inserting Data: Use wpdb->insert() for adding new records. As an example, $wpdb->insert( 'your_table', array( 'column1' => 'value1', 'column2' => 'value2' ) ); inserts a new row into ‘your_table’.
  4. Sanitizing Queries: Use WordPress’s prepared statement functions, like $wpdb->prepare(). For example, $wpdb->prepare( "SELECT * FROM your_table WHERE column = %s", $value ); safely prepares a query by substituting %s with the sanitized value of $value.

Formatting SQL statements.

When formatting SQL statements you may break them 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.

The following placeholders can be used in the query string:

  • %d (integer)
  • %f (float)
  • %s (string)
  • %i (identifier, e.g. table/field names)

Error reporting.

Ensure that error reporting is disabled following the debugging phase.

Write to log

Use our custom logger for either debugging purposes or for logging highly crucial function results.

The second parameter is the flag, and should be the file name or function name, so we can easily trace it,

Logs are saved to /wp-content/logs/debug-logs/… where you can filter through date and flag.

write_log( 'Returning false: Invalid array or empty args', 'handle_media_item' );

Use tabs for indentation.

Must using tabs for indentation instead of spaces when formatting your code. Tabs can help maintain consistent and efficient code structure.

For Visual Studio Code:

  1. Open Visual Studio Code.
  2. Click on “File” in the top-left corner and select “Preferences,” then choose “Settings” (or simply press Ctrl + , on Windows/Linux or Cmd + , on macOS).
  3. In the settings search bar, type “tab size” to find the “Editor: Tab Size” setting.
  4. Change the “Editor: Tab Size” value to your preferred tab size (e.g., 4 for four spaces).
  5. In the search bar, type “insert spaces” to find the “Editor: Insert Spaces” setting.
  6. Ensure that the “Editor: Insert Spaces” option is unchecked. This will make Visual Studio Code use tabs for indentation.
  7. Close the settings tab.

Remove trailing spaces.

To remove trailing spaces at the end of lines of code, you can follow these instructions:

For Visual Studio Code:

  1. Open your code file in Visual Studio Code.
  2. Press Ctrl + H (or Cmd + H on macOS) to open the Find and Replace dialog.
  3. In the “Find” input field, enter a space followed by a dollar sign: $
  4. Leave the “Replace” input field empty.
  5. Click the “Replace All” button (represented by a double arrow icon).

Visual Studio Code will go through your code and remove any trailing spaces at the end of lines.

!empty() vs isset()

Always utilize !empty() to verify the existence of a variable and empty() to check if a variable is empty or null.

if ( ! empty( $variable ) ) {
    // The variable is both set and not empty.
    // You can proceed with your code here.
}

Preferrably, use if ( $something ) {} as most our functions return false.

Parameters position.

In PHP 8.1, all parameters without default values should come before those with default values.

// Incorrect
function abc( $ghgjh, $fdfs = '', $dfdsfs, $fdfs )

// Correct
function abc( $ghgjh, $dfdsfs, $fdfs = '' )

Debug before submissiom for approval.

Always ensure that error logging is enabled and thoroughly check the error logs after running all functions in your task or code before submitting it for review.

Remove any error_logs, echo, die, var_dump, or print_r debugging statements from the code after debugging is complete.

Directly Referencing Fully Qualified Class Names

To optimize memory usage and avoid globally loading autoloaders and required files across your project, follow these guidelines when referencing classes in your code:

  1. Avoid use Statements: Do not use the use statement to import classes at the beginning of your PHP files. Instead, directly reference the fully qualified class names wherever necessary in your code.
  2. Referencing Classes:
    • When you need to instantiate or refer to a class, use its fully qualified class name (including the namespace) directly in the code.
    • Example:
      // Instead of using the 'use' statement like this:
      use Vendor\Package\ClassName;
      // Directly reference the fully qualified class name:
      $object = new \Vendor\Package\ClassName();
  3. Method Calls:
    • When calling static methods, use the fully qualified class name directly.
    • Example
      // Instead of:
      use Vendor\Package\ClassName;
      ClassName::staticMethod();
      // Use:
      \Vendor\Package\ClassName::staticMethod();

Code audit.

Ask ChatGPT the following questions to audit your code and note any important considerations with CTO.

Ask chatGPT the following questions:

  1. Audit this code, is it fully complaint with latest version of PHP.
  2. Audit this code and provide your views and recommendations {add all your code here}
  3. Audit this code, can you see any code that may likely break or result in errors? {add all your code here}
  4. Audit this code, are there any security considerations? {add all your code here}
  5. Audit this code, are there any performance considerations? {add all your code here}
  6. Audit this code, are there any best practices or coding standards that this code might not be adhering to? {add all your code here}
  7. Audit this code, is there any part of this code that might not be scalable or could cause issues as the application grows? {add all your code here}
  8. Audit this code, are there any dependencies used that are outdated or have known vulnerabilities? {add all your code here} Update your code accordingly.
  9. Audit this code, are there any breaches to WordPress coding standards and if so what are they. {add all your code here}
Leave a Reply 0

Your email address will not be published. Required fields are marked *