web analytics

How to read comment blocks into PHP array?

Did you ever notice the commented lines over theme files, widget and plugin files in PHP in different CMS like WordPress etc.? These comment blocks are not there just because the developer wanted to. These lines can be there as the system may require those lines to describe the file in terms such as the name of the theme or plugin, create date, author name, update date, version number etc. These information about the file then can later be used in the system or CMS.  

This purpose is solvable in many ways, such as

  1. Using a .ini file
  2. A separate .php file that returns an array of information
  3. Using a array-string-array method
  4. Using .txt or any file with any or no extension
  5. Using a registration method

In this particular post, we will see how to achieve this purpose while writing information in comments at the beginning of a PHP file.  

Read comment blocks into PHP array

You can use 2 PHP files, one is where we will read the commented lines (index.php), another is where the commented lines of information will be (plugin.php). Though you could have done this with a single file.  

Anyway, now write the following lines in plugin.php

<?php
/*
 * Name : A plugin
 * Description: This plugin performs blah blah blah operations
 * */

 /*
 You can have more comments later after as we will only read the first block of comments
 */
 
echo 'Nothing Here, we are testing';

Okay, now open and edit the index.php as follows,

<?php
$fileContent = file_get_contents('plugin.php');
$tokens = token_get_all( $fileContent );

foreach($tokens as $token){
	if($token[0] == T_COMMENT){
		$commentBlock = $token[1];
		break; //exiting as we only need the first block of comment
	}
}

$info = array('name' => '','description' => '');

foreach($info as $i=>$v){
	$matches = array();
	preg_match('/'.$i.'s*:s*(?P<'.$i.'>[^n]*)/i',$commentBlock,$matches);
	if(isset($matches[$i])) $info[$i] = $matches[$i];
}

That’s it, the $info array will now have the information for each of its index. If we print_r() the $info array, we get the following

Array
(
    [name] => Code 2 JS String
    [description] => Convert a piece of code; such as google adsense ad code, or a piece of html code to a JS string that could be assigned to a JS variable.
)

Explanation

First of all we are reading the content of the plugin.php file in $fileContent variable using the file_get_contents() function.  

Then we are getting an array of tokens & contents of each token in $tokens variables. The $tokens array contains a separate array for each token it founds along with its contents. Hint: Do var_dump()or print_r() the $tokens array to examine tokens.  

Then we looped over the $tokens array until we find a token which is T_COMMENT. As soon as we find it, we grab the content of this token and put it in $commentBlock variable and break the loop. T_COMMENT is a constant from PHP that holds the token number for commented blocks. We are existing loop as we need the first commented block only and expect to have the information there.  

Then we have the $info array previously indexed with the terms of information we are seeking. That is, no matter how much information are there in the commented block for how many terms, we will only consider the information of these terms in the $info array. In this case, the terms we will look for are name & description.  

Then we loop over the $info array and in each loop, we run a regular expression match on the text of the commented block using the term of the loop ($i). If found, we fill the $info[$i] with the found information.  

Notice that in the regular expression, we are using named groups. If you do not know what it is then read Using Group Names in PHP preg_match() regex to index results by names instead of numeric values

Limitations

  1. Not multi-line solution, write each term and it’s information in one line
  2. This solution does not fetch dynamic terms. However, to fetch additional information, just add the terms in the $info array, no need to code.
Thank you. Take a moment to share 🙏