When executing PHP scripts through CLI while simulating web server behavior, developers often encounter empty $_GET arrays despite passing query parameters in URLs. This occurs because PHP's CLI mode doesn't automatically parse HTTP-style query strings.
In standard web server environments (like Apache/Nginx), query parameters from URLs (e.g., index.php?foo=bar
) automatically populate $_GET
. However, in CLI mode:
php script.php?param=value // Doesn't work
php -r "echo $_GET['param'];" // Returns undefined index
Method 1: Simulating $_GET via Command Arguments
Parse command line arguments into $_GET:
<?php
parse_str(implode('&', array_slice($argv, 1)), $_GET);
var_dump($_GET);
?>
Execution:
php script.php "param1=value1" "param2=value2"
Method 2: Environment Variables
QUERY_STRING="param1=value1¶m2=value2" php script.php
PHP script:
<?php
if (isset($_ENV['QUERY_STRING'])) {
parse_str($_ENV['QUERY_STRING'], $_GET);
}
?>
Method 3: STDIN Parsing
For your specific webserver implementation:
<?php
if (php_sapi_name() === 'cli') {
$raw = file_get_contents('php://stdin');
if (preg_match('/GET \/[^?]+\?([^ ]+)/', $raw, $matches)) {
parse_str($matches[1], $_GET);
}
}
?>
A robust solution for custom web servers:
<?php
function initializeGetParams() {
global $argv;
// Method 1: Command line arguments
if (php_sapi_name() === 'cli' && count($argv) > 1) {
parse_str(implode('&', array_slice($argv, 1)), $_GET);
return;
}
// Method 2: Environment variable
if (isset($_ENV['QUERY_STRING'])) {
parse_str($_ENV['QUERY_STRING'], $_GET);
return;
}
// Method 3: STDIN parsing
$stdin = file_get_contents('php://stdin');
if (preg_match('/GET .*\?([^ ]+) HTTP/', $stdin, $matches)) {
parse_str($matches[1], $_GET);
}
}
initializeGetParams();
var_dump($_GET);
?>
For high-traffic implementations:
- Cache parsed parameters when possible
- Consider using compiled extensions for parameter parsing in custom servers
- Benchmark different parsing methods for your specific use case
Create a test harness:
# Test command line arguments
php test.php "user_id=123" "action=delete"
# Test environment variable
QUERY_STRING="user_id=456&action=create" php test.php
# Test STDIN simulation
echo "GET /test.php?user_id=789&action=update HTTP/1.1" | php test.php
When implementing custom parameter handling:
- Always sanitize input data
- Consider implementing web server-style URL decoding
- Validate parameter types before use
- Implement size limits for query strings
When implementing a custom PHP web server that executes scripts via command line interface (CLI), developers often encounter the issue where $_GET superglobal variables aren't populated as expected. This occurs because GET parameters are traditionally passed through the URL query string in web requests, not through CLI execution.
In a standard web server environment (like Apache or Nginx), PHP automatically parses the query string from the URL (e.g., script.php?param1=value1
) and populates $_GET. However, when running PHP via CLI:
php script.php
The $_GET array remains empty because there's no web server to parse and pass the query parameters.
Here are several approaches to solve this problem:
Method 1: Using Command Line Arguments
Parse command line arguments and manually populate $_GET:
// In your PHP script
parse_str(implode('&', array_slice($argv, 1)), $_GET);
var_dump($_GET);
Execute with:
php script.php param1=value1 param2=value2
Method 2: Simulating Web Server Environment
Set environment variables before execution:
// Bash/Shell
QUERY_STRING="param1=value1¶m2=value2" php script.php
// In PHP:
parse_str(getenv('QUERY_STRING'), $_GET);
Method 3: Using STDIN
Pass parameters through standard input:
echo "param1=value1¶m2=value2" | php script.php
// In PHP:
parse_str(stream_get_contents(STDIN), $_GET);
For your specific web server implementation, here's how to modify the execution:
// Before executing php index.php
$queryString = parse_url($requestUri, PHP_URL_QUERY);
putenv("QUERY_STRING=$queryString");
// Or when executing:
exec("QUERY_STRING=$queryString php index.php");
Each method has different performance implications:
- Command line arguments work well for few parameters
- Environment variables are efficient but have size limits
- STDIN is most flexible for large amounts of data
Here's a full example for your web server:
// Parse the request URL
$urlParts = parse_url($_SERVER['REQUEST_URI']);
$scriptPath = $urlParts['path'];
$queryString = $urlParts['query'] ?? '';
// Build command with environment variables
$envVars = [
'REQUEST_METHOD' => 'GET',
'QUERY_STRING' => $queryString,
'SCRIPT_FILENAME' => realpath($scriptPath)
];
$envString = '';
foreach ($envVars as $key => $value) {
$envString .= "$key=" . escapeshellarg($value) . ' ';
}
// Execute PHP script
$command = "$envString php " . escapeshellarg($scriptPath);
exec($command, $output, $returnCode);
// Send output to client
echo implode("\n", $output);