PHP
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Object-Oriented PHP
-
Section 5: Working with Data
-
Section 6: Modern PHP (PHP 8)
-
Section 7: Working with Files and Networking
-
Section 8: Common PHP Frameworks Overview
-
Section 9: Tooling and Ecosystem
-
Section 10: Practical Projects
-
Section 11: Interview Practice
-
Section 12: More Standard Library
-
Section 13: Data Structures and Algorithms in PHP
-
Section 14: More Practice Exercises
-
Section 15: More Security and Best Practices
-
Section 16: More Testing and Tooling
-
Section 17: WordPress-Style CMS Concepts
-
Section 18: Advanced OOP Practice
-
Section 19: More Web Fundamentals
-
Section 20: Database Practice
-
Section 21: PHP Manual: Array Functions
-
Section 22: PHP Manual: Date and Calendar Functions
-
Section 23: PHP Manual: Filesystem and Directory Functions
-
Section 24: PHP Manual: Filter and Var Handling
-
Section 25: PHP Manual: Math Functions
-
Section 26: PHP Manual: JSON and XML
-
Section 27: PHP Manual: Network and Stream Functions
-
Section 28: PHP Manual: Error and Exception Handling
-
Section 29: PHP Manual: Output Control and Misc
-
Section 30: PHP Manual: FTP, Zip, and Mail
-
Section 31: Modern PHP Frameworks Deep Dive
-
Section 32: PHP Design Patterns
-
Section 33: More Practice Exercises
-
Section 34: PHP Performance and Deployment
-
Section 35: More Interview Practice
-
Section 36: More PHP Standard Library
-
Section 37: PHP Concurrency and Async
-
Section 38: More Web Development Practice
-
Section 39: PHP Testing Deep Dive
-
Section 40: Composer and Package Development
-
Section 41: PHP Security Deep Dive
-
Section 42: More Practical Projects
-
Section 43: Legacy PHP Maintenance
-
Section 44: More Algorithm Practice
-
Section 45: Final Practice and Review
-
Section 46: PHP for E-Commerce Patterns
-
Section 47: PHP API Design Deep Dive
-
Section 48: PHP Caching Strategies
-
Section 49: PHP Queue and Background Jobs
-
Section 50: PHP Multi-Tenancy Patterns
-
Section 51: PHP Real-Time Features
-
Section 52: PHP CMS and Content Modeling
-
Section 53: PHP Internationalization
-
Section 54: More Framework-Specific Practice
-
Section 55: PHP Legacy Code Refactoring
-
Section 56: More Practice Projects Round 2
-
Section 57: PHP Command-Line Applications
-
Section 58: PHP and Microservices
-
Section 59: More Interview and Review Round 2
114: Stream Contexts and Wrappers
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-Agentheader (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.
There are no comments for now.