Header In the past week I’ve had two weird bugs come up. After an hour or two of troubleshooting they both revolved around an extra character before the <?php tag in a PHP file. In one case I added an extra return line before the <?php and in another I added an extra “`”.

`<?php
class ... {
...
}

In trying to debug these problems I wrote a script to find PHP files with extra characters and I’ve added it to my pre-commit check.

How to Fix this Proactively

The most annoying thing about trying to detect this type of problem is that the files are valid PHP so linting your files won’t catch the problem. I initially try solving the problem using grep and awk and a combination of things but that was both hard to maintain and difficult to do.

The Script

I ended up using PHP to solve this problem because I have a feeling I’ll want to do checks similar to this in the future and I’m much better with PHP than BASH :-) .

#!/usr/bin/php

<?php
function checkIfDirectoryHasProblemFile($dir)
{
    $returnVal = false;
    if ($dir == './directory/to/skip') {
        return false;
    }

    $entries = glob($dir . '/*');

    $searchString = "<?php";
    $searchStringLength = strlen($searchString);

    foreach ($entries as $entry) {
        if (is_dir($entry)) {
            if (checkIfDirectoryHasProblemFile($entry)) {
                $returnVal = true;
            }
            continue;
        }

        if (entryIsSkippable($entry)) {
            continue;
        }

        $contents = file_get_contents($entry);
        $contentsFirstCharacters = substr($contents, 0, $searchStringLength);
        if ($contentsFirstCharacters != $searchString) {
            echo "{$entry} does not start with {$searchString}", PHP_EOL;
            echo "Found: ", substr($contents, 0, $searchStringLength), PHP_EOL;
            echo PHP_EOL;
            $returnVal = true;
        }

    }

    return $returnVal;
}

function entryisSkippable($entry)
{
    $info = pathinfo($entry);

    if (!isset($info['extension'])) {
        return true;
    }

    if ($info['extension'] != 'php') {
        return true;
    }

    return false;
}

if (checkIfDirectoryHasProblemFile("./src")) {
    exit(1);
}

if (checkIfDirectoryHasProblemFile("./tests")) {
    exit(1);
}

exit(0);

I would like to highlight a couple things about this script.

  1. We’re using exit(1) to show there’s a problem and exit(0) to show that everything is correct. This allows us to use the scripts return value to drive another script (which I’ll have to share later).
  2. if ($dir == './directory/to/skip') { allows you to define project specific directories to ignore. For example, my current project has a series of JS and SCSS files inside the src directory and they never start with <?php so I’m ignoring the whole directory.
  3. Although unlikely, I take no responsibility for any problems this code creates.

An Example Run

$ ./checkPHPFiles.php 

./src/Controller/TasklistController.php does not start with <?php
Found: `<?ph

Sound Off!

Has this script helped you? Let us know in the comments or share this on social media.