leader

PHP CLI

View markdown

First PHP CLI Program

Here's a typical first program.


<?
 echo "hello\n";

Run it with the php command and no surprises.


$  php hello.php
hello

If you want to run the PHP script directly without the leading php command then add #!/usr/local/bin/php as the first line as shown below.


#!/usr/local/bin/php
<?
 echo "hello\n";

Run it again...


$ hello.php
 -jailshell: hello.php: command not found

Whoops, command not found. The current directory isn't in the path. This can be fixed by including the current directory in the path like this, PATH=$PATH:.. Another alternative is to specify the current directory like this, ./hello.php.

The following examples use both methods to run scripts in the current directory.


$ PATH=$PATH:.

$ hello.php
 -jailshell: hello.php: Permission denied

Ugh, Permission denied. No worries, the script just needs to be made executable with the chmod command.


$ ls -l hello.php
 -rw-r--r-- 1 user user  Jan 25 09:11 hello.php 
$ chmod 744 hello.php

$ ls -l hello.php  -rwx r--r-- 1 user user  Jan 25 09:11 hello.php*

$ ./hello.php
 Content-type: text/html

hello
WARNING: If you see Content-type: text/html then you are not running the CLI version of PHP. I got this error because I incorrectly pointed to /usr/bin/php instead of usr/local/bin/php.

Anyway... if you must continue running the cgi version of php then you can suppress the Content-type: text/html header by running PHP in quiet mode with #!/usr/bin/php -q.


#!/usr/bin/php -q
<?
 echo "hello\n";

Run the PHP script again and all looks good. Again, the -q switch is only required because I was incorrectly running the cgi version of PHP instead of the cli version. Hostgator makes it transparent and easy to use the CLI version, but I still managed to mess it up.


$ hello.php
hello

SAPI PHP Server API

PHP has a special variant that is tweaked to work from the command-line. The php -v version command will clearly show if your are running the cli version.

$ which php
/usr/local/bin/php

$ php -v
PHP 5.4.45 (cli) (built: Apr 17 2017 15:59:08)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v10.2.4, Copyright (c) 2002-2018, by ionCube Ltd.
    with Zend Guard Loader v3.3, Copyright (c) 1998-2013, by Zend Technologies

$ /usr/bin/php -v
PHP 5.4.45 (cgi-fcgi) (built: Apr 17 2017 15:59:08)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v10.2.4, Copyright (c) 2002-2018, by ionCube Ltd.
    with Zend Guard Loader v3.3, Copyright (c) 1998-2013, by Zend Technologies

In the above example php -v, located at /usr/local/bin/php, returns cli but /usr/bin/php -v returns cgi-fcgi. My mistake above was to incorrectly type #!/usr/bin/php instead of #!/user/local/bin/php.

CGI-FCGI vs CLI

While I debugged the above issue I stumbled onto, and worked-around, three differences between CLI mode and CGI-FCGI mode.

php_sapi_name

The php_sapi_name() function returns cli or something else, such as cgi-fcgi. The following example checks the Server API (SAPI) at the start of the command-line script. If the SAPI is not cli then the script aborts with an error message.


#!/usr/local/bin/php
<?
$server_api = php_sapi_name();
if ($server_api != 'cli') exit("Wrong Server API (SAPI): '$server_api'\n\n"); 

echo "Correct SAPI!!\n";
exit;

$ sapi_test.php
 Correct SAPI!!

$ /usr/bin/php sapi_test.php
Content-type: text/html

 Wrong Server API (SAPI): 'cgi-fcgi'

Version of PHP

The php -v command returns the CLI version of PHP. Note, Apache httpd server may be configured to use a different version.

$ php -v
 PHP 5.4.45 (cli) (built: Apr 17 2017 15:59:08)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
    with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v10.2.4, Copyright (c) 2002-2018, by ionCube Ltd.
    with Zend Guard Loader v3.3, Copyright (c) 1998-2013, by Zend Technologies

Which PHP am I using

The which command returns the location of the program. Sometimes the path is just a link. The ls -l command returns where the link points to. The ls -d command returns the PHP versions that are available on the the system.

$ which php
 /usr/local/bin/php

$ ls -l /usr/local/bin/php
lrwxrwxrwx 1 root root 18 Jun 26  2018 /usr/local/bin/php -> /opt/php54/bin/php*

$ ls -d /opt/php* 
/opt/php52/  /opt/php53/  /opt/php54/  /opt/php55/  /opt/php56/  /opt/php70/  /opt/php71/  /opt/php_with_imap_client/  /opt/phpcur@  /opt/phpedge@  /opt/phpstable@

Change PHP Version

One way to change the PHP version is to create an alias. In the following example php -v returns the current version. The alias php="/opt/php71/bin/php" command defines an alias for php. The php -v command shows the PHP version changed to 7.1.14. The unalias command removes the alias and the PHP version changes back to 5.4.45.


$ php -v
 PHP 5.4.45 (cli) (built: Apr 17 2017 15:59:08)

$ alias php="/opt/php71/bin/php"

$ php -v
 PHP 7.1.14 (cli) (built: Feb 23 2018 18:28:03) ( NTS )

$ unalias php

$ php -v
 PHP 5.4.45 (cli) (built: Apr 17 2017 15:59:08) 

Another way to change the version is to add the desired version to the beginning of the PATH using the assignment PATH=/opt/php56/bin:$PATH. The php -v and which php show the version correctly changed. One way to undo this change is to use the sed command as shown in the example. Another way is to exit the terminal and start a new terminal.

I prefer this method. The alias doesn't seem to always work for me.


$ PATH=/opt/php56/bin:$PATH

$ which php
 /opt/php56/bin/php

$ php -v
 PHP 5.6.30 (cli) (built: Mar 27 2017 11:48:20)

$ echo $PATH
 /opt/php56/bin/php:/usr/local/jdk/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin

$ PATH=`echo $PATH |sed -e 's/[^:]*://'`

$ echo $PATH
/usr/local/jdk/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin

$ php -v
 PHP 5.4.45 (cli) (built: Apr 17 2017 15:59:08)

The above alias and PATH statements were run from the command line and the PHP version change will be lost when the terminal is closed. To make these changes permanent put them into the ~/.bashrc startup script.

Script Tags <? .. ?>

The PHP closing script tag ?> is not required in any PHP script. It is often best not to close a script because blank lines after the close are transmitted to the browser and may cause unexpected, difficult to debug, behavior. None of my example scripts have a closing tag.

The PHP open tag <? or <?php is required in CGI mode. It is not required in CLI mode when the -r command line option, like this php -r script.php.

Arguments $argv and $argc

PHP uses the global variables $argv and $argc for command-line arguments as shown in the following example.

#!/usr/bin/php -q
<?
echo "hello\n";
echo "argc = $argc\n";
echo "count = " . count($argv) . "\n";
echo "sizeof = " . sizeof($argv) . "\n";
$i = 0;
foreach ($argv as $arg) {
  echo "argv[$i] = '$arg'\n";
  $i++;
}

Array $argv contains the list of arguments. The first item, $argv[0], contains the name of the PHP script. $argc indicates the number of arguments in $argv and is the same as count($argv) or sizeof($argv).


$ hello.php cat dog
hello
argc = 3
count = 3
sizeof = 3
argv[0] = './hello.php'
argv[1] = 'cat'
argv[2] = 'dog'

PHP Functions & Commands