I want to run a PHP script from the command line, but I also want to set a variable for that script.
Browser version: script.php?var=3
Command line: php -f script.php (but how do I give it the variable containing 3?)
Script:
<?php
// number of arguments passed to the script
var_dump($argc);
// the arguments as an array. first argument is always the script name
var_dump($argv);
Command:
$ php -f test.php foo bar baz
int(4)
array(4) {
[0]=>
string(8) "test.php"
[1]=>
string(3) "foo"
[2]=>
string(3) "bar"
[3]=>
string(3) "baz"
}
Also, take a look at using PHP from the command line.
If you want to keep named parameters almost like var=3&foo=bar (instead of the positional parameters offered by $argv) getopt() can assist you.
Besides argv (as Ionut mentioned), you can use environment variables:
E.g.:
var = 3 php -f test.php
In test.php:
$var = getenv("var");
As well as using argc and argv as indicated by Ionut G. Stan, you could also use the PEAR module Console_Getopt which can parse out unix-style command line options. See this article for more information.
Alternatively, there's similar functionality in the Zend Framework in the Zend_Console_Getopt class.
A lot of solutions put the arguments into variables according to their order. For example,
myfile.php 5 7
will put the 5 into the first variable and 7 into the next variable.
I wanted named arguments:
myfile.php a=1 x=8
so that I can use them as variable names in the PHP code.
The link that Ionuț G. Stan gave at
http://www.php.net/manual/en/features.commandline.php
gave me the answer.
sep16 at psu dot edu:
You can easily parse command line arguments into the $_GET variable by using the parse_str() function.
<?php
parse_str(implode('&', array_slice($argv, 1)), $_GET);
?>
It behaves exactly like you'd expect with cgi-php.
$ php -f somefile.php a=1 b[]=2 b[]=3
This will set $_GET['a'] to '1' and $_GET['b'] to array('2', '3').
Related
I found some questions about processing an ini/bash file.
For example: Best/easiest way to parse configuration parameters in Sh/Bash and php
However they doesn't take in account other kind of assignments like:
arrays:
stuff=( "foo" "bar" "donald duck" "mickey mouse" )
variables calling another variable:
foobar = "bartender"
foo = "$foobar give me a beer!"
possible other things I'm not figuring them atm
Instead of parsing the variables in php side i was thinking instead of using a shell script processing an input config.sh file and prepare a vars.php files already written in php language.
So an array like the one above will be converted in $stuff = array ("foo", "bar", "donald duck", "mickey mouse" ) and the other variables like $foo = "bartender give me a beer!"
But how is possible export via bash the variables definied into a shell script in an efficient way ? Has bash something like php $GLOBALS in order to cycle throught the definied vars ?
I think also an intelligent bash script "sh variables to json" could work, so that the json could be parsed in php after :)
To be more clear, I'm writing a set of scripts that are based on a config.sh file. But, i have a slight amount of php scripts also that need the same configuration, that's why I tought would have been easier prepend all my php script with a parse of the config.sh file so I can use the same vars I have in bash also in php.
While some parser of ini/bash definition exists they are mere literal parser without taking in account variables inside other variables and arrays.
example.php:
$args = __FILE__.' -vvv';
$argv = explode(' ', $args);
$argc = count($argv);
$GLOBALS['argv'] = $_SERVER['argv'] = $argv;
$GLOBALS['argc'] = $_SERVER['argc'] = $argc;
var_export(getopt('v'));
$ example.php -v
> array('v' => false);
Eventually getopt does not look up to $GLOBALS to get argv. So it there any way I can override argv array?
TL;DR
No, there is no native way to do this. Depending of your goals there may be other ways to resolve the issue, but overriding is not one of them.
Operating on super-globals
Structure
To realize why it is so, you should know, that super-globals are not just "variables" to which you are referring. That means, if you are using $argv to de-reference arguments list, it does not mean that you'll access some data which is stored in "variable" $argv. Instead, you'll access to data container by "link", called $argv. However, there are different ways to access this data - $_SERVER['argv'] or $GLOBALS array at least. To illustrate, I'll go with the code:
var_dump($argv, $_SERVER['argv']);
unset($argv);
var_dump($argv, $_SERVER['argv']);
This will result in something like:
array(2) {
[0]=>
string(11) "example.php"
[1]=>
string(4) "-vvv"
}//<--------------------- derived from $argv
array(2) {
[0]=>
string(11) "example.php"
[1]=>
string(4) "-vvv"
}//<--------------------- derived from $_SERVER['argv']
NULL//<------------------ we've unset $argv, so unset a reference
array(2) {
[0]=>
string(11) "example.php"
[1]=>
string(4) "-vvv"
}//<--------------------- but data is still there and available via another reference
Internally
As you can see, the reference can be destroyed, but actual data will remain untouched. That will be stored in symbols table. Many PHP functions are accessing this structure to retrieve data, and getopt() is not an exception. So the conclusion is - yes, you can modify the reference (or even destroy it), but actual data will be still in super-globals.
getopt()
Now, about this function. Just take a look at its implementation:
/* Get argv from the global symbol table. We calculate argc ourselves
* in order to be on the safe side, even though it is also available
* from the symbol table. */
if (PG(http_globals)[TRACK_VARS_SERVER] &&
(zend_hash_find(HASH_OF(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv"), (void **) &args) != FAILURE ||
zend_hash_find(&EG(symbol_table), "argv", sizeof("argv"), (void **) &args) != FAILURE) && Z_TYPE_PP(args) == IS_ARRAY
)
{
//...omitted
}
It's clearly stated, that it will try to search "argv" in symbol_table (if you want - here's a link to - how it will be done exactly). And that means - it will access actual data, thus, overriding it externally will have no effect.
As a result - getopt() will work with data which were gathered at script startup, and that data will contain actual parameters, no matter if you'll override them inside your script.
Following is my command line arguments:
php a.php -g UAMS ABC
Now when I get command from command line using getopt then I am getting only first argument i.e UAMS. I want to get both arguments i.e UAMS and ABC.
Following is my piece of code to get argument throug getopt() function.
$options=getopt("g");
echo "Options: ".json_encode($options);
I am only getting UAMS.
When I give argument like
php a.php -g a/b/c
Then I get arguments through getopt then it gives output as a\/b\/c?
So why it is not giving correct answer?
"g" is an option without values "g:" would be one with an optional value. See http://de.php.net/getopt
The backslashes are from json_encode().
I want to pass parameters from PHP Command Line Interface, and then read in the values using PHP script, something like this:
<?php
$name1 = $argv[1];
echo $name1;
?>
I pass the variable from CLI like this:
C:\xampp\php\php.exe name.php Robby
The above works, I get Robby as the output.
But I want to do something like this:
C:\xampp\php\php.exe name.php -inputFirstName="Robby"
So that the user is well informed to enter the correct parameters in the correct places. What is the appropriate way to parse these parameters?
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($key, $val) = explode('=', $argv[1]);
var_dump(array($key=>$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) the proceed
Grab the arguments array excluding first item
Turn it into a standard query string format with ampersands
use parse_str to extract to the $_GET array
While the answer is correct and you could do the parsing by hand, PHP also offers the getopt() function that might actually provide useful here.
There's also object-oriented alternatives (written in PHP, available in a number of libraries) that might turn out to be what you need. Googling for "php getopt" will yield helpful results.
you can send parameters as one argument then parse that argument like a $_GET array
C:\xampp\php\php.exe name.php "inputFirstName=Robby&LastName=John"
and in your PHP file
if (!empty($argv[1])) {
parse_str($argv[1], $_GET);
}
you'll get arguments in $_GET array like usual
The getopt() function is probably the most correct answer in the case of the question. Especially since it was made platform independent with PHP 5.3. In the particular case of this question and parsing multiple parameters, one way to leverage this function would be as follows:
$defaultValues = array("inputFirstName" => "");
$givenArguments = getopt("", array("inputFirstName:"));
$options = array_merge($defaultValues, $givenArguments);
$inputFirstName = $options['inputFirstName'];
The call to set $inputFirstName with the value "Robby" would be:
> php script.php --inputFirstName="Robby"
Explanation
Default values for all expected parameters are set in the $defaultValues array. Input sent through via command line arguments are collected by PHP's getopt function and stored by the $givenArguments. Note that the colon (:) at the end of the "inputFirstName:" string indicates that this is a required argument. Without a colon here, only the presence of the argument would be detected, not the actual value (more information in the PHP Manual). Merging these two arrays together on the third line results in array with all expected parameters being set with either default values or arguments provided from the command line/terminal if they are available.
I don't know if at the time this question has being asked what i going to answer to it was available but if you call php-cgi -f myfile.php var=something you can retrieved whit $var=$_GET['var']; from the command line then you don't have to change your code to call it from the web browser or the command line
If you don't mind using a library, I suggest you take a look at The Console Component by Symfony.
It can be used to create command line applications and supports the use of Arguments & Options.
The documentation page contains a couple of excellent examples to get you started.
Of course under the hood it uses the same techniques as explained by vascowhite.
your best hope is to use
exec("php -f php.file.php example=js.json > ech0");
echo file_get_contents("ech0");
unlink("ech0");
That's what I use in PipesJS
You can parse the user input on your program looking for specific strings such as -inputFirstName="x" (using regular expressions, for example) and then set the correct variable to x.
I'm trying to run PHP from the command line under Windows XP.
That works, except for the fact that I am not able to provide parameters to my PHP script.
My test case:
echo "param = " . $param . "\n";
var_dump($argv);
I want to call this as:
php.exe -f test.php -- param=test
But I never get the script to accept my parameter.
The result I get from the above script:
PHP Notice: Undefined variable: param in C:\test.php on line 2
param = ''
array(2) {
[0]=> string(8) "test.php"
[1]=> string(10) "param=test"
}
I am trying this using PHP 5.2.6. Is this a bug in PHP 5?
The parameter passing is handled in the online help:
Note: If you need to pass arguments to your scripts you need to pass -- as the first argument when using the -f switch.
This seemed to be working under PHP 4, but not under PHP 5.
Under PHP 4 I could use the same script that could run on the server without alteration on the command line. This is handy for local debugging, for example, saving the output in a file, to be studied.
Why do you have any expectation that param will be set to the value?
You're responsible for parsing the command line in the fashion you desire, from the $argv array.
You can use the getopt() function.
Check blog post PHP CLI script and Command line arguments.
The parameter passing is handled in the online help Note: If you need to pass arguments to your scripts you need to pass -- as the first argument when using the -f switch. This seemed to be working under PHP 4, but not under PHP 5.
But PHP still doesn't parse those arguments. It just passes them to the script in the $argv array.
The only reason for the -- is so that PHP can tell which arguments are meant for the PHP executable and which arguments are meant for your script.
That lets you do things like this:
php -e -n -f myScript.php -- -f -n -e
(The -f, -n, and -e options after the -- are passed to file myScript.php. The ones before are passed to PHP itself).
If you want to pass the parameters similar to GET variables, then you can use the parse_str() function. Something similar to this:
<?php
parse_str($argv[1]);
?>
Would produce a variable, $test, with a value of <myValue>.
PHP does not parameterize your command line parameters for you. See the output where your second entry in ARGV is "param=test".
You most likely want to use the PEAR package Console_CommandLine: "A full featured command line options and arguments parser".
Or you can be masochistic and add code to go through your ARGV and set the parameters yourself. Here's a very simplistic snippet to get you started (this won't work if the first part isn't a valid variable name or there is more than 1 '=' in an ARGV part:
foreach($argv as $v) {
if(false !== strpos($v, '=')) {
$parts = explode('=', $v);
${$parts[0]} = $parts[1];
}
}
Command-line example:
php myserver.php host=192.168.1.4 port=9000
In file myserver.php, use the following lines:
<?php
parse_str(implode('&', array_slice($argv, 1)), $_GET);
// Read arguments
if (array_key_exists('host', $_GET))
{
$host = $_GET['host'];
}
if (array_key_exists('port', $_GET))
{
$port = $_GET['port'];
}
?>
$argv is an array containing all your commandline parameters... You need to parse that array and set $param yourself.
$tmp = $argv[1]; // $tmp="param=test"
$tmp = explode("=", $tmp); // $tmp=Array( 0 => param, 1 => test)
$param = $tmp[1]; // $param = "test";
You can do something like:
if($argc > 1){
if($argv[1] == 'param=test'){
$param = 'test';
}
}
Of course, you can get much more complicated than that as needed.
If you like living on the cutting edge, PHP 5.3 has the getOpt() command which will take care of all this messy business for you. Somewhat.
You could use something like
if (isset($argv[1]) {
$arg1 = $argv[1];
$arg1 = explode("=", $arg1);
$param = $arg1[1];
}
(How to handle the lack of parameters is up to you.)
Or if you need a more complex scenario, look into a command-line parser library, such as the one from Pear.
Using the ${$parts[0]} = $parts[1]; posted in another solution lets you override any variable in your code, which doesn’t really sound safe.
You can use the $argv array. Like this:
<?php
echo $argv[1];
?>
Remember that the first member of the $argv array (which is $argv[0]) is the name of the script itself, so in order to use the parameters for the application, you should start using members of the $argv[] from the '1'th index.
When calling the application, use this syntax:
php myscript.php -- myValue
There isn't any need to put a name for the parameter. As you saw, what you called the var_dump() on the $argv[], the second member (which is the first parameter) was the string PARAM=TEST. Right? So there isn't any need to put a name for the param. Just enter the param value.