PHP is a great scripting language to build web applications. Reckoning my first exposure to the language, I have been tinkering with PHP for some years by now. Despite the sluggish improvement and development towards a more architecturally robust, more feature-rich, and less quick-and-dirty programming language recently, I still love coding bytes in PHP. Some people may think of PHP as the language for programming the web quickly. Write some HTML, embed some javascript, add some CSS, put some PHP code, and voila… a dynamic web page is created. I won’t praise how good PHP is for developing a web application. Several companies may have done that. Name Facebook and Yahoo as examples. With some optimization to native PHP codes, both companies have shown how to use the language to cater to millions of users and run a serious business.
In this post, I’d like to highlight another feature of PHP, the command line interface (CLI). In my personal experience, PHP CLI can be an alternative to some administrative tasks. Linux users may have been familiar with shell scripting for carrying out system management and configuration tasks. So, why must PHP? The answer is portability. The same PHP code should work not only on Linux but also on Windows. Some critics may argue that other languages may also have answer for portability. I concur to that criticism while at the same time emphasizing PHP as another viable option.
The application to be shown immediately is a file generator. It will create a file of random content with size specified by user when executing the file. The content consists of alphanumeric ASCII characters that are picked randomly. No newline are included in the file. Yet, user can tweak the application to make the generated output file also include newline.
This application can be useful for those who are learning how to write a command line-based PHP utility and also for others who want to conveniently generate files of various sizes for workload testing purpose.
Source code and snapshots are provided below:
a. Source code: filegenerator.php
/**
*A command line PHP utility to generate file of random content with various size
*@author Mikael Fernandus Simalango (https://tech.amikelive.com)
*@license MIT
*/
if(!defined('DS')) {
define('DS',DIRECTORY_SEPARATOR);
}
if(!defined('CRLF')) {
define('CRLF',PHP_EOL);
}
class fileGenerator {
private $_seed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
private $_fsize = 0;
private $_fsizeString = '';
private $_saveDir = '';
private $_override = false;
private $_outfile = 'output.txt';
public function __construct() {
$this->_saveDir = dirname(__FILE__);
}
public function setFilesize($size) {
$this->_fsize = $this->convertToByte($size);
}
public function setOutputFile($file) {
$this->_outfile = $file;
}
public function setOutputDir ($dir) {
$this->_saveDir = $dir;
}
public function setOverrideFlag ($flag) {
$this->_override = (bool) $flag;
}
public function convertToByte($fileSize) {
$size = (int) $fileSize;
$type = '';
preg_match('/[^0-9]+/',$fileSize, $type);
$this->_fsizeString = $size.$type[0];
$multiplier = 1;
switch (strtolower($type[0])) {
case 'b':
$multiplier *= 1;
break;
case 'kb':
$multiplier *= 1024;
break;
case 'mb':
$multiplier *= 1024*1024;
break;
default:
print 'Unsupported conversion. Exiting';
exit;
}
return $size*$multiplier;
}
public function getNameOfFile($file) {
if(strpos($file,DS))
$fileNameOnly = substr(strrchr($file,DS),1);
else
$fileNameOnly = $file;
$ext = $this->getFileExtension($fileNameOnly);
$strReduce = $ext ? (strlen($ext) + 1) : 0;
return substr($fileNameOnly,0,strlen($fileNameOnly) - $strReduce);
}
public function getFileExtension($file) {
return substr(strrchr($file,'.'),1);
}
public function generateUniqueFilename($fileName = '') {
if($fileName == '')
$fileName = $this->_outfile;
//rewrite the filename if its name is set to default or existing file is detected
if($fileName == 'output.txt' || file_exists($this->_saveDir.DS.$fileName)) {
$fn = $this->getNameOfFile($fileName);
$ext = $this->getFileExtension($fileName);
if(!$ext) $ext = 'txt';
$hash = substr(md5(time()),0,8);
$return = $fn.'_'.$this->_fsizeString.'-'.$hash.'.'.$ext;
}
else {
$return = $fileName;
}
return $return;
}
protected function _writeFile() {
$fn = $this->_override ? $this->_outfile : $this->generateUniqueFilename();
$fp = fopen($this->_saveDir.DS.$fn,'wb');
$content = '';
$seedSize = strlen($this->_seed);
for($i=0;$i<$this->_fsize;$i++) {
$charAt = rand(0,($seedSize-1));
$content .= $this->_seed[$charAt];
//You can uncomment this part if you want to add newlines to the outputted file
/*if($i%64 == 0) {
$content .= "\n";
$i++;
}*/
}
flock($fp,LOCK_EX);
$stat = fwrite($fp,$content);
flock($fp,LOCK_UN);
fclose($fp);
if ($stat) {
$this->_outfile = $fn;
return true;
}
return false;
}
protected function _environmentCheck() {
$errorMsg = array();
if(!is_dir($this->_saveDir)) {
array_push($errorMsg,'Directory for output "'.$this->_saveDir.'" does not exist');
}
if(!is_writable($this->_saveDir)) {
array_push($errorMsg,'Directory for output "'.$this->_saveDir.'" is not writable');
}
if($errorMsg) {
print 'Problem(s) with environment settings:'.CRLF;
for($i=0; $i<count($errorMsg); $i++)
print ($i+1)."\t".$errorMsg[$i].CRLF;
print CRLF.'Exiting...'.CRLF;
exit;
}
}
public function run() {
$this->_environmentCheck();
$stat = $this->_writeFile();
if($stat)
print 'File '.$this->_outfile.' has been written successfully'.CRLF;
else
print 'Failed to write '.$this->_outfile.CRLF;
}
}
if($argc < 2) {
print "AML Random Content File Generator".CRLF;
print "Usage: php -f filegenerator.php -- -s output_size [--override -d output_dir -f output_filename]".CRLF;
exit();
}
$gen = new fileGenerator();
for($i=0;$i<count($argv); $i++) {
if($argv[$i] == '-s') {
$size = $argv[$i+1];
$gen->setFilesize($size);
}
else if ($argv[$i] == '-d') {
$dir = $argv[$i+1];
$gen->setOutputDir($dir);
}
else if ($argv[$i] == '-f') {
$fname = $argv[$i+1];
$gen->setOutputFile($fname);
}
else if ($argv[$i] == '--override') {
$gen->setOverrideFlag(true);
}
}
$gen->run();
b. Snapshots for execution on Windows
c. Snapshots for execution on Fedora Linux
If you want to play with this simple application, you can download it directly from the following link:
AML PHP Command Line File Generator (389 downloads )
Pingback: Sample PHP Application: A Simple PHP Command Line-based File … » WB Tips
Nice Article. I didn’t know you can use php this way. Maybe not the best solution but good to know. Thank you for sharing.
I suggest using Symfony Console Component to deal with parameter parsing http://dev.umpirsky.com/building-cli-apps-with-symfony-console-component/
@klaus
yes, it may not be the best way to do things. but we’ve got an alternative.
@umpirsky
your article is nicely written. it seems that symphony implements some design patterns in its built-in design. those who want to code CLI tools in a more structured way may take benefit from your article.