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
116: Working with Stream Filters
Imagine you're installing a water filtration system in your house. You don't take a giant bucket, fill it from the tap, pour it through a filter, and then move it to a different bucket. That would be exhausting and a waste of space. Instead, you install the filter inline. As the water flows from the city main to your faucet, it passes through the filter. The water is cleaned while it's moving.
PHP stream filters work exactly the same way. Instead of reading a 2GB log file into a variable, modifying the string, and saving it back—which would likely crash your server due to memory limits—you attach a filter to the stream. As you read the file chunk by chunk, PHP passes each piece through the filter before it even hits your variable. You're transforming the data in transit.
Plugging in Pre-made Filters
PHP comes with several built-in filters. Some are simple, like `string.toupper` (which makes everything uppercase) or `string.rot13`. You attach these using stream_filter_append().
// Let's say we have a text file and we want to read it as uppercase
$handle = fopen('report.txt', 'r');
// Attach the filter to the handle
stream_filter_append($handle, 'string.toupper');
while (!feof($handle)) {
echo fread($handle, 1024); // The data is already uppercase by the time it reaches here
}
fclose($handle);
I've found that this is incredibly useful when dealing with CSVs or large exports where you need to normalize data (like forcing case sensitivity) without loading the whole dataset into an array. It's efficient, lean, and keeps your memory footprint flat.
Building Your Own Data Transformer
The real power kicks in when you create your own filter. To do this, you need to create a class that extends php_user_filter. You'll primarily be overriding the filter method, which handles the "buckets" of data as they flow through.
Let's build a "Redaction Filter." Suppose you're streaming a log file to a browser, but you need to hide any mention of the word "SECRET" for security reasons.
class RedactionFilter extends php_user_filter {
public function filter($in, $out, &$consumed, $closing): bool {
while ($bucket = stream_bucket_make_writeable($in)) {
// Replace "SECRET" with "[REDACTED]" in the current chunk of data
$bucket->data = str_replace('SECRET', '[REDACTED]', $bucket->data);
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return true;
}
}
// You have to register the filter class with a name before you can use it
stream_filter_register('redact_secrets', 'RedactionFilter');
$handle = fopen('system.log', 'r');
stream_filter_append($handle, 'redact_secrets');
while ($line = fgets($handle)) {
echo $line;
}
fclose($handle);
One thing to be careful about: since streams process data in chunks (buckets), there's a tiny chance your target word (like "SECRET") could be split right down the middle between two buckets. For simple replacements, this usually isn't an issue, but if you're building a high-precision parser, you'll need to handle those "boundary" cases by keeping a small buffer of the previous chunk's end. I'll leave that for you to ponder as you experiment.
Stacking Multiple Filters
The beauty of this system is that it's a pipeline. You can call stream_filter_append multiple times. The data will flow through the first filter, then the result will pass into the second, and so on. You could, for instance, redact secrets and then compress the output using zlib.deflate in one seamless motion.
📋 Practical Task
The Log File PII Masker
You have been tasked with creating a security tool that scrubs Personally Identifiable Information (PII) from server logs before they are sent to a third-party analysis tool. Emails should not be visible in these logs.
Your Goal: Create a custom stream filter that identifies email addresses using a regular expression and replaces them with the string <email_masked>.
Requirements:
- Define a class that extends
php_user_filter. - Implement the
filtermethod usingpreg_replaceto mask emails. - Register your filter with the name
mask_emails. - Open a dummy text file containing several email addresses, apply the filter, and print the output to the screen.
There are no comments for now.