PHP Cheatsheet

HTTP, CLI, and Dates

Use this PHP reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Request Method Routing

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

if ($method === 'POST') {
    // handle form or JSON body
} elseif ($method === 'GET') {
    // render page or read query params
} else {
    http_response_code(405);
}

Keep routing decisions explicit. Do not trust method override headers unless your framework intentionally supports them.

Reading JSON Bodies

$raw = file_get_contents('php://input');
$payload = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);

$email = $payload['email'] ?? null;

$_POST is for form-encoded requests. JSON APIs usually read php://input and decode it manually or through a framework request object.

Query Strings and URLs

$query = http_build_query(['page' => 2, 'q' => 'php']);
$url = '/search?' . $query;
$parts = parse_url('https://example.com/path?a=1');
parse_str($parts['query'] ?? '', $params);

Use helpers to build and parse URLs instead of concatenating unescaped user input.

CLI Arguments

// php script.php input.csv --dry-run
$script = $argv[0];
$args = array_slice($argv, 1);
$options = getopt('', ['dry-run', 'output:']);

$argv is available in CLI mode. getopt handles simple flags; larger CLIs usually use Symfony Console.

Reading Stdin

$line = trim(fgets(STDIN));                 // one line
$answer = readline('Continue? [y/N] ');     // prompt + read (CLI)
while (($line = fgets(STDIN)) !== false) {  // until EOF
    $n = (int) $line;
}
$all = stream_get_contents(STDIN);          // everything at once

fgets returns the line including its trailing newline, so trim before parsing. fgets(STDIN) returns false at end of input.

DateTimeImmutable

$now = new DateTimeImmutable('now', new DateTimeZone('UTC'));
$tomorrow = $now->modify('+1 day');
$due = $now->add(new DateInterval('P3DT12H'));   // 3 days 12 hours
echo $tomorrow->format(DateTimeInterface::ATOM); // 2026-07-06T00:00:00+00:00
echo $now->format('Y-m-d H:i:s');

Prefer DateTimeImmutable so date operations return new values instead of mutating shared objects.

Parsing Dates

$dt = DateTimeImmutable::createFromFormat('m/d/Y', '07/05/2026', new DateTimeZone('UTC'));
if ($dt === false) { /* input did not match the format */ }

$loose = new DateTimeImmutable('2026-07-05 14:30');  // ISO-ish strings parse directly

createFromFormat returns false on bad input, so always check before using the result. Format characters mirror format(): Y year, m month, d day, H:i:s time.

Diffs and Timestamps

$interval = $start->diff($end);        // DateInterval
$interval->days;                       // total whole days
echo $interval->format('%a days, %h hours');

$ts = $now->getTimestamp();            // Unix seconds
$fromTs = new DateTimeImmutable('@' . $ts);            // UTC
$fromTs = (new DateTimeImmutable())->setTimestamp($ts);
time();                                // current Unix timestamp

diff() works across time zones because both objects represent absolute instants. The @timestamp constructor always yields UTC.

Time Zones

$tz = new DateTimeZone('America/Los_Angeles');
$local = $now->setTimezone($tz);

Store instants in UTC when possible. Convert to a user timezone only at display boundaries.

File Uploads

if (isset($_FILES['avatar']) && $_FILES['avatar']['error'] === UPLOAD_ERR_OK) {
    $tmp = $_FILES['avatar']['tmp_name'];
    $name = basename($_FILES['avatar']['name']);
    move_uploaded_file($tmp, __DIR__ . '/uploads/' . $name);
}

Validate MIME type, size, extension, and destination. Never trust the original filename as safe storage input.

HTTP Clients

composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client(['timeout' => 5]);
$response = $client->get('https://api.example.com/health');
$body = (string) $response->getBody();

Set timeouts on outbound HTTP. Production code should also handle non-2xx responses and retries with backoff.