Skip to Content
Course content

114: Stream Contexts and Wrappers

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Listen, I know your first instinct when you see an API is to pull in cURL. I did that for years because it's the "industry standard." But sometimes, cURL is overkill. When you just need to push a bit of data to a URL or read a file with specific requirements, PHP's stream contexts and wrappers are a much leaner way to get the job done.

At its simplest, a "wrapper" is just a way for PHP to handle different protocols (like http://, ftp://, or php://) as if they were local files. A "context" is essentially a set of options you pass to those wrappers to change their behavior. Think of it as a configuration object that tells PHP, "Hey, when you open this stream, use these specific settings."

Attempting a simple API post

Let's build a small script that sends some JSON data to a mock API endpoint. I want to keep it lightweight, so I'll start with file_get_contents(). Most people think this function is only for reading files, but because of the HTTP wrapper, it can do a lot more.

$url = 'https://jsonplaceholder.typicode.com/posts';
$data = ['title' => 'Stream Contexts', 'body' => 'This is awesome', 'userId' => 1];

// I'll just pass the data and see what happens
$response = file_get_contents($url, false, stream_get_meta_data($url)); 
echo $response;

Correcting my assumption

Wait, I just realized I'm treating file_get_contents like a magic wand. If you run the code above, you'll notice it just returns the list of all posts from the API. Why? Because by default, the HTTP wrapper performs a GET request. I can't just "pass" data into the function; I have to explicitly tell the stream to change its method to POST.

This is where the stream context comes in. We use stream_context_create() to build an array of options that PHP will use when it opens the connection.

Defining the request behavior

Now I'll actually set up the context. I need to specify that I'm using the http wrapper, change the method to POST, and provide the content. I also need to tell the server I'm sending JSON, otherwise, it might ignore my payload or throw a 400 error.

$url = 'https://jsonplaceholder.typicode.com/posts';
$data = json_encode([
    'title' => 'Stream Contexts', 
    'body' => 'Now it actually works', 
    'userId' => 1
]);

$options = [
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/json\r\n",
        'content' => $data,
        'timeout' => 5 // I always add a timeout so my script doesn't hang forever
    ]
];

$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);

echo $result;

Notice the \r\n at the end of the header string. That's a quirk of the HTTP wrapper; it requires CRLF (carriage return and line feed) to separate headers. If you forget that, you'll spend an hour wondering why your headers aren't being recognized.

Why do it this way?

You might be thinking, "Why not just use a library?" In a massive enterprise app, you probably should. But in a small utility script, a cron job, or a lightweight plugin, avoiding a heavy dependency is a win. By using stream_context_create, you're using the language's native capabilities to handle network I/O without the overhead of a full-blown HTTP client.




📋 Practical Task

The User-Agent Spoofing Fetcher

Some servers block requests that don't have a "real" browser User-Agent string in the header. Your task is to write a script that fetches the HTML of https://www.google.com (or any site of your choice) using file_get_contents() and a stream context.

Your script must:

  • Create a stream context using stream_context_create().
  • Set a custom User-Agent header (e.g., Mozilla/5.0 (Windows NT 10.0; Win64; x64)...).
  • Set a request timeout of 10 seconds.
  • Output the first 200 characters of the resulting page to prove it worked.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.