PHP Tags
What Are PHP Tags?
In simple terms: PHP tags are markers that tell the PHP engine where PHP code starts and where it ends inside a file.
Technically: When PHP processes a file, it begins in output mode, where every character is copied directly to the output. An opening tag switches the parser into PHP mode, where text is interpreted as code. A closing tag switches it back to output mode.
Why Tags Are Needed
PHP was designed to be embedded in documents such as HTML pages. A single file may contain HTML, CSS, JavaScript, and PHP. Tags give the engine an unambiguous way to separate the parts it must execute from the parts it must simply pass through.
<h1>Title</h1> ← output mode: sent as-is
<?php ← switch to PHP mode
echo "Hello"; ← executed
?> ← switch back to output mode
<p>Footer</p> ← output mode: sent as-is
Types of PHP Tags
| Tag | Name | Status |
|---|---|---|
<?php ... ?> | Standard tags | Always available — use these |
<?= ... ?> | Short echo tag | Always available since PHP 5.4 — use in templates |
<? ... ?> | Short open tag | Depends on short_open_tag setting — avoid |
<% ... %> | ASP-style tags | Removed in PHP 7.0 |
<script language="php"> ... </script> | Script tags | Removed in PHP 7.0 |
The Standard Opening Tag: <?php
Syntax
<?php
// code
?>
Example
<?php
$course = "PHP Fundamentals";
$lessons = 42;
?>
<h2><?php echo $course; ?></h2>
<p>This course contains <?php echo $lessons; ?> lessons.</p>
Output (HTML)
<h2>PHP Fundamentals</h2>
<p>This course contains 42 lessons.</p>
How It Works
- The first block sets two variables. It produces no output itself.
?>returns to output mode, so<h2>is copied to the output.<?php echo $course; ?>switches into PHP mode briefly, prints the variable, and switches back.- Variables created in the first block are still available in later blocks. All blocks in a file run as one script; switching modes does not reset anything.
Why <?php Is the Recommended Tag
<?php works on every PHP installation regardless of configuration. Code that uses it can be moved to any server without changes. It also cannot be confused with XML declarations such as <?xml version="1.0"?>, which is a real problem for short open tags (explained below).
Whitespace After <?php
The opening tag must be followed by whitespace — a space, tab, or newline:
<?php echo "Works"; ?>
<?phpecho "Does not work"; ?>
In the second line, PHP does not recognize <?phpecho as an opening tag, so the entire line is treated as ordinary text and printed literally.
The Short Echo Tag: <?=
What It Is
<?= is a shortcut for <?php echo. It opens PHP mode, prints the value of the expression, and is closed with ?>.
Syntax
<?= expression ?>
Example
<?php
$product = "Wireless Mouse";
$price = 799;
$inStock = true;
?>
<div class="product">
<h3><?= $product ?></h3>
<p>Price: ₹<?= number_format($price) ?></p>
<p>Status: <?= $inStock ? 'Available' : 'Sold out' ?></p>
</div>
Output (HTML)
<div class="product">
<h3>Wireless Mouse</h3>
<p>Price: ₹799</p>
<p>Status: Available</p>
</div>
How It Works
<?= $product ?>is exactly equivalent to<?php echo $product; ?>.- Any expression can be used: a variable, a function call such as
number_format($price), or a ternary such as$inStock ? 'Available' : 'Sold out'. - No semicolon is needed, because the closing tag ends the statement.
Why Use It
Templates often contain dozens of small outputs. Compare:
<td><?php echo $order['id']; ?></td>
<td><?= $order['id'] ?></td>
The short echo tag is shorter and easier to read, which is why template-heavy code (and frameworks' plain-PHP views) uses it widely.
When Not to Use It
<?= is designed only for printing a single expression. Use <?php for logic such as assignments, loops, and conditions:
<?php foreach ($items as $item): ?>
<li><?= $item ?></li>
<?php endforeach; ?>
The foreach ... endforeach form shown here is the alternative syntax for control structures, which is designed for templates and is covered in the Alternative Syntax lesson.
Security note: When the printed value comes from users, a database, or any external source, escape it:
<?= htmlspecialchars($comment) ?>. Printing raw user input allows cross-site scripting (XSS) attacks. This is covered in Escaping Output (htmlspecialchars).
The Short Open Tag: <? (Avoid)
What It Is
<? is an older, shorter form of <?php:
<? echo "Hello"; ?>
Why It Should Be Avoided
- It depends on configuration. It works only if the
short_open_tagdirective is enabled. Thephp.ini-developmentandphp.ini-productionfiles that ship with PHP set it toOff. Code that relies on it may work on one server and print raw source code on another — potentially exposing logic or credentials. - It conflicts with XML. An XML declaration starts with
<?xml. With short open tags enabled, PHP tries to interpret it as code and throws a parse error. You would have to output it through PHP, for example<?php echo '<?xml version="1.0"?>'; ?>, just to avoid the conflict.
You will still find <? in very old projects. When maintaining such code, replace it with <?php.
Note:
short_open_tagdoes not affect<?=. The short echo tag has been always available since PHP 5.4, so it is safe to use everywhere.
The Closing Tag: ?>
What It Does
?> ends PHP mode and returns to output mode. It also has two behaviors that are important to understand.
1. The Closing Tag Implies a Semicolon
<?php echo "No semicolon needed" ?>
PHP treats ?> as the end of the statement. This is why <?= $value ?> needs no semicolon.
2. One Newline Directly After ?> Is Removed
If a line break immediately follows the closing tag, PHP removes that single line break from the output.
Example
<?php echo "Line 1" ?>
Line 2
Output
Line 1Line 2
Why This Happens
The newline after ?> is swallowed, so Line 2 follows Line 1 directly. This behavior exists so that template files and included files do not add unwanted blank lines to the output. Only one newline is removed; a second newline or any spaces after ?> are output normally.
Omitting the Closing Tag in PHP-Only Files
When a file contains only PHP code — classes, functions, configuration, or scripts — leave out the closing ?> tag.
Recommended
<?php
// config.php
const DB_HOST = 'localhost';
const DB_NAME = 'shop';
Not Recommended
<?php
// config.php
const DB_HOST = 'localhost';
const DB_NAME = 'shop';
?>
Why the Closing Tag Causes Problems
In the second version, anything after ?> — a blank line, a space, or a line break from the editor — is in output mode and is sent to the browser as soon as the file is loaded.
That is a problem because of how HTTP works. A response consists of headers (status code, cookies, redirects, content type) followed by the body (the page content). Headers must be sent first. The moment PHP outputs even one character of body content, it sends the headers and can no longer change them.
Example: The "Headers Already Sent" Error
config.php (with a blank line after ?>):
<?php
const SITE_NAME = 'My Shop';
?>
login.php:
<?php
require 'config.php';
// After a successful login, redirect to the dashboard
header('Location: /dashboard.php');
exit;
Result
Warning: Cannot modify header information - headers already sent by (output started at /var/www/config.php:4) in /var/www/login.php on line 5
Step-by-Step Explanation
login.phploadsconfig.php.- The line break directly after
?>is removed, but the next line break on line 4 is output. - That output forces PHP to send the HTTP headers immediately.
header('Location: ...')tries to add a redirect header, but the headers were already sent, so PHP issues a warning and the redirect does not happen.
The warning message is helpful: output started at /var/www/config.php:4 tells you exactly which file and line produced the stray output. Without the closing tag, there is no output mode at the end of config.php, so no stray whitespace can ever be sent.
The same error affects setcookie(), session_start(), and http_response_code(), because all of them need to modify headers.
Coding standard: PER Coding Style (the successor to PSR-12) states that the closing
?>tag must be omitted from files containing only PHP.
A Hidden Cause: The UTF-8 BOM
Some editors save files with a byte order mark (BOM) — three invisible bytes (EF BB BF) at the very start of a UTF-8 file. Because these bytes appear before <?php, PHP is still in output mode and sends them to the browser.
Symptoms
- "Headers already sent" warnings reporting
output started at ...:1, even though line 1 contains only<?php - Strange characters (
) at the top of pages or at the start of JSON responses, which breaks JSON parsing in JavaScript
Fix
Save PHP files as UTF-8 without BOM. In Visual Studio Code, click the encoding in the status bar, choose Save with Encoding, and select UTF-8. Most modern editors use UTF-8 without BOM by default.
Files That Mix PHP and HTML
When a file contains HTML after PHP code, you need the closing tag to return to output mode.
Example
<?php
$pageTitle = "Contact Us";
$email = "support@example.com";
?>
<!DOCTYPE html>
<html>
<head>
<title><?= htmlspecialchars($pageTitle) ?></title>
</head>
<body>
<h1><?= htmlspecialchars($pageTitle) ?></h1>
<p>Email us at <a href="mailto:<?= $email ?>"><?= $email ?></a></p>
</body>
</html>
How It Works
- The first PHP block prepares data.
?>switches to output mode for the HTML document.- Short echo tags insert values exactly where they are needed.
- The file ends in HTML, so no closing tag issue exists — the trailing content is intentionally part of the output.
A good structure for such files is: logic at the top, presentation below. Keeping calculations, database queries, and validation in the top block — and only simple output in the HTML — makes templates much easier to read and maintain. Larger applications take this further by separating logic and templates into different files.
Common Mistakes
Using <? and Seeing Raw Code in the Browser
Why it happens: short_open_tag is disabled on the server.
Fix: Replace every <? with <?php (but leave <?= as it is).
"Headers Already Sent" Warnings
Why it happens: Output was sent before header(), setcookie(), or session_start(). Common causes: whitespace after ?> in an included file, a BOM, or an echo placed before the header call.
Fix: Read the output started at file:line part of the warning, remove the stray output there, and omit ?> in PHP-only files.
Missing Space After <?php
<?phpecho "Hi";
What happens: The code is printed as text instead of executing.
Fix: Add a space or newline: <?php echo "Hi";.
Writing Logic Inside <?=
<?= $total = $price * $qty ?>
This is valid PHP — it assigns and prints the value — but it hides an assignment inside an output tag, which makes templates confusing. Perform the calculation in a <?php block and print it with <?= $total ?>.
Forgetting ?> Before HTML
<?php
$name = "Asha";
<h1>Hello</h1>
What happens: PHP Parse error: syntax error, unexpected token "<".
Why: PHP is still in PHP mode, so it tries to interpret <h1> as code.
Fix: Close PHP mode with ?> before writing HTML.
Best Practices
- Use
<?phpfor all code blocks. - Use
<?= ?>for printing values in HTML templates, and escape external data withhtmlspecialchars(). - Never use
<?short open tags. - Omit the closing
?>in files that contain only PHP. - Save files as UTF-8 without BOM.
- In mixed files, keep logic at the top and output below to keep templates clean.
Official reference: https://www.php.net/manual/en/language.basic-syntax.phptags.php