When calling a PHP script from the command line you can use $argc to find out how many parameters are passed and $argv to access them. For example running the following script:
<?php
var_dump($argc); //number of arguments passed
var_dump($argv); //the arguments passed
?>
Like this:-
php script.php arg1 arg2 arg3
Will give the following output
int(4)
array(4) {
[0]=>
string(21) "d:\Scripts\script.php"
[1]=>
string(4) "arg1"
[2]=>
string(4) "arg2"
[3]=>
string(4) "arg3"
}
See $argv and $argc for further details.
To do what you want, lets say
php script.php arg1=4
You would need to explode the argument on the equals sign:-
list(
val) = explode('=', $argv[1]);
var_dump(array(
val));
That way you can have whatever you want in front of the equals sign without having to parse it, just check the key=>value pairs are correct. However, that is all a bit of a waste, just instruct the user on the correct order to pass the arguments.
Answer from vascowhite on Stack OverflowWhen calling a PHP script from the command line you can use $argc to find out how many parameters are passed and $argv to access them. For example running the following script:
<?php
var_dump($argc); //number of arguments passed
var_dump($argv); //the arguments passed
?>
Like this:-
php script.php arg1 arg2 arg3
Will give the following output
int(4)
array(4) {
[0]=>
string(21) "d:\Scripts\script.php"
[1]=>
string(4) "arg1"
[2]=>
string(4) "arg2"
[3]=>
string(4) "arg3"
}
See $argv and $argc for further details.
To do what you want, lets say
php script.php arg1=4
You would need to explode the argument on the equals sign:-
list(
val) = explode('=', $argv[1]);
var_dump(array(
val));
That way you can have whatever you want in front of the equals sign without having to parse it, just check the key=>value pairs are correct. However, that is all a bit of a waste, just instruct the user on the correct order to pass the arguments.
I use this fairly concise method:
if($argc>1)
parse_str(implode('&',array_slice($argv, 1)), $_GET);
Which would handle a call such as:
php script.php item1=4 item2=300
By sending it into $_GET you automatically handle web or CLI access.
For commentary, this is doing the following:
- If the count of arguments is greater than one (as first item is the name of the script) then proceed
- Grab the arguments array excluding first item
- Turn it into a standard query string format with ampersands
- use
parse_strto extract to the$_GETarray
Which PHP binary are you using? The CLI or CGI? I suspect you need a CGI version of the binary for PHP to properly handle accept the environment variables and POST data if you pass that.
The php-cgi binary implements the CGI interface, which allows you to pass parameters on the command line:
php-cgi -f index.php left=1058 right=1067 class=A language=English
Which end up in $_GET:
Array
(
[left] => 1058
[right] => 1067
[class] => A
[language] => English
)
You may want to read up on how CGI works so you can implement that in your web server.
Ref: RFC3875
According to Wikipedia, the answer is to set the QUERY_STRING environment variable:
QUERY_STRING='user=foo&pass=bar&left=1234' php-cgi index.php
or in separate steps:
export QUERY_STRING='user=foo&pass=bar&left=1234'
php-cgi index.php
This works if you use the php-cgi command, because this is part of the CGI specification. The ordinary php command ignores this variable, but your script might use it.
You call a script with parameters like this:
php prog.php DBF=clients
No HTTP request is made, so $_GET etc. will not be available. As stated in the PHP documentation for CLI usage $argv will hold the parameters for your script.
$argv[0] is the script name itself, $argv[1] is the first parameter etc.
parse_str() the parameter:
#!/usr/bin/php
<?php
// $argv[0] will hold the script name
// $argv[1] will hold the first argument
// print_r($argv[1]);
// parse the first argument
parse_str($argv[1], $arg);
// print_r($arg);
if(isset($arg['DBF']) && $arg['DBF'] == 'clients') {
// Do something for the clients
echo "Clients stuff";
echo "\n";
} else if(isset($arg['DBF']) && $arg['DBF'] == 'suppliers') {
// Do something for the suppliers
echo "Suppliers stuff";
echo "\n";
}
The $_GET and $_POST variables are superglobals that are created only when PHP is being used to process web requests via a server like Apache.
If you are running PHP from the command line, you can add your variable "DBF" as an argument after the script name:
$ php prog.php clients
To access commandline variables, call the $argv variable, which is an array. The first item in the array is the name of the script, and the following items are whatever arguments you appended to the command line request:
array(2) {
[0]=>
string(8) "prog.php"
[1]=>
string(4) "clients"
}
Reference: https://www.php.net/manual/en/reserved.variables.argv.php
The ?type=daily argument (ending up in the $_GET array) is only valid for web-accessed pages.
You'll need to call it like php myfile.php daily and retrieve that argument from the $argv array (which would be $argv[1], since $argv[0] would be myfile.php).
If the page is used as a webpage as well, there are two options you could consider. Either accessing it with a shell script and Wget, and call that from cron:
#!/bin/sh
wget http://location.to/myfile.php?type=daily
Or check in the PHP file whether it's called from the command line or not:
if (defined('STDIN')) {
$type = $argv[1];
} else {
$type = $_GET['type'];
}
(Note: You'll probably need/want to check if $argv actually contains enough variables and such)
Just pass it as normal parameters and access it in PHP using the $argv array.
php myfile.php daily
and in myfile.php
$type = $argv[1];
Arguments, made easy
One day I decided to defeat this monster once and for all. I forged a secret weapon - a function that acts as a storage, a parser and a query function for arguments.
// define your arguments with a multiline string, like this:
arg('
-q --quiet-mode bool Suppress all error messages
-f --filename str Name of your input document
-m --max-lines int Maximum number of lines to read
');
$argText = arg("??"); // removes bool/int/etc column
print "
Syntax:
$argText
";
// then read any value like this:
$maxLines = arg("max-lines",99);
$filename = arg("filename");
$stfuMode = arg("quiet-mode");
// let's see what we got
printf("Value of --max-lines: %s\n",$maxLines);
printf("Value of --quiet-mode: %s\n",$stfuMode);
printf("Value of first unnamed argument: %s\n",arg(1));
Explanation
All you need to do is write the argument list as a multiline string. Four columns, looks like a help, but
arg()parses your lines and finds out the arguments automatically.Separate columns by two or more spaces - just like you would anyway.
Once parsed, each item will be represented by an array of fields, named char, word, type and help, respectively. If there's no short (char) or long (word) version for a parameter, just use a dash. Not for both, obviously.
Types are what they seem: bool means there's no value after the parameter; it's false if missing, true if present. The int and str types mean there must be a value, and int makes sure it's an integer. Optional parameters are not supported. Values can be separated by space or equal sign (i.e. "-a=4" or "-a 4")
After this first call, you have all your arguments neatly organized in a structure (dump it, you'll see) and you can query their values by name or number.
Function arg() has a second parameter for defaults so you'll never have to worry about missing values.
With the argument "??", as you see in the example, you get back a string that your command line tool can use as a help with arguments. Gone are the days when you had to keep those two in sync.
The arg() function itself
function arg($x="",$default=null) {
static $argtext = "";
static $arginfo = [];
/* helper */ $contains = function($h,$n) {return (false!==strpos($h,$n));};
/* helper */ $valuesOf = function($s) {return explode(",",$s);};
// called with a multiline string --> parse arguments
if($contains($x,"\n")) {
// parse multiline text input
$argtext = $x;
$args = $GLOBALS["argv"] ?: [];
$rows = preg_split('/\s*\n\s*/',trim($x));
$data = $valuesOf("char,word,type,help");
foreach($rows as $row) {
list($char,$word,$type,$help) = preg_split('/\s\s+/',$row);
$char = trim($char,"-");
$word = trim($word,"-");
$key = $word ?: $char ?: ""; if($key==="") continue;
$arginfo[$key] = compact($data);
$arginfo[$key]["value"] = null;
}
$nr = 0;
while($args) {
$x = array_shift($args); if($x[0]<>"-") {$arginfo[$nr++]["value"]=$x;continue;}
$x = ltrim($x,"-");
$v = null; if($contains($x,"=")) list($x,$v) = explode("=",$x,2);
$k = "";foreach($arginfo as $k=>$arg) if(($arg["char"]==$x)||($arg["word"]==$x)) break;
$t = $arginfo[$k]["type"];
switch($t) {
case "bool" : $v = true; break;
case "str" : if(is_null($v)) $v = array_shift($args); break;
case "int" : if(is_null($v)) $v = array_shift($args); $v = intval($v); break;
}
$arginfo[$k]["value"] = $v;
}
return $arginfo;
}
if($x==="??") {
$help = preg_replace('/\s(bool|int|str)\s+/'," ",$argtext);
return $help;
}
// called with a question --> read argument value
if($x==="") return $arginfo;
if(isset($arginfo[$x]["value"])) return $arginfo[$x]["value"];
return $default;
}
I hope this helps a lot of lost souls out there, like I was. May this little function shed a light upon the beauty of not having to write a help AND a parser and keeping them in sync... Also, once parsed, this approach is lightning fast since it caches the variables so you can call it as many times as you want. It acts like a superglobal.
Also available on my GitHub Gist.
You can retrieve the "raw" arguments using $argv. See also: http://www.php.net/manual/de/reserved.variables.argv.php
Example: php file.php a b c
$argv will contain "file.php", "a", "b" and "c".
Use getopts to get the parameters "parsed", PHP will do the dirty job for you. So it's probably the best way to go in your case as you want to pass the parameters with --options.
Have a close look at http://www.php.net/manual/de/function.getopt.php
It describes the function well.