Wednesday, May 25, 2011

Web-less PHP: Command Line PHP

When I decided to give PHP a closer look, I wondered if PHP was a browser-only technology or if it could be used for command line scripting. It turns out that one can write operating system level scripts with PHP as discussed in online resources such as Command Line Scripting in PHP, Command Line PHP on Microsoft Windows, and Executing PHP files. In this blog post, I look at PHP command line scripting at an introductory level.

At first glance, command line PHP script code looks like PHP code intended for the web browser. The difference becomes more obvious, though, when one notices there is typically no web-specific code (HTML/CSS/JavaScript) in the PHP command line script (and there often is for browser-oriented PHP).

I like to start PHP command line scripts with a shebang statement to make it even more obvious that it's a script intended for the command line rather than for the web browser. Although the shebang is intended for Unix and Linux operating systems, it doesn't hurt anything in DOS/Windows and communicates the target of the script (command line instead of web browser). The following code snippet indicates use of the PHP shebang in a simple PHP Hello, World example.

demoBasicHelloWorld.php
#!/usr/bin/php
<?php
   print "Hello World!";
?>

The short PHP script above does its job and, when run from the command line, prints out the string "Hello World!". This is shown in the next screen snapshot.


Many scripting languages seem to share the sometimes helpful/sometimes maddening trait of having multiple ways to do any one task. In the case of writing output, PHP has multiple approaches. I used the PHP print language construct in the above example, but the echo language construct works as well as shown in the next code listing.

demoBasicHelloWorldWithEcho.php
#!/usr/bin/php
<?php
   echo "Hello World!";
?>

The output of using echo instead of print appears exactly the same and so I don't show it here. Why would one ever choose to use print instead of echo or echo instead of print? There are seemingly numberless online resources explaining the differences between the two and contrasting them in various performance benchmarks. These include PHP Echo Vs Print: Which Should Developers Use?, PHP: Echo Versus Print(f) [which reminds us there is also the printf for printing formatted output in a similar fashion as C's sprintf and Java's String.format/Console.printf], and Echo (PHP) Versus Print (PHP). PHP Tidbit: echo vs print succinctly explains the difference: print returns a boolean value indicate status of the output whereas echo does not return anything. The slight performance benefit typically seen with echo typically does not favor it significantly compared to print for most use.


PHP Command-line Arguments

Any scripting language needs to be able to accept and use arguments passed to it on the command line. Even Java class's main functions expect arguments and Groovy makes this easier to use by implicitly providing the args handle to all Groovy scripts. PHP handles command-line arguments in a fashion similar to the C language. The use of command-line arguments is demonstrated in the next PHP code listing.

#!/usr/bin/php
<?php
if ($argc < 2)
{
   print "Hello World!";
}
else
{
   print "Hello $argv[1]!";
}
?>

The output from running the above script with and without an extra argument on the command line is shown in the next screen snapshot.



Getting PHP and Environment Information

PHP makes it really easy to get more information than you could probably ever use. This is demonstrated in the next very simple PHP code example.

showPhpInfo.php
#!/usr/bin/php
<?php
phpinfo();
?>

This simple code using phpinfo() returns too much information to show here. It includes PHP configuration information as well as the names and settings of the applicable environment variables. The end of the output contains PHP licensing information.

Speaking of environmental variables, most scripting languages running in an operating system environment need access to one or more environmental variables. PHP makes it easy to access these as shown in the next code listing.

getGroovyHomeEnvVar.php
#!/usr/bin/php
<?php
print getenv('GROOVY_HOME');
?>

The output from executing the above script leads to the output shown in the next screen snapshot.



Running Operating System Commands from PHP

Most scripting languages must support an ability to invoke operating system commands. PHP support is covered in the article Use command-line tools in PHP. Sub-titled "Run shell commands in your Web applications," this article "considers the tools built into PHP that allow you to tap into the underlying shell environment and file system PHP is running on." Specific commands for invoking shell commands from PHP include shell_exec() (equivalent to using backticks), exec(), passthru(), and C-like system().

When possible, I prefer scripts that are independent of operating system. However, when I do need operating system specific functionality, I like to either make the script either clearly advertise that it is operating system specific or, even better, put code in the script to handle different operating systems. PHP makes it possible to determine the operating system via its php_uname function.

The next PHP code listing demonstrates using php_uname in conjunction with the backticks to execute a command appropriate for the identified operating system.

#!/usr/bin/php
<?php
$os_name = php_uname("s"); // "s" mode requests operating system 'name'
if (strtoupper(substr($os_name, 0, 3)) === 'WIN')
{
   echo `dir`;
}
else
{
   echo `ls`;
}
?>

The output from running the above script is shown in the next image.



Distinguishing Web Browser PHP from Command Line PHP

There are numerous ways to determine whether a piece of PHP code is intended for a web browser or for a command line. A brute force mechanism is to look for HTML and other telltale signs of web pages to identify a piece of PHP intended for the web browser. Looking for line breaks can be useful because web-intended PHP will tend to use <br> tags while command-line intended PHP tends to use "\n". A convenient runtime mechanism for determing the environment in which the PHP code is executing is php_sapi_name, which returns the interface between the PHP code and its executing server. If the returned String is "cli," it is a command-line interface. If it is anything other than "cli," it is not command line (and is likely running on a web server and intended for a web browser).

The code below demonstrates use of php_sapi_name to distinguish running in command line versus in web server.

demoDisplayPhpEnv.php
#!/usr/bin/php
<?php
   /*
    * Script that indicates how to programmatically determine the environment
    * within which a PHP script is running.
    */
   $php_type = php_sapi_name();
   if ($php_type == "cli")
   {
      echo "PHP script executed from command line.\n";
   }
   else
   {
      echo "PHP script NOT executed from command line.\n";
   }
?>

The output from running the above PHP script from the command line is shown next.


The CLI SAPI differs from other PHP SAPIs and these differences are documented in PHP Command Line Usage: Differences to other SAPIs.


Conclusion

PHP is not just for web pages and web sites anymore. It can be used for command line scripting as well. My primary interest in PHP remains for web development and I believe I will continue to prefer languages such as Groovy, Ruby, and bash for my scripting. However, it is useful to know that PHP can be used for command line scripts. PHP developers can probably find the same benefits using the language they know well to write scripts that I find when using Groovy to write scripts. For me, I find working with PHP on command line scripts to be an easy way to become more familiar with PHP syntax, standard functions, and coding conventions.


Additional Resources

2 comments:

Paul Richard said...

Dustin, thanks for opening the door to this Linux user and amateur PHP coder who was looking for a solution to integrate CLI and PHP. Your perspective is refreshing, given the unenthusiastic consensus about PHP in the Linux community, in favor of Perl and Python...I was not looking forward to going in either of those directions, but now I see I don't have to...Python holds some interest but I prefer to stay in C syntax. Now to get that CLI web server working...Best regards, Paul

@DustinMarx said...

Paul,

Thanks for taking the time to provide that feedback. I'm happy to hear that this post was useful to you.

Although my trade is software development, I too am an "amateur PHP coder," but I have felt that PHP is a language to at least have passing familiarity with in this industry.

Good luck with the CLI web server!

Dustin