20.3.1 Problem
You want to parse program options that may be
specified as short or long options, or they may be grouped.
20.3.2 Solution
Use PEAR's
Console_Getopt class. Its getopt( ) method can parse both
short-style options such as -a or -b and long-style options
such as --alice or --bob:
$o = new Console_Getopt;
// accepts -a, -b, and -c
$opts = $o->getopt($_SERVER['argv'],'abc');
// accepts --alice and --bob
$opts = $o->getopt($_SERVER['argv'],'',array('alice','bob'));
20.3.3 Discussion
To parse short-style options, pass Console_Getopt::getopt(
) the array of command-line arguments and a string specifying valid
options. This example allows -a, -b, or -c as
arguments, alone or in groups:
$o = new Console_Getopt; $opts = $o->getopt($_SERVER['argv'],'abc');
For the previous option string abc, these are valid
sets of options to pass:
% program.php -a -b -c % program.php -abc % program.php -ab -c
The getopt( ) method returns an array. The first
element in the array is a list of all of the parsed options that were specified
on the command line, along with their values. The second element is any
specified command-line option that wasn't in the argument specification passed
to getopt( ). For example, if the previous program is run as:
% program.php -a -b sneeze
then $opts is:
Array
(
[0] => Array
(
[0] => Array
(
[0] => a
[1] =>
)
[1] => Array
(
[0] => b
[1] =>
)
)
[1] => Array
(
[0] => program.php
[1] => sneeze
)
)
Put a colon after an option in the specification string to
indicate that it requires a value. Two colons means the value is optional. So,
ab:c:: means that a can't have a value, b must, and
c can take a value if specified. With this specification string,
running the program as:
% program.php -a -b sneeze
makes $opts:
Array
(
[0] => Array
(
[0] => Array
(
[0] => a
[1] =>
)
[1] => Array
(
[0] => b
[1] => sneeze
)
)
[1] => Array
(
[0] => program.php
)
)
Because sneeze is now set as the value of b,
it is no longer in the array of unparsed options. Note that the array of
unparsed options always contains the name of the program.
To parse long-style arguments, supply getopt( ) with
an array that describes your desired arguments. Put each argument in an array
element (leave off the leading --) and follow it with = to
indicate a mandatory argument or = = to indicate an optional argument.
This array is the third argument to getopt( ). The second argument (the
string for short-style arguments) can be left blank or not, depending on whether
you also want to parse short-style arguments. This example allows debug
as an argument with no value, name with a mandatory value, and
size with an optional value:
require 'Console/Getopt.php';
$o = new Console_Getopt;
$opts = $o->getopt($_SERVER['argv'],'',array('debug','name=','size=='));
These are valid ways to run this program:
% program.php --debug % program.php --name=Susannah % program.php --name Susannah % program.php --debug --size % program.php --size=56 --name=Susannah % program.php --name --debug
The last example is valid (if counterproductive) because it
treats --debug as the value of the name argument and doesn't
consider the debug argument to be set. Values can be separated from
their arguments on the command line by either a = or a space.
For long-style arguments, getopt( ) includes the
leading -- in the array of parsed arguments; for example, when run as:
% program.php --debug --name=Susannah
$opts is set to:
Array
(
[0] => Array
(
[0] => Array
(
[0] => --debug
[1] =>
)
[1] => Array
(
[0] => --name
[1] => Susannah
)
)
[1] => Array
(
[0] => program.php
)
)
We've been using $_SERVER['argv'] as the array of
command-line arguments, which is fine by default. Console_Getopt provides a method,
readPHPArgv( ), to look also in $argv and
$HTTP_SERVER_VARS['argv'] for command-line arguments. Use it by passing
its results to getopt( ):
require 'Console/Getopt.php';
$o = new Console_Getopt;
$opts = $o->getopt($o->readPHPArgv(),'',array('debug','name=','size=='));
Both getopt( ) and readPHPArgv( ) return a
Getopt_Error object when these encounter an error; for example, having
no option specified for an option that requires one. Getopt_Error extends
the PEAR_Error base class, so you can use familiar methods to handle
errors:
require 'Console/Getopt.php';
$o = new Console_Getopt;
$opts = $o->getopt($o->readPHPArgv(),'',array('debug','name=','size=='));
if (PEAR::isError($opts)) {
print $opts->getMessage();
} else {
// process options
}