Passing $_GET Parameters to PHP Scripts via Command Line Interface (CLI)


3 views

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:

  1. Always sanitize input data
  2. Consider implementing web server-style URL decoding
  3. Validate parameter types before use
  4. 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);