How does PHP echo's a "Hello World"? – Behind the scene

Have you ever wondered how PHP echo’s a “Hello World” for you on the browser? Even I didn’t until I read about the PHP internals and extensions. I thought may be a few out there will be interested in exploring the other side of PHP, so here we go.

In my last post I discussed in brief “How your browser reaches to my server when you type http://abhinavsingh.com in address bar?”. Read through if you have missed out on that. Here I will discuss in brief “How does PHP churns out the content requested on the webpage?”

An Overview
Here is what happens step-wise:

  1. We never start any PHP daemon or anything by ourself. When we start Apache, it starts the PHP interpreter along itself
  2. PHP is linked to Apache (In general term SAPI i.e. a Server API) using mod_php5.so module
  3. PHP as a whole consists of 3 modules (Core PHP, Zend Engine and Extension Layer)
  4. Core PHP is the module which handles the requests, file streams, error handling and other such operations
  5. Zend Engine(ZE) is the one which converts human readable code into machine understandable tokens/op-codes. Then it executes this generate code into a Virtual Machine.
  6. Extensions are a bunch of functions, classes, streams made available to the PHP scripts, which can be used to perform certain tasks. For example, we need mysql extension to connect to MySQL database using PHP.
  7. While Zend Engine executes the generated code, the script might require access to a few extensions. Then ZE passes the control to the extension module/layer which transfer back the control to ZE after completion of tasks.
  8. Finally Zend Engine returns back the result to PHP Core, which gives that to SAPI layer, and finally which displays it on your browser.

A Step Deeper
But wait! This is still not over yet. Above was just a high level flow diagram. Lets dig a step deeper and see what more is happening behind the scenes:

  1. When we start Apache, it also starts PHP interpreter along itself
  2. PHP startup happens in 2 steps
  3. 1st step is to perform initial setup of structures and values that persists for the life of SAPI
  4. 2nd step is for transient settings that only last for a single page request

Step 1 of PHP Startup
Confused over what’s step 1 and 2 ? No worries, next we will discuss the same in a bit more detail. Lets first see step 1, which is basically the main stuff.
Remember step 1 happens even before any page request is being made.

  1. As we start Apache, it starts PHP interpreter
  2. PHP calls MINIT method of each extension, which is being enabled. View your php.ini file to see the modules which are being enabled by default
  3. MINIT refers to Module Initialization. Each Module Initialization method initializes and define a set of functions, classes which will be used by future page requests

A typical MINIT method looks like:

      PHP_MINIT_FUNCTION(extension_name) {

          /* Initialize functions, classes etc */

      }

Step 2 of PHP Startup

  1. When a page request is being made, SAPI layer gives control to PHP layer. PHP then set up an environment to execute the PHP page requested. In turn it also create a symbol table which will store various variables being used while executing this page.
  2. PHP then calls the RINIT method of each module. RINIT refers to Request Initialization Module. Classic example of RINIT module implementation is the Session’s module. If enabled in php.ini, the RINIT method of Sessions module will pre-populate the $_SESSION variable and save in the symbol table.
  3. RINIT method can be thought as an auto_prepend_file directive, which is pre-appended to every PHP script before execution.

A typical RINIT method looks like:

      PHP_RINIT_FUNCTION(extension_name) {

          /* Initialize session variables, pre-populate variables, redefine global variables etc */

      }

Step 1 of PHP Shutdown
Just like PHP startup, shutdown also happens in 2 steps.

  1. After the page execution is complete either by reaching the end of the script or by call of any exit() or die() function, PHP starts the cleanup process. In turn it calls RSHUTDOWN method of every extension. RSHUTDOWN can be thought as auto_append_file directive to every PHP script, which no matter what happens, is always executed.
  2. RSHUTDOWN method, destroys the symbols table (memory management) by calling unset() on all variables in the symbols table

A typical RSHUTDOWN method looks like:

      PHP_RSHUTDOWN_FUNCTION(extension_name) {

          /* Do memory management, unset all variables used in the last PHP call etc */

      }

Step 2 of PHP Shutdown
Finally when all requests has been made and SAPI is ready to shutdown, PHP call its 2nd step of shutdown process.

  1. PHP calls the MSHUTDOWN method of every extension, which is basically the last chance for every extension to unregister handlers and free any persistent memory allocated during the MINIT cycle.

A typical RSHUTDOWN method looks like:

      PHP_MSHUTDOWN_FUNCTION(extension_name) {

          /* Free handlers and persistent memory etc */

      }

And that brings us to the end of what we can call as PHP Lifecycle. Important point to note is that Step 1 of Startup and Step 2 of Shutdown happens when no request is being made to the web servers.

I hope this post will clear many doubts and un-answered questions which you might have.

Do leave a comment and feedbacks.

  • Leek Adam

    Amazing information as always. May I know whats the source of information for you? Is there any book, library, website which you refers to?

    Anyways interesting article. Even after so much of initialization and crap , PHP is able to deliver the goods :)

  • http://www.jaisenmathai.com/ Jaisen Mathai

    Any idea what the cost is of loading modules which are never loaded? I hadn’t thought about each module’s minit function being called on every single request.

  • http://abhinavsingh.com admin

    You got it wrong actually. MINIT is called for each module once only when you start your yapache server. After that only RINIT method is called for each module upon every subsequent page request.

    RINIT generally involve populating variables e.g. in case of $_SESSION variables, which really doesn’t cost much. Even if you are not using it, it will be unset() upon module RSHUTDOWN method call.

    However its always a better practice to keep an eye on what modules PHP loads by default and what not. In case of high traffic websites that might enhance the performance. (Though I have no stats to show how much enhancement in performance)

    Note: Step 1 of startup and Step 2 of shutdown, happens when you start and stop SAPI. Step 2 of startup and Step 1 of shutdown happens when a page is requested.

  • http://www.vsoftgames.com Vitor Almeida da Silva

    Interesting post. Thanks for sharing these.

  • JD001

    Same as Jaisen, I have now concerns over the performance of PHP since its calling RINIT module of each and every extension whether required or not.

    However thanks for sharing this useful information with us all.

  • Nikhil Aggarwala

    Super post. I expect a post on how to write a PHP extension, if you can. I have searched a lot on web and found a lot of so called Hello World PHP extension code. But unfortunately none of them clearly explains each and every piece of that code.

    From this post I guess you have dealt with PHP extensions and it would be nice if you can share the same with us.

    @JD001
    I am sure that PHP developers must have thought about loading of extensions and surely they must have made it a light weight process. I am sure it won’t effect your site performance.

  • Piccolo Principe

    I have seen the case where bad written scripts (infinite recursion) cause php to segfault. What happen in this case? What initialization is repeated?

  • http://rohitnair.info Rohit Nair

    Interesting stuff. I guess because PHP is so easy as a language and you have this feeling that “it just works”, you tend to overlook its internals and unless you know that, you obviously can’t write efficient PHP.

  • http://abhinavsingh.com admin

    @Piccolo Principe
    What sort of infinite loop are you talking about? Is it a simple while(1) {} thing that you are referring to?

    Well I am not sure where did you encountered segmentation fault? Can you give an example of a script you are referring? Once I got an segmentation fault but it wasn’t because of a bad script.

  • http://abhinavsingh.com admin

    @Rohit
    Yes i must say PHP is a lot easy to start with. And you can build serious sites faster in PHP than in any other language.

    But now that I am going through a lot of Python and analyzing the performance, I can find that Python provides a better scalable site.

    One guy had a 7GB text file that he needed to run some parsing on (to prepare for a DB import). Performance Numbers (on 5 million lines worth of the file)

    $ time ./split.pl p.test (# Perl 5.8.8)
    real 0m38.577s
    user 0m33.554s
    sys 0m0.848s

    $ time ./split.py p.test (# Python 2.4.4)
    real 0m44.895s
    user 0m42.975s
    sys 0m0.900s

    $ time php split.php p.test (# PHP 5.2.6RC4)
    real 1m10.887s
    user 0m51.251s
    sys 0m18.677s

    which shows PHP is about 50% slower as compared to Perl and Python. Perl is fastest but then Perl is not suitable for web development stuffs.

  • Pingback: PHP Extensions - How and Why? | Abhi's Weblog

  • Pingback: MySQL Query Cache, WP-Cache, APC, Memcache - What to choose « Abhi’s Weblog

  • Pingback: The lifecycle of a PHP script | Geoff Garbers

  • anubhav.jha

    Wow thanks really helped in lot of things…

  • kiren s

    Wonder full explanation of terminology behind php.It helped me lot.Before reading this i was looking to relate processor and php code.Now i understood the role of zend engine.It would be great full if you can write more about zend engine and its working.
    Thank you very much

  • Pingback: Learning to write PHP Extensions | Huazai

  • sushma ramanna

    Just wow:-) Thanks for sharing

  • Pingback: Introduction to Node.js and what I find so great about it | Askmike.orgAskmike.org

  • Girish

    Thanks for putting up the lifecycle details of PHP, it is an enlightening topic.
    Need few clarifications from you and these are listed as below:
    1. Is the module “mod_php5.so” specific to Apache or do the other servers like IIS have the same module?
    I assume the CorePHP is configured in the server to point to the correct module.
    2. My assumption is that the entire lifecycle that you have explained is a functionality that every server that supports PHP needs to incorporate to execute php code.
    3. Similarly the Zend Engine component and CorePHP, Extension Layer are part of Server that exhibit the lifecycle of PHP. Is this Zend Engine part of Zend framework? I ask this because of the name ‘Zend’.
    4. Do we first need to download and install basic PHP from PHP.net and then proceed for installation of PHP frameworks like Zend, CakePHP etc?

  • mak ashtekar

    thank you very much.. I was looking for this article long time ago.. Finally i got ..
    Thank you so much

  • Nasser

    Thanks for this article. Hope to see more of your articles in future.

  • Pingback: PHP调用C++动态链接库