PHP Unconference Europe 2015

getopt

(PHP 4 >= 4.3.0, PHP 5)

getoptObtém opções da lista de argumentos da linha de comando

Descrição

array getopt ( string $options [, array $longopts ] )

Retorna uma matriz associativa das opções/argumentos baseada no formato especificado no parâmetro options, ou FALSE em caso de erro.

Parâmetros

options

O parâmetro options deve conter os seguintes elementos: caracteres individuais, e caracteres individuais seguidos por dois pontos para indicar uma opção com um argumento a seguir. Por exemplo, a string de opção x reconhece uma opção -x, e uma string de opção x: reconhece uma opção e um argumento -x argumento. Não importa se o argumento tem espaço no início.

longopts

Valor Retornado

Esta função irá retornar uma matriz de opções/argumentos . Se uma opção não tiver argumento o valor definido será FALSE.

Changelog

Versão Descrição
5.3.0 Esta função não depende mais do sistema e funcionando também em Windows.

Exemplos

Exemplo #1 Exemplo da getopt()

<?php
// parse the command line ($GLOBALS['argv'])
$options getopt("f:hp:");
?>

add a note add a note

User Contributed Notes 15 notes

up
10
chris at tiny dot net
10 years ago
"phpnotes at kipu dot co dot uk" and "tim at digicol dot de" are both wrong or misleading.  Sean was correct.  Quoted space-containing strings on the command line are one argument.  It has to do with how the shell handles the command line, more than PHP.  PHP's getopt() is modeled on and probably built upon the Unix/POSIX/C library getopt(3) which treats strings as strings, and does not break them apart on white space.

Here's proof:

$ cat opt.php
#! /usr/local/bin/php
<?php
$options
= getopt("f:");
print_r($options);
?>
$ opt.php -f a b c
Array
(
    [f] => a
)
$ opt.php -f 'a b c'
Array
(
    [f] => a b c
)
$ opt.php -f "a b c"
Array
(
    [f] => a b c
)
$ opt.php -f a\ b\ c
Array
(
    [f] => a b c
)
$
up
5
ch1902
1 year ago
Sometimes you will want to run a script from both the command line and as a web page, for example to debug with better output or a command line version that writes an image to the system but a web version that prints the image in the browser. You can use this function to get the same options whether passed as command line arguments or as $_REQUEST values.

<?php
/**
* Get options from the command line or web request
*
* @param string $options
* @param array $longopts
* @return array
*/
function getoptreq ($options, $longopts)
{
   if (
PHP_SAPI === 'cli' || empty($_SERVER['REMOTE_ADDR']))  // command line
  
{
      return
getopt($options, $longopts);
   }
   else if (isset(
$_REQUEST))  // web script
  
{
     
$found = array();

     
$shortopts = preg_split('@([a-z0-9][:]{0,2})@i', $options, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
     
$opts = array_merge($shortopts, $longopts);

      foreach (
$opts as $opt)
      {
         if (
substr($opt, -2) === '::'// optional
        
{
           
$key = substr($opt, 0, -2);

            if (isset(
$_REQUEST[$key]) && !empty($_REQUEST[$key]))
              
$found[$key] = $_REQUEST[$key];
            else if (isset(
$_REQUEST[$key]))
              
$found[$key] = false;
         }
         else if (
substr($opt, -1) === ':'// required value
        
{
           
$key = substr($opt, 0, -1);

            if (isset(
$_REQUEST[$key]) && !empty($_REQUEST[$key]))
              
$found[$key] = $_REQUEST[$key];
         }
         else if (
ctype_alnum($opt))  // no value
        
{
            if (isset(
$_REQUEST[$opt]))
              
$found[$opt] = false;
         }
      }

      return
$found;
   }

   return
false;
}
?>

Example

<?php
// php script.php -a -c=XXX -e=YYY -f --two --four=ZZZ --five=5
// script.php?a&c=XXX&e=YYY&f&two&four=ZZZ&five=5

$opts = getoptreq('abc:d:e::f::', array('one', 'two', 'three:', 'four:', 'five::'));

var_dump($opts);

/**
array(7) {
  'a' => bool(false)
  'c' => string(3) "XXX"
  'e' => string(3) "YYY"
  'f' => bool(false)
  'two' => bool(false)
  'four' => string(3) "ZZZ"
  'five' => string(1) "5"
}
*/
?>
up
6
uberlinuxguy at tulg dot org
6 years ago
One thing of important note would be that getopt() actually respects the '--' option to end an option list.  Thus given the code:

test.php:
<?php
    $options
= getopt("m:g:h:");
    if (!
is_array($options) ) {
        print
"There was a problem reading in the options.\n\n";
        exit(
1);
    }
   
$errors = array();
   
print_r($options);
?>

And running:

# ./test.php ./run_vfs  -h test1 -g test2 -m test3 -- this is a test -m green

Will return:

Array
(
    [h] => test1
    [g] => test2
    [m] => test3
)

Whereas running:
# /test.php ./run_vfs  -h test1 -g test2 -m test3 this is a test -m green

Will return:

Array
(
    [h] => test1
    [g] => test2
    [m] => Array
        (
            [0] => test3
            [1] => green
        )

)
up
4
mpartap at gmx dot net
4 years ago
Here's another way of removing options found by getopt() from the argv[] array. It handles the different kind of parameters without eating chunks that do not belong to an --option. (-nr foo param1 param2 foo)
<?php
$parameters
= array(
 
'n' => 'noparam',
 
'r:' => 'required:',
 
'o::' => 'optional::',
);

$options = getopt(implode('', array_keys($parameters)), $parameters);
$pruneargv = array();
foreach (
$options as $option => $value) {
  foreach (
$argv as $key => $chunk) {
   
$regex = '/^'. (isset($option[1]) ? '--' : '-') . $option . '/';
    if (
$chunk == $value && $argv[$key-1][0] == '-' || preg_match($regex, $chunk)) {
     
array_push($pruneargv, $key);
    }
  }
}
while (
$key = array_pop($pruneargv)) unset($argv[$key]);
?>
up
1
Damien B.
6 years ago
This is how I handle arguments with getopt: I use switch within a foreach at the beginning of a program.

<?php

$opts
= getopt('hs:');

// Handle command line arguments
foreach (array_keys($opts) as $opt) switch ($opt) {
  case
's':
   
// Do something with s parameter
   
$something = $opts['s'];
    break;

  case
'h':
   
print_help_message();
    exit(
1);
}

print
"$something\n";

?>
up
1
joey at alegria dot co dot jp
8 years ago
There are 2 simpler (and much faster) methods for getting good getopt() operation without creating your own handler.

1. Use the Console_Getopt PEAR class (should be standard in most PHP installations) which lets you specify both short and long form options as well as whether or not arguments supplied to an option are themselves 'optional'. Very simple to use and requires very little code to operate compaired to writing own handler.

2. If you cannot load external PEAR objects, use your shell's getopt() functions (which in BASHs case work very well) to process options and have your shell script then call your PHP script with a rigid argument structure that is very easy for PHP to digest such as:
% myfile.php -a TRUE -b FALSE -c ARGUMENT ...
If the initial arguments are invalid you can have the shell script return an error without calling the PHP script. Sounds convoluted but is a very simple solution and in fact PHP's own % pear command uses this method. /usr/bin/pear is a shell script that does some simle checking before calling pearcmd.php and repassing the arguments on to it.

The second method is by far the best for portability because it allows a single shell script to check a few things like your PHP version and respond acordingly e.g. does it call your PHP4 or PHP5 compatible script? Also, because getopt() is not available on Windows, The second solution allows you to do Windows specific testing as a BAT file (as oposed to BASH, ZSH or Korn on UNIX).
up
1
koenbollen at gnospamail dot com
7 years ago
After you use the getopt function you can use the following script to update the $argv array:
<?php
  $options
= "c:ho:s:t:uvV";
 
$opts = getopt( $options );
  foreach(
$opts as $o => $a )
  {
    while(
$k = array_search( "-" . $o, $argv ) )
    {
      if(
$k )
        unset(
$argv[$k] );
      if(
preg_match( "/^.*".$o.":.*$/i", $options ) )
        unset(
$argv[$k+1] );
    }
  }
 
$argv = array_merge( $argv );
?>
Note: I used the array_merge function to reindex the array's keys.

Cheers, Koen Bollen
up
2
takingsides at gmail dot com
7 months ago
As already mentioned getopt() will stop parsing options upon the '--'.  Sometimes you will have options and arguments but the user may not always provide the explicit -- option.

Below is a quick way to collect options and arguments regardless of the -- consistently.

#!/usr/bin/php
<?php

$options
= getopt('hl::m:v:a', [
   
'help',
   
'list::',
   
'module:',
   
'version:',
   
'all',
]);

var_dump( $options );

$args = array_search('--', $argv);
$args = array_splice($argv, $args ? ++$args : (count($argv) - count($opt)));

var_dump( $args );
?>
up
0
Missingdoc
3 days ago
Just because i found that on Google instead of on official PHP documentation:

The syntax of the longopts array is the following
"option" for an opt without argument
"option=" for an opt with a required argument
"option==" for an opt that may have an argument or not

So for example

$longopts = array("no_argument", "required_argument=", "optional_argument==");
up
0
Anonymous
3 years ago
getopt() only returns the options specified if they were listed in the options.

So you cant make a switch() use default: to complain of an unknown option. :(
up
0
m at ttcarter dot com
5 years ago
I wrote a library some time ago to counter some of the missing features of the rather limited 'getopt' function. The library as well documentation can be found on my website at http://hash-bang.net/2008/12/missing-php-functions-getopts/

It provides functionality for long switches (e.g. '--delete'), incrementing switches (e.g. '-v -v -v' or '-vvv' for very, very verbose), long values (e.g. '--exclude this.file') and lots more.
up
0
mbirth at webwriters dot de
6 years ago
After getopt() of PHP5.3.0 (on Windows) ignored some parameters if there was a syntactical problem, I decided to code my own generic parameter parser.

<?php
   
/**
     * Parses $GLOBALS['argv'] for parameters and assigns them to an array.
     *
     * Supports:
     * -e
     * -e <value>
     * --long-param
     * --long-param=<value>
     * --long-param <value>
     * <value>
     *
     * @param array $noopt List of parameters without values
     */
   
function parseParameters($noopt = array()) {
       
$result = array();
       
$params = $GLOBALS['argv'];
       
// could use getopt() here (since PHP 5.3.0), but it doesn't work relyingly
       
reset($params);
        while (list(
$tmp, $p) = each($params)) {
            if (
$p{0} == '-') {
               
$pname = substr($p, 1);
               
$value = true;
                if (
$pname{0} == '-') {
                   
// long-opt (--<param>)
                   
$pname = substr($pname, 1);
                    if (
strpos($p, '=') !== false) {
                       
// value specified inline (--<param>=<value>)
                       
list($pname, $value) = explode('=', substr($p, 2), 2);
                    }
                }
               
// check if next parameter is a descriptor or a value
               
$nextparm = current($params);
                if (!
in_array($pname, $noopt) && $value === true && $nextparm !== false && $nextparm{0} != '-') list($tmp, $value) = each($params);
               
$result[$pname] = $value;
            } else {
               
// param doesn't belong to any option
               
$result[] = $p;
            }
        }
        return
$result;
    }
?>

A call like: php.exe -f test.php -- alfons -a 1 -b2 -c --d 2 --e=3=4 --f "alber t" hans wurst

and an in-program call parseParameters(array('f')); would yield in a resulting array:

Array
(
    [0] => alfons
    [a] => 1
    [b2] => 1
    [c] => 1
    [d] => 2
    [e] => 3=4
    [f] => 1
    [1] => alber t
    [2] => hans
    [3] => wurst
)

As you can see, values without an identifier are stored with numeric indexes. Existing identifiers without values get "true".
up
0
Francois Hill
6 years ago
Although very interesting, koenbollen at gnospamail dot com's update of the argv array fails when option values follow the option with no space :
Indeed
    php MyScript.php5 -t5
and
    php MyScript.php5 -t 5
with $options="t:" are treated as the same by getopt.

This upgraded function should take care of it :

File : shift_test.php5
<?php
   
function shift($options_array)
    {
        foreach(
$options_array as $o => $a )
        {
           
// Look for all occurrences of option in argv and remove if found :
            // ----------------------------------------------------------------
            // Look for occurrences of -o (simple option with no value) or -o<val> (no space in between):
           
while($k=array_search("-".$o.$a,$GLOBALS['argv']))
            {   
// If found remove from argv:
               
if($k)
                    unset(
$GLOBALS['argv'][$k]);
            }
           
// Look for remaining occurrences of -o <val> (space in between):
           
while($k=array_search("-".$o,$GLOBALS['argv']))
            {   
// If found remove both option and value from argv:
               
if($k)
                {    unset(
$GLOBALS['argv'][$k]);
                    unset(
$GLOBALS['argv'][$k+1]);
                }
            }
        }
       
// Reindex :
       
$GLOBALS['argv']=array_merge($GLOBALS['argv']);
    }

   
print_r($argv);
   
$options_array=getopt('t:h');
   
shift($options_array);
   
print_r($argv);
?>

>php shift_test.php5 -h -t4 param1 param2
will ouptut :
Array
(
    [0] => test.php5
    [1] => -h
    [2] => -t4
    [3] => param1
    [4] => param2
)
Array
(
    [0] => test.php5
    [1] => param1
    [2] => param2
)

>php shift_test.php5 -h -t 4 param1 param2
will ouptut :
Array
(
    [0] => test.php5
    [1] => -h
    [2] => -t
    [3] => 4
    [4] => param1
    [5] => param2
)
Array
(
    [0] => test.php5
    [1] => param1
    [2] => param2
)
up
-1
geoff at gosquared dot com
4 years ago
It seems under PHP 5.3.2, getopt() makes a script fail to load if called via HTTP without any conditions. You'll need something like if(isset($_SERVER['argc'])) $args = getopt(); to prevent that.
up
-1
Anonymous
7 years ago
About getopt(String):
Parses the command-line arguments into an associative array, using the function's String parameter to specify arguments and options, thus:
* arguments are specified as any letter followed by a colon, e.g. "h:".
* arguments are returned as "h" => "value".
* options are specified as any letter not followed by a colon, e.g. "r".
* options are returned as "r" => (boolean) false.

Also note that:
1) Options or arguments not passed in the command-line parameters are not set in the returned associative array.
2) Options or arguments present in the command-line arguments multiple times are returned as an enumerated array within the returned associative array.
To Top