The basics
What is a PHP file?
A .php file holds a program written in PHP, a language made for building web pages on a server. When someone visits a PHP page, the web server runs the file, and the visitor's browser receives whatever it printed: usually HTML, sometimes JSON, an image or a PDF. WordPress, Drupal, Joomla, Laravel and Symfony applications are all made of PHP files.
That makes PHP files different from HTML files. An HTML file is the page; a PHP file is a recipe the server follows to make the page, often a different one for each visitor: their name, their basket, today's prices. The browser can't do this itself, which is why a PHP file needs a server with PHP installed.
The file is plain text, so any text editor can open it and show the code. Opening it in a browser straight from your computer doesn't run it: you see the code, or the browser offers to download it.
Downloaded a file ending in .php?
When a website's download link is a PHP script, such as download.php?id=42, the browser sometimes saves the result under the script's name. The file is whatever the script sent: often a PDF, an image or a ZIP. Open it in a text editor and look at the start: %PDF means a PDF, PK a ZIP, <html a web page. Rename it with the right extension.
Anatomy
What's inside a PHP file
A PHP file is a text file in which <?php … ?> tags mark the code. PHP runs the code and sends everything outside the tags as it is. Here is a small page that lists products from PHP objects, part by part.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use App\Shop\Product;
$products = [
new Product('Notebook', 4.50),
new Product('Pencil', 0.80),
];
function h(string $text): string
{
return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
}
?>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Shop</title></head>
<body>
<h1>Products</h1>
<ul>
<?php foreach ($products as $product): ?>
<li><?= h($product->name) ?>: €<?= number_format($product->price, 2) ?></li>
<?php endforeach; ?>
</ul>
</body>
</html>- 1
<?phpThe opening tag
Switches from output to code. It must be followed by a space, tab or newline. Anything before it, even one blank line or an invisible byte order mark, is sent to the browser.
- 2
declare(strict_types=1);Strict types
Must be the first statement in the file. With it, passing a number where a function expects a string is a
TypeErrorinstead of a silent conversion. - 3
require __DIR__ . '/vendor/autoload.php';The Composer autoloader
Loads the packages installed with Composer and lets PHP find your own classes by name.
__DIR__is this file's folder, so the path works whichever folder the request started from. - 4
use App\Shop\Product;A namespace import
Lets the code say
Productinstead ofApp\Shop\Product. Under the PSR-4 convention, that class lives in a file calledProduct.phpin aShopfolder. - 5
$products = [ … ];Variables and arrays
Variables start with
$. Square brackets make an array, PHP's all-purpose list and dictionary. - 6
htmlspecialchars($text, ENT_QUOTES, 'UTF-8')Escaping output
Turns
<,>,&and quotes into HTML entities, so text from a database or a visitor can't add HTML or scripts to the page (cross-site scripting). - 7
?>The closing tag
Switches back to output. Everything until the next
<?phpgoes to the browser unchanged. A file that is all PHP should leave this tag out, as the next section explains. - 8
<!DOCTYPE html> …Plain HTML
Sent as it is. The browser only ever receives HTML like this: it never sees the PHP code, only what the code printed.
- 9
<?php foreach (…): ?> … <?php endforeach; ?>A loop around HTML
The alternative syntax (a colon and
endforeach) is made for templates: the HTML between the tags is sent once per product. - 10
<?= h($product->name) ?>The short echo tag
<?=is short for<?php echo, and is always available.->reads a property of an object.
Under the hood
What happens when a server runs a PHP file
- 1The browser asks for a page, such as
https://example.com/products.php. - 2The web server sees the
.phpextension and passes the request to PHP instead of sending the file. Usually that's PHP-FPM, a pool of PHP processes behind Nginx, Apache or Caddy; some Apache servers run PHP inside the server withmod_php. - 3PHP compiles the file to opcodes, the instructions its engine runs. OPcache, which comes with PHP, keeps the compiled version in memory, so later requests skip this step until the file changes.
- 4PHP runs the code from top to bottom. Text outside the tags and anything printed with
echobecome the response.header()can set the content type, a redirect or a cookie, but only before any output. - 5The server sends the output to the browser, as
text/htmlunless the script said otherwise. - 6PHP forgets everything. Each request starts from scratch; anything that must last, such as a logged-in user or an order, lives in a session, a database or a file.
On the command line, php script.php runs the same file without a web server, printing the output in the terminal. That's how PHP is used for scripts, scheduled jobs and tools such as Composer.
The big gotcha
Why a PHP file downloads or shows its code instead of running
A PHP file only runs when a server with PHP handles it. Anywhere else it's just text. The usual reasons you see code, or get a download, instead of a page:
| Where you opened it | What you see | Why | Fix |
|---|---|---|---|
| Double-clicked on your computer | The code, or a download prompt | Browsers can't run PHP, and file:// has no server | Run php -S localhost:8000 in the folder and open the page through it |
| A static host (GitHub Pages, object storage, 99helpers) | The code as plain text | Static hosts send files as they are and never run server code | Use a host with PHP, or export the pages as HTML |
| Your PHP hosting, after a change | A download of the .php file | No PHP handler for that file, often an .htaccess line naming a PHP version the host removed | Remove or update the handler line, or pick the PHP version again in the hosting panel |
| Your PHP hosting | Code from <? onwards in the page source | Short open tags (<? without php) are switched off on that server | Use <?php (and <?= for echo) everywhere |
A server that shows PHP source is showing whatever is in it, including database passwords in configuration files. If your live site ever does this, take it offline until PHP is running again, then change those passwords.
How to
How to run, edit and check a PHP file
| Windows | macOS | Linux | |
|---|---|---|---|
| Get PHP | The Windows builds from php.net, a package such as XAMPP, or PHP inside WSL | Homebrew (brew install php); recent macOS versions don't include PHP | The distribution's php-cli package |
| Run a script | php script.php | php script.php | php script.php |
| Serve pages | php -S localhost:8000 | php -S localhost:8000 | php -S localhost:8000 |
# In the folder that holds your PHP files:
php -S localhost:8000
# then open http://localhost:8000/sample-page.php in a browser.
# Serve a subfolder as the document root instead:
php -S localhost:8000 -t public/The built-in server (in PHP since 5.4) serves the current folder and returns index.php or index.html for a folder address. The PHP manual is clear that it's for development and testing only: by default it's a single process that stalls while one request is busy, and it shouldn't be used on a public network. php -v shows your version and php -m the installed extensions.
- Read or edit it: any plain-text editor works. VS Code with a PHP extension such as Intelephense, or PhpStorm, add autocompletion and error checking.
- Check the syntax without running it:
php -l file.phpprintsNo syntax errors detectedor the parse error, and exits with status 255 on failure. - Find bugs before they run: static analysers such as PHPStan and Psalm catch type errors and calls to methods that don't exist.
- Format: PHP-CS-Fixer or PHP_CodeSniffer apply the PSR-12 or PER coding style.
- Turn a PHP page into static HTML: run it and save the output,
php page.php > page.html, or save the page from your browser while a server runs it. Pages that depend on a database or form input only keep the content of that moment.
The rules
Tags, encodings, file names and project layout
- Leave out the closing tag in pure PHP files. The PHP manual recommends it: a newline or space after a final
?>is sent as output, which can break headers, sessions, downloads and JSON. Files that end in HTML, like templates, keep their tags. - Use
<?phpand<?=only. The short<?tag can be switched off with theshort_open_tagsetting, and the PSR-1 coding standard allows only the two long forms. - UTF-8 without a BOM. PHP doesn't decode the file; it outputs strings byte for byte. A byte order mark before
<?phpis output too, before your code runs, which causes "headers already sent" warnings and makesdeclare(strict_types=1)or anamespaceline a fatal error. PSR-1 requires UTF-8 without a BOM. - A shebang is allowed for command-line scripts: PHP skips a first line starting with
#!, so#!/usr/bin/env phpabove<?phpworks. - One class per file, named after the class. The PSR-4 autoloading standard maps
App\Shop\Producttosrc/Shop/Product.php, matching upper and lower case, which matters on Linux servers. PSR-1 adds that a file should either declare things or do things (print, change settings), not both. - Keep only the entry point in the web root. Modern apps put
index.phpin apublic/folder that the server serves, and everything else, including configuration with passwords, outside it.
my-site/
composer.json dependencies and autoload rules
composer.lock exact versions Composer installed: commit it
vendor/ installed packages; vendor/autoload.php loads them
public/ the web server's document root, the only folder online
index.php the entry point: every request starts here
style.css
src/
Shop/
Product.php class App\Shop\Product (PSR-4: one class per file)
config/
database.php settings and passwords, outside public/Versions
PHP versions and which ones are still supported
Each PHP version gets two years of active support (bug and security fixes), then two years of security fixes only. A PHP file doesn't declare its version; projects state it in composer.json, for example "php": ">=8.2". As of October 2026:
| Version | Released | Active support until | Security fixes until |
|---|---|---|---|
| 8.5 | 20 November 2025 | 31 December 2027 | 31 December 2029 |
| 8.4 | 21 November 2024 | 31 December 2026 | 31 December 2028 |
| 8.3 | 23 November 2023 | 31 December 2025 | 31 December 2027 |
| 8.2 | 8 December 2022 | 31 December 2024 | 31 December 2026 |
Anything older, including the 7.x versions many hosts still offer, gets no fixes from the PHP project. The big steps for code were PHP 5 (2004, a new object model), PHP 7 (2015, a much faster engine and scalar type declarations) and PHP 8 (2020, named arguments, match and a JIT compiler). Code written for PHP 7 often needs small changes for PHP 8, which turned many old warnings into errors.
Troubleshooting
PHP errors you'll meet on a server, and what they mean
| Error message | Usual cause | Fix |
|---|---|---|
| A blank white page, or HTTP 500 | A fatal error, with error display switched off (as it should be on a live site) | Read the server's PHP error log, or switch on display_errors on a development copy |
| Parse error: syntax error, unexpected … | A missing semicolon, bracket or quote, often on the line before the one reported | Run php -l file.php |
| Cannot modify header information - headers already sent by (output started at …) | Output before header(), setcookie() or session_start(): a BOM, whitespace before <?php or after ?>, or an echo | Go to the file and line named in the message; remove the BOM or the closing tag |
| strict_types declaration must be the very first statement | A BOM or text before <?php | Save as UTF-8 without a BOM |
| Call to undefined function mb_strlen() | The extension (here mbstring) isn't installed or enabled | Install or enable it; php -m lists what's loaded |
| Failed opening required 'vendor/autoload.php' | Composer's packages were never installed on this machine | Run composer install |
| Allowed memory size of … bytes exhausted | The script needed more than memory_limit (128 MB by default) | Process data in smaller pieces, or raise the limit |
| Maximum execution time of 30 seconds exceeded | A web request ran past max_execution_time (no limit on the command line) | Move long jobs to a command-line script or a queue |
Security
Is it safe to open a PHP file, and what goes wrong on servers
Opening a .php file on your own computer is safe: browsers and text editors only show the code. The risks are on servers, where PHP files run with the web server's permissions:
- Uploaded PHP files. If an upload form lets someone put a
.phpfile (orphoto.php.jpgon a badly configured server) into a folder the server runs PHP in, they can run any code on your server. This "web shell" is one of the most common ways PHP sites are taken over. Store uploads outside the web root, check file types by content, and switch off PHP in upload folders. - SQL injection. Building database queries by pasting in form values lets attackers rewrite the query. Use prepared statements with PDO or mysqli.
- Cross-site scripting. Escape everything you print with
htmlspecialchars(), as the sample does. - Including files by user input.
include $_GET['page']lets visitors choose which file runs. Map allowed values to files instead. - Secrets in PHP files. Keep database passwords and API keys in a configuration file or environment variables outside the web root, so a server misconfiguration can't publish them.
- Old PHP versions get no security fixes. Check the version your host runs against the table above.
Free downloads
Sample PHP files to download
Free sample PHP files for testing servers, editors, syntax highlighters, linters and upload filters. All pass php -l and run with PHP 8.2 or later, except sample-syntax-error.php, which fails on purpose.
Loading…What's inside sample-page.php
The preview shows the file as source, the way a static host serves it. Open it in a text editor to follow the numbered comments, or run php -S localhost:8000 in its folder and open /sample-page.php to see the page PHP builds from it.
Comments 1 and 2: the opening tag and strict types
<?phpon the first line, a comment explaining how to run the file, thendeclare(strict_types=1)as the first statement.Comment 3: data
An array with string keys holding a week of opening hours, with
nullfor a closed day.Comment 4: an escaping function
h()wrapshtmlspecialchars()so every value printed into the page is safe against cross-site scripting.Comments 5 and 6: input and dates
$_GET['name'] ?? ''reads an optional?name=from the address, and aDateTimeImmutablewith a named time zone works out today's day.Comment 7: the closing tag
PHP stops and the HTML that follows is sent as it is, up to each
<?=or<?phptag inside it.Comments 8 and 9: templates
Short echo tags print values, and a
foreach … endforeachloop writes one table row per day, marking today's row with a class.Comments 10 and 11: a form and constants
A GET form that sends a name back to the same file, and
PHP_VERSIONin the footer, so you can see which PHP built the page.
All sample PHP files
Commented PHP page
sample-page.php · 3.4 KB (3,473 bytes)
A web page mixing PHP and HTML: opening hours with today highlighted, a greeting form and escaped output, with numbered comments explaining each part.
- Checking whether a server runs PHP or serves it as text
- Teaching how PHP and HTML mix
Command-line script
sample-cli.php · 2.1 KB (2,169 bytes)
A pure-PHP length converter with a
#!/usr/bin/env phpshebang and no closing tag. Uses an enum,match,$argv, STDERR and exit codes:php sample-cli.php 5 km mi.- Testing PHP on the command line and in CI
- An example of a file with the closing tag left out
UTF-8 encoding test
sample-utf8.php · 1.9 KB (1,946 bytes)
Greetings in 12 languages plus symbols and emoji, comparing
strlen()withmb_strlen(),strtoupper()withmb_strtoupper(), and JSON with and without escaped Unicode.- Spotting encoding bugs in editors and pipelines
- Checking that the mbstring and intl extensions are installed
UTF-8 with a byte order mark
sample-bom.php · 1.0 KB (1,034 bytes)
Starts with the bytes
EF BB BFbefore<?php. When run, it reports that output had already started at line 1, which is what breaksheader()and sessions.- Reproducing "headers already sent" problems
- Checking whether an editor or pipeline adds or strips a BOM
Missing semicolon (deliberate syntax error)
sample-syntax-error.php · 541 bytes
An
echowithout a semicolon. Clearly labelled;php -lreportsunexpected token "echo"on line 16 and exits with status 255.- Testing how editors, linters and CI report parse errors
- Showing that PHP reports the line after the mistake
100 KB PHP file
sample-100kb.php · 100 KB (102,400 bytes)
A constant array of Roman numerals from 1 to 3,999 and a function that checks every one, padded with a comment to exactly 102,400 bytes.
- Upload and size-limit tests
- Parser, highlighter and OPcache tests
Ways to test with them
- Does the server run PHP? Upload
sample-page.phpand open it. A page with an opening-hours table means PHP ran; the source code means it didn't. - Lint in CI:
php -lshould pass for every sample exceptsample-syntax-error.php, which must fail with exit status 255. - BOM handling: run
sample-bom.php; if it no longer reports output at line 1, something on the way removed the BOM. - Upload filters: many upload forms rightly refuse
.phpfiles. Use the samples to confirm yours does, including the exactly 102,400-bytesample-100kb.phpfor size limits.
Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.
Put it online
Have a PHP file? Share its code with a link.
Drop a .php file on 99helpers and it gets its own address in seconds. The link shows the source as plain text: the code is never run on our servers, so it's a way to share PHP for review or download, not to host a PHP site.
Questions
PHP files, frequently asked
What is a .php file?
A PHP source file: a program, often mixed with HTML, that a web server runs to build a web page. The browser receives only the output, never the PHP code.
How do I open a PHP file?
To see or edit the code, open it in a text editor such as VS Code or Notepad. To see the page it makes, it has to run on a server with PHP, such as the built-in one: php -S localhost:8000.
Why does my browser download the PHP file instead of showing the page?
The server isn't running it through PHP: PHP isn't installed, isn't set up for that extension, or a handler line in .htaccess points to a PHP version that's gone. Opened from your own disk, a PHP file never runs.
I downloaded a file ending in .php. What is it?
Usually the file you wanted, saved under the name of the script that sent it. Open it in a text editor: %PDF at the start means a PDF, PK a ZIP. Rename it with the right extension.
Should I end a PHP file with ?>?
Not if the file contains only PHP. The PHP manual recommends leaving it out, because whitespace after it is sent as output and can cause "headers already sent" errors.
Which PHP version should I use?
A supported one: as of October 2026 that's 8.4 or 8.5 for new projects, with 8.2 and 8.3 still getting security fixes. PHP 8.2's security support ends on 31 December 2026.
Can I convert a PHP file to HTML?
You can save its output: run php page.php > page.html, or save the page from a browser while a server runs it. You get the page as it was at that moment, without the dynamic parts.
Is it safe to open a .php file?
Yes, on your own computer: a browser or text editor only shows the code. PHP files are dangerous on servers that let visitors upload them, because the server would run them.
Related formats
Other file types explained
Keep going
Related
Sources
- PHP manual: PHP tags
- PHP manual: Built-in web server
- PHP: Supported versions
- PHP manual: History of PHP
- PHP-FIG PSR-1: Basic Coding Standard
Last reviewed 27 October 2026.