PHP Techniques to Write Clean and Readable Code

PHP Techniques to Write Clean and Readable Code

When starting a project, developers should think about how to write clean and readable PHP code so that it can be easy to maintain and fix when there’s a bug. To meet these requirements, developers in the team should follow coding standards and best practices.

What are these coding standards and best practices? Are there any PHP techniques to write clean and readable code? The answers can be found right in this article!

PHP clean code techniques

Why do you need PHP clean code?

For simple reasons:

  • You spend much more time to read code than to write code. With clean code, you're easy to read and understand what you write. Especially, after months or years revisiting the code, you'll still understand it. Or if someone else reads your code, they'll easy to understand.
  • Clean code expresses the business logic better than bad code. You'll be lost in a maze of if...else with about 5-10 nested conditions, and you have no idea what's going on!
  • Clean code gives you an oppoturnity to document the process, the "how" to write PHP code and the best practices. This documentation is valuable accross the company/team and can be used to train other members.
  • If you work with WordPress or any open source project, collaboration and contribution is key. With PHP clean code, you say the same language with other developers around the world and increase the chance for you or them to contribute to shared projects.

In our company, as we create multiple plugins for WordPress (Meta Box and Slim SEO), a developer might work on a different project at one time. And they usually collaborate with other people to develop new features or fix bugs. So, writing PHP clean code is a must for us to keep the products easy to maintain and develop.

Coding Standards

Coding standards are the rules for coding that are set up by developers in a project. When every project member follows these coding standards, the code can be easy to read, reuse, and improve.

These are the benefits of the coding standards:

  • The coding standards play an important role as the blueprint for all the project members. That helps everyone to understand each other’s code more easily.
  • With the appropriate way of coding, your code will become simpler and cleaner, helping you avoid common mistakes.
  • When you want to copy the code to use for other projects, you can easily do so without reducing the code quality.

The coding standards consist of these following common elements:

  • Naming variables, constants, functions, classes, …
  • Using spaces or tabs
  • Declaring and using variables
  • Comment
  • The maximum length for a line of code, file, ...

In case you’re developing products for WordPress like themes and plugins, you have to follow the WordPress coding standards. However, these coding standards have some strict rules that I think you may not need to follow. And here are the main rules in the WordPress coding standards that you should comply with:

Indentation and Line Length of Code

You should use tabs instead of spaces to help computers display the code in the most flexible way. In terms of line length, a line of code should be in 75 - 85 characters to make the code more readable.

Declare Arrays

WordPress requires developers to declare long array syntax (1, 2, 3). However, from the 5.4 version, PHP supports writing short array syntax [1, 2, 3]. And it’s totally fine to use short array syntax. In fact, it’s encouraged to do so.

Shorthand PHP Tag

WordPress requires you to write the full PHP tag as follows:

<?php echo 'Some text'; ?>

But from the 5.4 version, PHP supports writing short tags (this feature is always on), so you can use it for a cleaner command:

<?= 'Some text'; ?>

Control Structure

Control structure includes if, for, while, switch, … Between these words and the opening bracket, you should use ONE space (press the spacebar only ONCE) to distinguish them from function calls.

if ( ( condition 1 ) || ( condition 2 ) ) { 
    the action to be implemented 1; 
} elseif ( ( condition 3 ) && ( condition 4 ) ) { 
    the action to be implemented 2; 
} else { 
    the action to be implemented by default; 
}

As for switch commands, you can code as follows:

switch ( condition ) {
    case 1:
        the action to be implemented
        break;

    case 2:
        the action to be implemented
        break;
    default:
        the default action
        break;
}

Function Calls

When calling a function, you should add ONE space between the function name, the opening parenthesis, and the first variable, don’t write it without spaces. You should also add a space between the comma and each parameter, between the last parameter, the closing bracket, and the semicolon. For better visualization, see the below example of a function call coding standards:

$var = foo( $bar, $baz, $quux );

Naming Files and Classes

In WordPress, all classes must be named Class_Name. You need to capitalize the first letter of each word and separate it with an underscore.

The filename of the class is written as class-class-name.php. You have to add the class- prefix, lowercase class names, and separate words with dashes.

However, when working with “big” plugins and themes, you should use Composer to autoload files. In this case, the coding standards above can’t work anymore because Composer follows PSR’s rules. Therefore, it’s crucial to follow the PSR files and classes naming rules if you use Composer:

  • Class name: in the form of ClassName (capitalize the first letter of each word and write the words without spaces).
  • Filename: in the form of ClassName.php (the file’s name is the same as the class’s name).

In addition, these files are placed in the folders that correspond to their namespaces. For example, a class with the full name of \ALSearch\Shortcode\Field will be placed in the src\ShortCode folder, and its file’s name is Field.php. In this example, the src folder corresponds to the ALSearch namespace, while other parts of the class name correspond to the parts that are in the same hierarchy.

The ?: Operator

WordPress doesn’t allow using the ?: operator in the short form. It always requires writing in the long form:

$type = $type ? $type : 'select';

However, from PHP version 5.3, you can write it shorter to make them easier to read as follows:

$type = $type ?: 'select';

PHP Best Practices

There are several coding techniques that we use in our projects to make the code more optimal and easier to read and fix. I have summarized those techniques in the following sections:

Consistency

You should code in the same style for a function, class, or file, and avoid coding in different styles for the same code like the following example:

<?php if ( $args['label'] ) : ?>
    <span class="als-field__label"><?php echo esc_html( $args['label'] ); ?></span>
<?php endif; ?>

<?php
if ( $args['prefix'] ) {
    echo '<span class="als-field__prefix">' . esc_html( $args['prefix'] ) . '</span>';
}

The above code displays the label and the prefix. Although the coding styles are different, they return the same result. Therefore, we should rewrite them consistently as follows:

if ( $args['label'] ) {
    echo '<span class="als-field__label">', esc_html( $args['label'] ), '</span>';
}
if ( $args['prefix'] ) {
    echo '<span class="als-field__prefix">', esc_html( $args['prefix'] ), '</span>';
}

Early Return

If the conditional blocks are too large, the code will be very difficult to read and you will find it harder to follow the logic. To fix this, you need to write small conditional blocks. One of the techniques to do it is "early return" - return as soon as possible.

For instance, I have the following code that hasn’t been optimized:

if ( 'none' !== $field['sanitize_callback'] ) {
    if ( is_callable( $field['sanitize_callback'] ) {
        $value = call_user_func( $field['sanitize_callback'], $value, $args );
    } else {
        // a very long code
    }
}
return $value;

When you apply the “early return” technique, this code is rewritten as follows:

if ( 'none' === $field['sanitize_callback'] ) {
    return $value;
}
if ( is_callable( $field['sanitize_callback'] ) {
    return call_user_func( $field['sanitize_callback'], $value, $args );
}
// a very long code.
return $value;

Set the Default Value

Setting the default value helps us remove conditional statements that check the existence of that value, thus making your code simpler and more readable.

Below is the code that hasn’t been optimized:

if ( isset( $args['prefix'] ) && $args['prefix'] !== '' ) {
    echo esc_html( $args['prefix'] );
}
if ( isset( $args['label'] ) && $args['label'] !== '' ) {
    echo esc_html( $args['label'] );
}

After setting the default value, the code becomes more readable:

$args = wp_parse_args( $args, [
    'prefix' => '',
    'label' => '',
] );
 
if ( $args['prefix'] ) {
    echo esc_html( $args['prefix'] );
}
if ( $args['label'] ) {
    echo esc_html( $args['label'] );
}

Or even better

echo esc_html( $args['prefix'] ) ?? '';
echo esc_html( $args['label'] ) ?? '';

Output Multiple Values with echo

When we need to output a lot of texts, we usually code like this:

echo '<span class="als-field__prefix">' . esc_html( $args['prefix'] ) . '</span>';

However, this approach isn’t as optimal as using the echo function. The echo function allows us to pass many parameters at once, so it works faster than the normal function:

echo '<span class="als-field__prefix">', esc_html( $args['prefix'] ), '</span>';

Use Lazy Declaration and Declare Only When Necessary

Remember that you should only declare variables when needed. This declaration also includes creating the initial value.

In addition, you should declare as late as possible. Better yet, you should declare right on the code that uses that variable.

Below is an example of the unnecessary variable declaration:

$date = parent::get_date();
$format = ''; // Declare unnecessarily because this variable is declared again in the below code

if ( $meta ) {
    $format = 'Y-m-d';
    return date( $format, $date );
}

You should declare the variable as follows:

$date = parent::get_date();

if ( $meta ) {
    $format = 'Y-m-d';
    return date( $format, $date );
}

Here is an example of declaring variables too early when we haven’t used them yet:

$format = 'Y-m-d';

// A very long code.

return date( $format, $date );

You should only declare the $format variable right before the code that uses it as follows:

// A very long code.

$format = 'Y-m-d';
return date( $format, $date );

Last Words

Improving and optimizing code is always a matter of concern for coders. The cleaner and more readable your code is, the more efficient your teamwork is. Besides, it will be easier to handle when there’s an issue. Therefore, don’t forget to apply the above techniques to get the best results.

At Meta Box, we're trying our best to write the best code for our WordPress plugins. They are plugins for developers, so the coding quality is our top priority.

If there are any other useful tips for coding, feel free to share it with us in the comment section!

How to Use Composer and Autoload in PHP

How to Use Composer and Autoload in PHP

When working with PHP projects, developers often have to manage many libraries from third parties. But installing and updating these libraries are quite complicated. To solve this problem, you can use Composer and Autoload to save time and effort.

Now, let’s find out what Composer and Autoload are, and how to use them in PHP!

PHP autoload Composer technique

What is Composer?

A composer is a tool for dependency management in PHP. In simple words, Composer is used for managing libraries in your PHP project.

Composer allows you to declare the libraries in your PHP projects, automatically load the code of the libraries, create and add necessary files to the PHP projects, and update libraries when they have new versions.

Common Problems in Libraries Management

When you work with PHP projects, if you don’t use Composer, you will have to deal with many problems in library management.

First, you need to download and move them to the PHP project folder to use the external libraries. However, the installation is fairly complicated and difficult to remember.

Besides, there are many situations where some libraries depend on others. Therefore, updating them takes a lot of time and effort because you have to find the original library. For example, library A depends on library B, and if library B has a new version, you will have to find and update it at library A first.

Now, thanks to Composer, the above problems can be solved easily!

Benefits of Composer

Composer offers developers two main benefits:

  • Help developers centrally manage third-party libraries as well as their versions simply and quickly with the composer.json file.
  • Automatically search and update new versions of libraries that are necessary for PHP projects.

Installing Composer

To install and activate Composer, just follow these steps:

Check If PHP has been Installed

First, you need to install PHP. To check if PHP has been installed, enter the following command in the terminal:

php -v

Install Composer on Windows

Installing Composer on Windows is very easy and quick. You just need to download the Composer-Setup.exe file, and then run it.

By default, Composer adds its path to the PATH environment variable of the system so that you can call the composer command from anywhere. However, if you can't run the composer command, add the C:\ProgramData\ComposerSetup\bin value to the PATH environment variable of the system.

Install Composer on CentOS/RHEL/Ubuntu

Go to terminal and enter the following command to install Composer:

sudo curl -sS https://getcomposer.org/installer | php

Still in the terminal, enter this command to allow calling the composer command from anywhere:

mv composer.phar /usr/local/bin/composer

General Composer Commands

When working with Composer, you need some general commands below:

Check the current version of Composer:

composer -v

Update the latest version of Composer:

composer -selfupdate

Clear the Cache memory of Composer (to force Composer to reload libraries in the Cache memory):

composer clearcache

Search for library packages:

composer search library_name

How to Use Composer in PHP Projects

Set Up Composer for New PHP Projects

The first thing you need to do is create the composer.json file. This file contains all the data for setting up Composer for the project. This can be done by adding the following command to the terminal:

composer init

After that, you need to declare the composer.json file as follows:

Package name (/) [admin/my_project]: vendor/myproject (/*this is the library name/*/)
Description []: How to use Composer in PHP
Author [elightup <[email protected]>, n to skip]: elightup<[email protected]>1
Minimum Stability []: dev
Package Type (e.g. library, project, metapackage, composer-plugin) []:
License []:
Define your dependencies.
Would you like to define your dependencies (require) interactively [yes]? no
Would you like to define your dev dependencies (require-dev) interactively [yes]? No
Do you confirm generation [yes]? Y

Done! I’ve finished creating the composer.json file with the following content:

{
    "name": "vendor/myproject",
    "description": "How to use Composer in PHP",
    "authors": [
        {
            "name": "elightup",
            "email": "[email protected]"
        }
    ],
    "minimum-stability": "dev",
    "require": { }
}

From now on, Composer settings (includes settings for libraries) will be saved in this composer.json file.

Adding PHP Libraries with Composer

First, you need to determine which libraries your PHP project needs by searching them here. Once you've determined the libraries that your PHP project needs to use, integrate them into your PHP project with Composer by two methods below:

Method 1: Enter a Command on the terminal

For instance, I want to use the latest version of the phpro/grumphp library (it’s used for checking the code quality). Therefore, I enter the following command into the terminal:

composer require phpro/grumphp

This command will require Composer to download the phpro/grumphp library. This library will be saved in the vendor file in your PHP project.

In addition, the vendor/autoload.php file is automatically created. This file is used for autoloading libraries for the PHP project.

Go back to the composer.json file, the following code will show up in the file:

"require": {
        "phpro/grumphp": "^0.19.1"
    }

Explanation:

  • phpro/grumphp is the library used for the PHP project.
  • 0.19.1 is the current version of the library.

From now on, when you want to share your PHP project, just copy only the composer.json file instead of the whole vendor folder. When you paste the composer.json file to another computer, Composer will automatically update the vendor folder.

Method 2: Enter a Command in the composer.json file

Instead of entering a command directly from the terminal as method 1, you can edit the description of the whoops library in the composer.json file by adding the code with the following content into the require section:

"library-name":"^the-smallest-version"

For example, I want to integrate the phpro/grumphp library version 0.19.1 into Composer, so I fill in the require section with the following content:

"require": {
    "phpro/grumphp": "^0.19.1",
}

After that, enter the composer update to install the library. This command will automatically update the latest version of some libraries that are necessary for the PHP project.

The advantage of this second method is that you can list all libraries before entering the composer update command. Therefore, this method is very convenient when you need to install many libraries at once.

To use these above libraries for the project, you just need to enter the include vendor/autoload.php command to the index.php file in the PHP project.

Remove a Library from the PHP Project

To remove a library that was already integrated into a PHP project (saved in the vendor file), you can follow one of two methods:

Method 1: Using the composer command

From the terminal, enter the following command:

composer remove vendor/package

In this command, vendor/package is the name of the library you want to remove. For example, I want to remove the phpro/grumphp library, so the command will be like this:

composer remove phpro/grumphp

Method 2: Update the composer.json file

Just go to the composer.json file, navigate to the require section, delete the folder you want (for instance, phpro/grumphp), and then enter the composer update command.

Versions in Composer

In some cases, developers don't need to use the latest version of the library but just need to use a certain version. To do that, you can specify versions for the libraries in Composer using 6 methods below:

Version Range

This method uses comparison operators such as >, <, >=, <=, !=, AND, OR to specify the range of valid versions that Composer can use. The AND the operator is represented by commas or spaces, and the OR the operator is represented by two vertical lines (||).

For example, to specify that Composer is only allowed to use versions before version 0.19 and not allowed to use version 0.17 of the phpro/grumphp library, I enter the following command to the terminal:

composer require phpro/grumphp "<0.19,!=0.17”

Explanation:

  • phpro/grumphp: the name of the library.
  • <0.19: Composer is only allowed to use versions before 0.19.
  • !=: Composer is only allowed to use versions except 0.17.
  • , is treated as the AND operator.

Wildcard Versions

This method is used to require Composer to use only the library versions in the range of x.x.*.

For example, if I use the composer require phpro/grumphp "0.18.*” command, Composer is only allowed to use the versions after version 0.18 and before version 0.19 (like 0.18.1, 0.18.2, ...) of the phpro/grumphp library. This is similar to the use of the “>=0.18 <0.19” command in the Version Range method.

Hyphen Ranges

This method uses the - operator to determine the range. For better understanding, look at the below example.

I want to require Composer to only use versions after version 0.1 and before version 0.19 of the phpro/grumphp library. Therefore, I enter the composer require phpro/grumphp "0.1 - 0.18” command. The range includes 0.18.1, 0.18.2, … It’s similar to “>=0.10 <0.19”.

Tiddle Range

This method uses the ~ operator. For example, if you enter “~0.18”, Composer will only use the versions after the 0.18 (except 0.18) and before the 1.0. It’s similar to “>0.18 <1.0”.

Caret Range

This method uses the ^ operator to specify that Composer is only allowed to use library versions from the version that is entered (not including itself).

For example, if I enter ^0.18.1, Composer will only use the library versions after 0.18.1 (except 0.18.1).

Dev-Master

When you use the Dev-Master method, your libraries will always be in the latest available versions. However, it comes with a lot of risks because the latest versions may not be finalized and they can have some bugs.

For example, to require Composer to always use the latest version of the phpro/grumphp library, I enter the composer require phpro/grumphp "dev-master” command.

Read more: How to use Composer to install Meta Box extensions from wordpress.org here.

You can use Composer to install Meta Box extensions from wordpress.org

Autoload

What is Autoload?

Autoload is a method to load and use classes. Using Autoload, we can load and call classes everywhere instead of including classes at the beginning of each PHP file. Therefore, we don’t need to load all classes in the library for all PHP files.

As I mentioned above, Composer makes library management convenient and quick. Besides, Autoload is an extremely useful tool that helps Composer easily manage the dependencies between libraries packages.

How Does Autoload Work?

To understand how Autoload works, you need to learn about the PSR-4 standard first. This is a recommended PHP coding standard for libraries.

Below is the content of the PSR-4 standard:

Code in folders should be organized properly so that every class can be referenced. To do that, developers need to build classes according to the following structure:

\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>

When developers build a class according to the above structure, the class can be referenced by a line of code with three components: NameSpace, SubNameSpaces, and ClassName.

Explanation:

  • NameSpace: the name of the vendor and the required prefix named by yourself. Especially, it mustn’t have a similar name to other vendors.
  • SubNameSpaces: The child namespaces (following the first namespace - vendor). From the SubNameSpaces, the path of the class will correspond to the structure of the folder where the code is stored. For example, you save the code of the library in the original folder src and call one of your classes that is cls1 with the \myvendor\namespace1\namespace2\cls1 syntax. It means that there is a namespace1 folder in the src folder, and there is a namespace2 folder in the namespace1 folder.
  • ClassName: This is the name of the created class. It’s required. Besides, you need to name the PHP file like the ClassName in the folder that corresponds to the last namespace (ClassName.php). This file will define the code of the class.

All the PHP projects have to use an Autoload library to load the above structure when needed. Frameworks that have the same Autoload mechanism can reuse libraries of each other. Nowadays, almost all PHP frameworks use the same Autoload mechanism according to PSR-4.

Composer can generate autoload code according to PSR-4. Therefore, this tool can help you reuse libraries of other PHP projects.

For example, I want to create a class named Car with the namespace Vehicle/Listings. Thus, the code of the class will be saved in the src/Listings/Car.php file with the following content:

<?php
namespace Vehicle\Listings
class Car {
    function list() {
        // code...
    }
}

The above code is PSR-4 compliant, so Composer will help you integrate it into the vendor/autoload.php file. To call this class when needed, tell Composer that you have a PSR-4 Autoload module by adding the following code to your composer.json file:

{
    "autoload": {
        "psr-4": {
            "Vehicle\\": "src/",
        }
    }
}

This code requires namespace level 1 - Vehicle to point to the src/ folder. Namespaces level 2 onwards will work the same. For example, the path of the Car class is src/Listings/Car.php. To be clear, src is the file that is pointed by namespace 1, Listings is the file in src, Car.php is the PHP file containing the code of the class.

After that, enter the following command to the terminal:

composer dump-autoload

Now, vendor/autoload.php has the mechanism to autoload your code when you need to use it. Henceforth, if you want to use the Car class, just call it by one of two codes below:

The first code:

<?php
$car = new Vehicle\Listings\Car();

The second code:

<?php
use Vehicle\Listings;
$car = new Car();

The two above codes have the same function. They just have different ways of calling, so you can use whichever you want.

PHP Autoload with Composer

Last Words

Composer and Autoload are two powerful and indispensable tools in PHP. Therefore, you should use them to save time and effort from managing libraries in your project. Hopefully, this article has helped you better understand the two tools and learn how to use them at a basic level. If you have any questions about Composer and Autoload, feel free to share them with us in the comment section!

In addition, you may like our articles on how to use Object Pool Pattern and PHP techniques to write clean and readable code in our Guide category.