C:\1990S\PHP.TXT
1995
PHP: The Browser Received the Finished Page
PHP's early server-side tools grew into an embedded language that assembled pages before delivery, bringing reusable presentation and application work into the same request.
A small museum has thirty web pages. Each repeats its opening hours at the bottom. The hours change, and somebody has to remember thirty edits.
The job is easy enough to understand. Its failure mode is equally easy: twenty-nine pages agree, and the thirtieth quietly invites visitors to arrive when the doors are locked.
Server-side page assembly offers another arrangement. Store the shared material once, then incorporate it while producing each response. The browser receives a complete page; the author maintains the common source separately.
PHP grew from practical web tools into a language suited to work like this. Its history is interesting partly because the initial ambition was so concrete: observe visits, interpret forms and make useful pages without writing another separate program for every small task.
The museum doesn’t need to know how a parser works. It does need the right opening hours.
A tool collection changed shape
Rasmus Lerdorf made early Personal Home Page tools for his own web use. The project history dates the public source release to June 1995, then describes FI, the Forms Interpreter, in September and the Personal Home Page Construction Kit rewrite in October. PHP/FI followed in April 1996.1
These names identify stages of development, rather than several interchangeable labels for modern PHP. HTML-comment embedded syntax belonged to the early work. PHP/FI moved the combined tools toward a more general embedded language.
The period PHP/FI manual gives a firsthand account of an earlier Perl wrapper, rewritten in C to reduce process overhead on an overloaded server. It describes the combined tools as a way to avoid many small separate CGI programs.2
That account is useful precisely because it starts with maintenance and operation. The language wasn’t conceived with a complete modern application ecosystem already waiting inside it. People wanted to perform work, asked for more capabilities, and the implementation changed to accommodate them.
Andi Gutmans and Zeev Suraski began a further parser rewrite in 1997. PHP 3 arrived in June 1998, with the recursive Hypertext Preprocessor expansion associated with that later name.1 The 1995 release doesn’t inherit modern sessions, database APIs or object features because their names now sound familiar.
Follow one museum request
Imagine a request for /exhibits/radio.html on an invented museum service. The public URL identifies the resource the visitor wants. The server’s configuration determines how that request reaches the page processor.
The details of that configuration can differ. Our teaching model begins after the correct template has been selected, so it doesn’t pretend to reproduce an installation’s CGI redirection or module setup.
The processor reads the template. Ordinary HTML contributes ordinary output. Instructions in the template can obtain other material or perform computation. The resulting output becomes the response sent to the browser.
Original explanatory diagram, 2026. Invented museum request, simplified server-side processing; not a PHP deployment trace or historic interface.
The browser then interprets the resulting HTML. It doesn’t need to execute the server’s include instructions to obtain the shared header or footer.
This distinguishes the example from an image referenced in a page. An image URL generally tells the browser about another resource to retrieve. A server-side include can contribute bytes to the HTML response before the browser receives it.
Both arrangements can reuse material, but they divide the work differently. A single response can contain output assembled from several server-side sources.
Three source pieces, one result
Here is an original miniature in the documented PHP/FI 2.0 include syntax. It is a later early-language example, explicitly not code claimed for the initial June 1995 PHP Tools release.2
The chosen radio template is:
<?include("/site/shared/header.html")>
<h2>Radio exhibit</h2>
<p>A receiver turns a signal into sound.</p>
<?include("/site/shared/footer.html")>
The server’s invented shared header contains:
<h1>Small Museum</h1>
Its shared footer contains:
<p>Open Tuesday to Saturday.</p>
The response body assembled by our teaching model is:
<h1>Small Museum</h1>
<h2>Radio exhibit</h2>
<p>A receiver turns a signal into sound.</p>
<p>Open Tuesday to Saturday.</p>
The original manual documents Include as inserting another file, with full PHP parsing on the included material.2 Our chosen shared files contain only literal HTML, so there is no further execution to follow in this example.
The paths in the include instructions refer to invented server-side files. They aren’t promises that the visitor can open those paths as public URLs. A server’s storage organization and its public resource naming needn’t coincide.
That distinction can be useful to authors. Shared source can live in an organized place without becoming a separate navigation target. The visitor sees the assembled result at the exhibit address.
One edit changes later responses
Now change the shared footer to say that the museum opens Wednesday to Sunday. No change to the radio template is necessary.
The next freshly generated radio response incorporates the new text. A clock exhibit and a camera exhibit using the same footer do so too.
Our checker constructs all three templates, renders them and verifies their shared text. It then updates the footer source, renders them again and checks that every new output contains the new hours and no longer contains the old ones.
This is a precise claim about the model: all generated outputs refer to the same current shared material. It doesn’t mean the text disappears from a visitor’s already displayed page the instant an author edits a file.
A previously delivered response is already somewhere else. The browser may continue showing it. A cache may still hold it. Updating server-side source and updating every copy of a past response are different operations.
The benefit is nevertheless substantial. If thirty templates had thirty separate footer copies, changing the hours would require maintaining thirty source locations. With one shared footer, the author maintains one location, while generation distributes its current contents into complete responses.
Original teaching diagram, 2026. Three invented exhibit templates share one footer source; the change applies to fresh generated responses, not automatically to already delivered pages.
The checker also retains an old rendered string and confirms that changing the source doesn’t mutate it. That small test keeps the explanation honest about where the state lives.
A useful dependency can become a broad mistake
Centralizing the footer reduces duplicated maintenance. It also increases the reach of a mistaken edit.
If the shared text says Wednesday to Monday by accident, every newly generated dependent page can acquire the same mistake. The system has distributed one authoritative source very effectively. It hasn’t established that the source is true.
A broken shared fragment can likewise affect several pages. A closing tag in the wrong place can damage an output structure that looked correct when considered as separate files. The complete response is the thing the browser must interpret.
The relationship consequently deserves review at two scales. Inspect the common piece, then inspect representative assembled pages. Reuse reduces repetition while increasing the value of getting the reused part right.
There is a second maintenance benefit beyond reducing edit counts. The author can see that an exhibit’s local content is distinct from museum-wide presentation. That division gives a change a sensible home.
It isn’t an argument for putting every repeated character in a shared file. Too many tiny dependencies can make a page harder to understand. The useful boundary follows a responsibility that really changes together, such as opening hours used across the site.
Input isn’t automatically presentation
Our miniature deliberately uses fixed trusted strings. It doesn’t insert a visitor’s name, search term or database value into the HTML.
That limit avoids hiding another important boundary. A string received from outside the template can contain characters with meaning in HTML. Inserting it into the output without an appropriate interpretation can change the structure the browser sees.
For example, a visitor’s supplied text might contain angle brackets. The server has to decide whether that text is content to display or markup to interpret. The fact that it came from a form doesn’t settle the decision.
Likewise, selecting an include path from arbitrary visitor input would grant a different kind of influence: choosing which server-side source the processor reads. Our example’s file names are fixed by the author, rather than treated as a harmless extension of a query parameter.
These are conceptual boundaries, not a modern deployment recipe. The purpose is to locate where authority enters the process. The server prepares output, and its decisions can affect what code or markup the browser ultimately interprets.
Keeping the source on the server doesn’t by itself make those decisions correct. It simply places the work and the responsibility there.
The result is still a document
A generated page can be completely ordinary HTML from the browser’s perspective. Its production history isn’t necessarily visible in its appearance.
That makes server-side programming easy to underestimate. A visitor sees a title, description and opening hours. Behind them, the server may have consulted files, selected data or made decisions before delivering the result.
The opposite temptation is to overcomplicate the story. A shared footer doesn’t require a framework, an elaborate object model or a modern language feature inventory to explain. The essential operation is assembling a response using a reusable source of truth.
The original PHP trajectory is useful here because its capabilities grew around practical requests. Tracking visits and handling forms led toward a tool that let authors keep small programs close to the pages they helped produce.
The code and output needn’t become the same thing. The author maintains the instructions and source pieces; the visitor receives their result.
Small scripts, substantial responsibility
The museum example contains very little computation. Its important calculation is organizational: thirty copies become one maintained source, and later responses are produced from that source.
The reduction doesn’t eliminate review, caching questions or the distinction between trusted source and outside input. It gives those questions a smaller, more intelligible arrangement in which to be answered.
PHP’s early history helped make that kind of arrangement practical for web authors. A page could remain a page to its reader while becoming the result of a program to its server.
The browser receives the finished document. Somebody still has to make sure the doors are open when it says they are.
Footnotes
-
PHP Documentation Group, History of PHP, early Tools/FI/Construction Kit/PHP-FI stages and PHP 3 chronology. June 1995 public source milestone separated from 1994 origins and later language features; no unread exact announcement day claimed. ↩ ↩2
-
Original PHP/FI Version 2.0 Documentation, firsthand Brief History and Include reference. Retained later-period manual, including PHP 3 migration advice; exact include syntax is PHP/FI 2.0, not asserted for first PHP Tools. Original model doesn’t execute the historical interpreter. ↩ ↩2 ↩3