Static analysis with PHPSA: PHP Smart Analyzer

Share this article

Static analysis with PHPSA: PHP Smart Analyzer

One requirement that never changes whether you are working on your projects alone or in a team, on small projects or big, is Code Quality. The bigger the project and the team, the harder it gets to maintain it.

A good way of slowing this increase in difficulty down is to use static analysis tools. Static analysis is the process of analyzing software without actually executing the program – a sort of automatic code review. Static analysis tools will detect common errors, enforce coding standards, and even clean up code blocks. The days of php -l filename are not over, but we now have a number of great tools that go the extra mile in helping us create and maintain high quality code.

Speaking of php -l filename, the good old PHP lint, it’s what will execute a syntax analysis on the target file and output any errors it finds. I used to have this little piece of code that I used on and off to send emails with PHP. It is a good starting point for our analysis.

<?php

class Email{

    //Constructor
    function Email( $subject, $message, $senderName, $senderEmail, $toList, $ccList=0, $bccList=0, $replyTo=0 ){

        $this->sender = $senderName . " <$senderEmail>";
        $this->replyTo = $replyTo;
        $this->subject = $subject;
        $this->message = $message;

        // Set the To recipients
        if( is_array($toList)){
            $this->to = join( $toList, "," );
        }else{
            $this->to = $toList;
        }

        // Set the cc list
        if( is_array($ccList) && sizeof($ccList)){
            $this->cc = join( $ccList, "," );
        }else{
            $this->cc = $ccList;
        }

        // Set the bcc list
        if( is_array($bccList) && sizeof($bccList)){
            $this->bcc = join( $bccList, "," );
        }else{
            $this->bcc = $bccList;
        }
    }

    function sendMail(){

        //create the headers for PHP mail() function
        $this->headers = "From: " . $this->sender . "\n";
        if( $this->replyTo ){
            $this->headers .= "Reply-To: " . $this->replyTo . "\n";
        }
        if( $this->cc ){
            $this->headers .= "Cc: " . $this->cc . "\n";
        }
        if( $this->bcc ){
            $this->headers .= "Bcc: " . $this->bcc . "\n";
        }

        print "To: " . $this->to ."<br>Subject: " . $this->subject . "<br>Message: " . $this->message . "<br>Headers: " . $this->headers;
        return mail( $this->to, $this->subject, $this->message, $this->headers );
    }
}

As you can see, this is a simple email sending class. If we run our PHP lint on this code, we will see that everything is good.

php -l Email.php

The result is the following:

No syntax errors detected in Email.php

In 2016, this result is not enough, because we also need to consider code quality and programming standards.

Enter PHP Smart Analyzer

Lost in the static

PHPSA is a static analysis tool for PHP.

PHPSA can be installed as a .phar, or through Composer, like so:

composer require ovr/phpsa

This will create a command line utility that will be symlinked to the vendor/bin folder of our project.

Using PHPSA

After the installation is done, we can run ./vendor/bin/phpsa.

PHPSA options

The result we get after the above executes is the same result as running the list command. The help command will list the instructions for running help on PHPSA. The check command will execute the static analysis on a designated file or folder.

Because we ran the PHP lint earlier, it is expected that PHPSA will not find any syntax errors on our code. But what happens if we insert an error on purpose? Will PHPSA be able to find it?

Let’s make a slight change in our Email class.

<?php

class Email{

    //Constructor
    function Email( $subject, $message, $senderName, $senderEmail, $toList, $ccList=0, $bccList=0, $replyTo=0 ){

        $this->sender = $senderName . " <$senderEmail>";
        $this->replyTo = $replyTo;
        $this->subject = $subject;
        $this->message = $message;

        // Set the To recipients
        if( is_array($toList)){
            $this->to = join( $toList, "," );
        }else{
            $this->to = $toList;
        }

        // Set the cc list
        if( is_array($ccList) && sizeof($ccList)){
            $this->cc = join( $ccList, "," )
        }else{
            $this->cc = $ccList;
        }

        // Set the bcc list
        if( is_array($bccList) && sizeof($bccList)){
            $this->bcc = join( $bccList, "," );
        }else{
            $this->bcc = $bccList;
        }
    }

    function sendMail(){
        //create the headers for PHP mail() function
        $this->headers = "From: " . $this->sender . "\n";
        if( $this->replyTo ){
            $this->headers .= "Reply-To: " . $this->replyTo . "\n";
        }
        if( $this->cc ){
            $this->headers .= "Cc: " . $this->cc . "\n";
        }
        if( $this->bcc ){
            $this->headers .= "Bcc: " . $this->bcc . "\n";
        }

        print "To: " . $this->to ."<br>Subject: " . $this->subject . "<br>Message: " . $this->message . "<br>Headers: " . $this->headers;

        return mail( $this->to, $this->subject, $this->message, $this->headers );

    }

}

This time around we have a clear syntax error in our code. Let’s run PHPSA and check the results.

PHPSA syntax errors

As we can see, PHPSA is quick to detect a syntax error. But none of this is actually new, our simple PHP lint can detect this error, too. So let’s correct it and check what else PHPSA has in store for us.

PHPSA static analysis

A lot of things to look at now!

Notice:  Missing docblock for Email() method in src/Email.php on 6 [missing-docblock]

Notice:  join() is an alias of function. Use implode(...). in src/Email.php on 15 [fcall.alias]

Notice:  sizeof() is an alias of function. Use count(...). in src/Email.php on 21 [fcall.alias]

Notice:  Property sender does not exist in Email scope in src/Email.php on 38 [undefined-property]

PHPSA warns us about a lot of different things, many more than the ones listed above. From functions that are just aliases of others, undefined properties and missing docblocks, PHPSA does a great job suggesting the use of better coding principles.

Let’s fix our code to correct all the above.

<?php

/**
 * Simple email sender class
 *
 */
class Email
{

    /**
     * The email headers
     */
    var $headers;
    /**
     * The email sender
     */
    var $sender;
    /**
     * The email recipients
     */
    var $to;
    /**
     * Reply To
     */
    var $replyTo;
    /**
     * Email cc list
     */
    var $cc;
    /**
     * Email bcc list
     */
    var $bcc;
    /**
     * Email content
     */
    var $message;
    /**
     * The subject of the email
     */
    var $subject;

    /**
     * This is the constructor for the Email class
     */
    function Email(
        $subject,
        $message,
        $senderName,
        $senderEmail,
        $toList,
        $ccList = 0,
        $bccList = 0,
        $replyTo = 0
    ) {

        $this->sender = $senderName . " <$senderEmail>";
        $this->replyTo = $replyTo;
        $this->subject = $subject;
        $this->message = $message;

        // Set the To recipients
        if (is_array($toList)) {
            $this->to = implode($toList, ",");
        } else {
            $this->to = $toList;
        }

        // Set the cc list
        if (is_array($ccList) && count($ccList)) {
            $this->cc = implode($ccList, ",");
        } else {
            $this->cc = $ccList;
        }

        // Set the bcc list
        if (is_array($bccList) && count($bccList)) {
            $this->bcc = implode($bccList, ",");
        } else {
            $this->bcc = $bccList;
        }
    }

    /**
     * The function that actually sends the email
     *
     * @return boolean Returns TRUE if the mail was successfully accepted for delivery, FALSE otherwise.
     */
    function sendMail()
    {

        //create the headers for PHP mail() function
        $this->headers = "From: " . $this->sender . "\n";
        if ($this->replyTo) {
            $this->headers .= "Reply-To: " . $this->replyTo . "\n";
        }
        if ($this->cc) {
            $this->headers .= "Cc: " . $this->cc . "\n";
        }
        if ($this->bcc) {
            $this->headers .= "Bcc: " . $this->bcc . "\n";
        }

        print "To: " . $this->to . "<br>Subject: " . $this->subject . "<br>Message: " . $this->message . "<br>Headers: " . $this->headers;

        return mail($this->to, $this->subject, $this->message, $this->headers);
    }
}

Not a lot of changes but enough for us to understand how useful a tool like PHPSA can be. We went from undocumented, kind of sloppy code, to fully documented and clear code. It is now easier to understand what every property and function in our code does. Running PHPSA now, we will not see any errors or warnings, which means we’ve just added another layer of quality to our code.

Conclusion

PHPSA is open source, which means that we can actually follow its development, request functionality and contribute for it, and since it is a focused tool, PHPSA is fast and lightweight. At this point it is still in early alpha stage, which means that it can behave strangely sometimes, mainly giving different results on different operating systems. Also, a lot of functionality is still missing.

Static analysis is a valuable tool if we want to enforce quality standards in our code bases. It becomes even more valuable when working in a team, as it forces everybody to use the same standards. Even though it is still a little behind some other tools like Code Sniffer or Mess Detector, PHPSA is a very useful tool that shows a lot of promise. Since one of the better ways to cover a wider range of errors is to combine various analysis tools, consider using PHPSA in your QA stack. Be sure to take it for a spin, and maybe contribute to the project on github where it lists a variety of todos and planned features.

Have you tried PHPSA yet? Let us know how you feel it compares to the rest!

Frequently Asked Questions (FAQs) about PHP Smart Analyzer (PHPSA)

What is the difference between PHPSA and other PHP code analysis tools?

PHPSA, or PHP Smart Analyzer, is a development tool that performs static analysis of your PHP code. Unlike other PHP code analysis tools such as Psalm or PHPStan, PHPSA is designed to be more user-friendly and accessible to beginners. It provides a comprehensive analysis of your code, identifying potential errors, bugs, and areas for improvement. It also offers suggestions for code optimization, making it a valuable tool for improving code quality and efficiency.

How does PHPSA improve code quality?

PHPSA improves code quality by identifying potential issues and providing suggestions for optimization. It checks for common coding errors, such as unused variables, undefined variables, and potential bugs. By identifying these issues, PHPSA helps developers to improve their code, making it more efficient, reliable, and maintainable.

Is PHPSA suitable for beginners?

Yes, PHPSA is designed to be user-friendly and accessible to beginners. It provides clear, easy-to-understand feedback on your code, making it a great tool for those new to PHP development. However, it’s also robust enough to be useful for more experienced developers, making it a versatile tool for any PHP project.

How does PHPSA compare to Psalm and PHPStan?

While all three tools perform static analysis of PHP code, there are some key differences. Psalm and PHPStan are more advanced tools, offering a deeper level of analysis. However, they can be more complex to use, particularly for beginners. PHPSA, on the other hand, is designed to be more user-friendly, making it a great choice for those new to PHP development.

Can PHPSA help with code optimization?

Yes, one of the key features of PHPSA is its ability to provide suggestions for code optimization. It identifies areas of your code that could be improved, providing clear, actionable feedback. This can help to improve the efficiency and performance of your code, making your applications run more smoothly.

Is PHPSA a standalone tool?

PHPSA is a standalone tool, meaning it can be used independently of any other software. However, it can also be integrated with other development tools to provide a more comprehensive development environment.

How does PHPSA handle complex code structures?

PHPSA is designed to handle complex code structures effectively. It performs a thorough analysis of your code, identifying potential issues and providing suggestions for improvement. This makes it a valuable tool for managing complex PHP projects.

Can PHPSA identify potential bugs in my code?

Yes, one of the key features of PHPSA is its ability to identify potential bugs in your code. It checks for common coding errors, such as unused variables and undefined variables, which can lead to bugs. By identifying these issues, PHPSA helps to improve the reliability of your code.

How user-friendly is PHPSA?

PHPSA is designed to be user-friendly and accessible to developers of all skill levels. It provides clear, easy-to-understand feedback on your code, making it easy to identify and fix potential issues.

Can PHPSA be integrated with other development tools?

Yes, PHPSA can be integrated with other development tools to provide a more comprehensive development environment. This makes it a versatile tool that can be adapted to suit your specific development needs.

Claudio RibeiroClaudio Ribeiro
View Author

Cláudio Ribeiro is a software developer, traveler, and writer from Lisbon. He's the author of the book An IDE Called Vim. When he is not developing some cool feature at Kununu he is probably backpacking somewhere in the world or messing with some obscure framework.

BrunoScode qualityOOPHPPHPphpcpdphpcsphpmdphpsaqaquality assurancestandardstandardsTesting
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week