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
81: Understanding the PHP Request Lifecycle
You've been writing PHP for a while now, and you're probably comfortable with the "code in, HTML out" flow. But have you ever stopped to wonder what's actually happening in the milliseconds between you hitting 'Enter' in your browser and the page appearing? To most, it's a black box. To an engineer, that black box is the request lifecycle, and if you don't understand it, you'll eventually hit a wall when debugging memory leaks or trying to optimize performance.
Let's stop guessing and actually track a request. I'm going to build a tiny "lifecycle tracker" to see where PHP starts and, more importantly, where it dies.
Hunting for the Start Line
I'll start with a simple script, profile.php, that pretends to fetch a user from a database. I want to know exactly when PHP takes over from the web server (like Nginx or Apache).
<?php
file_put_contents('lifecycle.log', "Request started at: " . microtime(true) . "\n", FILE_APPEND);
$user = ['name' => 'Devin', 'role' => 'Engineer'];
echo "<h1>User Profile: {$user['name']}</h1>";
file_put_contents('lifecycle.log', "Request ended at: " . microtime(true) . "\n", FILE_APPEND);
?>
If I run this and check lifecycle.log, I see two timestamps. It looks straightforward: the server gets the request, hands it to PHP, PHP runs the code from top to bottom, and then it's done. But wait—what happens if the script crashes? Or what if I use exit() halfway through? I suspect there's a cleanup phase I'm missing.
Testing the 'Share Nothing' Assumption
One of the weirdest things for people coming from Node.js or Python is PHP's "share nothing" architecture. In those languages, you can have a global variable that stays in memory across different users' requests. I remember trying this in PHP years ago and being baffled when it didn't work. Let's prove it right now.
I'll add a global counter to my script to see if it increments every time I refresh the page:
<?php
global $requestCount;
$requestCount++;
echo "This is request number: " . $requestCount;
?>
I refresh the page. It says "1". I refresh again. It still says "1". No matter how many times I hit F5, it never hits 2. Why? Because the PHP interpreter is wiped clean after every single request. The process (or the worker thread in PHP-FPM) essentially resets. This is a superpower for stability—one user's crashed script can't poison the memory for everyone else—but it's a pain when you actually want to persist data, which is why we rely so heavily on sessions and databases.
Catching the Exit
Now, back to that "cleanup" phase. If I call die() or exit(), my second file_put_contents call never happens. But I have a feeling PHP is still doing something behind the scenes before the process actually terminates. To prove this, I'll use register_shutdown_function().
This function tells PHP: "No matter how this script ends—whether it finishes naturally or crashes—run this one last bit of code."
<?php
register_shutdown_function(function() {
file_put_contents('lifecycle.log', "Shutdown function executed at: " . microtime(true) . "\n", FILE_APPEND);
});
file_put_contents('lifecycle.log', "Main script started at: " . microtime(true) . "\n", FILE_APPEND);
// Let's simulate a hard stop
exit("Stopping early!");
?>
When I run this, the page displays "Stopping early!", but when I check the log, I see the "Main script started" entry and the "Shutdown function executed" entry. This confirms the lifecycle: Request $\rightarrow$ SAPI (Server API) $\rightarrow$ Compilation $\rightarrow$ Execution $\rightarrow$ Shutdown $\rightarrow$ Termination.
The "SAPI" part is just a fancy way of saying the bridge between your web server and PHP. Whether you're using mod_php or PHP-FPM, the SAPI is what tells PHP, "Hey, here is a request from a browser, here are the GET/POST variables; go do your thing." Once that shutdown function finishes, the memory is freed, and the process is ready for the next stranger who hits your URL.
📋 Practical Task
Building a Request Execution Timer
To put this lifecycle knowledge into practice, you are going to build a diagnostic script that measures the exact duration of a PHP request, including the time spent in the shutdown phase.
Requirements:
- Create a script called
timer.php. - At the very top of the script, capture the start time using
microtime(true). - Store this start time in a variable that is accessible to a shutdown function (hint: you may need to use a global variable or a closure).
- Register a shutdown function that captures the end time, calculates the difference between the start and end, and logs the total execution time (in milliseconds) to a file named
performance.log. - Inside the main body of your script, simulate a "heavy" process using
usleep(50000)(50 milliseconds) and then callexit("Process Interrupted"). - Verify that despite the
exit()call, the total execution time is still correctly logged to the file.
There are no comments for now.