Have you ever wanted to know how many lines of code your web application consists of? I have.  To find out, I created a recursive function in PHP to count the number of lines in files relating to my web application.  Since your entire web application is likely to reside under one directory (that's the assumption I use in this article), we can count the number of lines in each file, and disinclude any files that don't have the file extensions we're looking for.  For example, the system that powers my website is built with PHP, HTML, JavaScript, and CSS so I'm only going to be counting the lines in files that match these extensions: .php, .html, .js, and .css.  Easy!  Let's get started...

Step 1: Creating the readDirectories() Function

Since it is likely that you have multiple files in multiple directories, we need a function to read in a listing of directories contained in our root directory so that we can read the files in each of those directories (and their sub-directories) as well.

/**
* Method: readDirectories
*	Purpose: Recursively read directories
*	@param $root - the Root Directory Path
*	@param $array - an array containing the currently read directories
*/
function readDirectories($root, $array = array()) {
    if(is_dir($root)) {
        if($handle = opendir($root)) {
            while(false !== ($file = readdir($handle))) {
                if($file == "." || $file == "..") continue;
                    if(is_dir($root . "/" . $file)) {
                        array_push($array, $root . "/" . $file);
                    }
                }
            }
        }
    }
	
    return $array;
}

This function takes two arguments: $root and $array.  It returns the $array variable containing whatever is currently inside it along with all the names of the directories specified in $root.  Pretty simple, but we also need to read all the files contained in each directory.

Step 2: Creating the readFiles() Function

As you can see below, the readFiles() function takes in two arguments: $root (the directory path to read files from) and $array.  The function returns $array containing whatever it had in it before plus all the files it discovered when reading the directory path specified in $root.

/**
* Method: readFiles
*	Purpose: Recursively read files in a directory
*	@param $root - the Root Directory Path
*	@param $array - an array containing the currently read files
*/
function readFiles($root, $array = array()) {
    if(is_dir($root)) {
        if($handle = opendir($root)) {
            while(false !== ($file = readdir($handle))) {
                if($file == "." || $file == "..") continue;

                if(!is_dir($root . "/" . $file)) {
                    array_push($array, $root . "/" . $file);
                }
            }
        }
    }
	
    return $array;
}

Now that we've built the pre-requisite functions for reading directories and files, we can finally get to the real meat of the article which is counting the lines in our web application!

Step 3: Creating the countLinesInDir() Function

/**
* Method: countLinesInDir
*	Purpose: Counts lines in files in specified directory and sub-directory
*	@param dir - the initial directory to look in
*	@param file_exts - an array of file extensions to filter with and count lines in
*	@param ex_dirs - an array of directories that should not be included in the count
*/ 
function countLinesInDir($dir, $file_exts = array(), $ex_dirs = array()) {	
    if(in_array($dir, $ex_dirs)) return 0;
	
    $total = 0;
    $dirs = readDirectories($dir);
    $files = readFiles($dir);
	
    foreach($dirs as $d) {
        $total += countLinesInDir($d, $file_exts, $ex_dirs);
    }
	
    foreach($files as $f) {
        $ext = strtolower(end(explode('.', $f)));
		
        if(in_array($ext, $file_exts)) {
            $total += count(file($f));
        }
    }
	
    return $total;
}

The function above takes three arguments:

  • $dir (the directory path), 
  • $file_exts (an array containing file extensions of files from which we'll count lines in), and 
  • $ex_dirs (an array containing names of directories we may want excluded from the total count).

The function first looks to see if the supplied directory is in our excluded directories array, if it is we return with 0 lines read.  If the directory is not excluded, we move on to count the total number of lines.  As you can see, this function loops through each directory (contained in $dirs) and calls itself to find all the sub-directories and files in that directory.  This is known as recursion and it's an easy way to solve big problems!  The function moves on to count all the lines of each file it finds in each directory as well.  Each time the function calls itself, it returns a total and that number is added to the overall total number of lines (which resides in the initial call to the countLinesInDir() function).  Once all recursive calls are returned and lines are counted, the function will return the overall total which should be pretty close to the total number of lines in your web application!