PHP Language Basics

PHP Tags And Script Structure

A .php file can contain PHP code, text outside PHP, or both. Tags tell the PHP parser which parts are instructions and which parts should pass directly to the output.

Understanding that boundary prevents several beginner mistakes: printing PHP source as text, putting HTML in the wrong parser mode, relying on disabled short tags, and sending accidental whitespace before an HTTP header.

Enter PHP Mode With The Full Opening Tag

A code-only script begins with the full opening tag:

PHP example
<?php

echo "PHP is running\n";

Use <?php, followed by whitespace such as a newline or space. The PHP manual requires that separation so the parser can recognise the token correctly.

The filename extension does not create PHP syntax by itself. A PHP-capable runtime must process the file, and the opening tag tells that runtime where PHP code begins. In a CLI script, run it with:

php script.php

In a web project, the configured server decides which files are sent to PHP. A browser requesting an incorrectly configured server can receive source text or a download instead of executed output; that is a server setup failure, not a different tag syntax.

Leave PHP Mode With A Closing Tag

The closing tag is:

?>

It tells PHP to stop parsing instructions. Content after it is emitted as non-PHP content until another opening tag appears.

A mixed template can therefore alternate between code and HTML:

PHP example
<?php

$pageTitle = 'Orders';
?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title><?= $pageTitle ?></title>
</head>
<body>
    <h1><?= $pageTitle ?></h1>
</body>
</html>

The assignment at the top runs in PHP mode. After ?>, the document markup is outside PHP mode and passes through as output. Each <?= ... ?> section briefly re-enters PHP to print one value.

Variables are covered in the next lesson. For this example, $pageTitle holds the string Orders so the same title can appear in two locations.

Use <?= For A Template Value

The short echo tag:

PHP example
<?= $pageTitle ?>

is shorthand for:

PHP example
<?php echo $pageTitle; ?>

Use <?= ... ?> when a template needs to output one expression. Use a full <?php ... ?> block for assignments, conditions, loops, function calls performed for their effects, or several statements.

The closing tag ends the short echo block, so this compact template expression does not require a semicolon:

PHP example
<p>Status: <?= 'ready' ?></p>

A semicolon is also accepted before the closing tag, but template code is usually clearer when short echo blocks contain only the value being printed.

Do not confuse <?= with the old ordinary short opening tag <?. The ordinary short form can depend on PHP configuration and should be avoided. Use the portable forms <?php for code and <?= for template output.

Know What PHP Does With Outside Text

Anything outside PHP tags is not parsed as PHP instructions. This file contains two output sources:

PHP example
Before PHP
<?php

echo "Inside PHP\n";
?>
After PHP

Its output is:

Before PHP
Inside PHP
After PHP

The first and last lines are emitted because they are outside PHP mode. The middle line is emitted by echo.

This behavior is useful for HTML templates, but surprising in a code-only file. A blank line before <?php is still outside PHP mode and can become output. In a web response, even invisible output can matter if the application later tries to send headers, start a session, or create a redirect.

Omit The Closing Tag In Code-Only Files

When a file ends in PHP code, use this structure:

PHP example
<?php

echo "ready\n";

Do not add ?> merely because an opening tag exists. The closing tag is optional at the end of a PHP-only file, and omitting it removes the opportunity for trailing spaces or blank lines to become accidental output.

This convention is especially important for files that will later be loaded by require or include. A helper file can perform no visible printing and still leak whitespace placed after a closing tag. That output may be harmless in a CLI experiment but can interfere with HTTP headers or corrupt a structured response.

Use a closing tag when the file genuinely needs to return to HTML or another outside format. Omit it when PHP code continues to the end of the file.

End Statements Explicitly

Most PHP statements end with a semicolon:

PHP example
<?php

echo "first\n";
echo "second\n";

The semicolon separates the two instructions. Source newlines improve readability but do not normally terminate statements.

This is invalid:

<?php

echo "first\n"
echo "second\n";

PHP may report the second echo as unexpected because that is where it becomes clear that the previous statement never ended. Inspect the reported line and the statement immediately before it.

A PHP closing tag can imply the end of the final statement in that block. For example, PHP accepts this:

PHP example
<p><?= 'Ready' ?></p>

Do not generalise that convenience to ordinary code. Explicit semicolons make statement boundaries clear, survive later edits, and avoid relying on a closing tag that code-only files should omit.

Format Source For Humans

PHP ignores much ordinary whitespace between tokens. These statements can technically share one line:

PHP example
<?php echo "first\n"; echo "second\n";

Prefer one statement per line:

PHP example
<?php

echo "first\n";
echo "second\n";

Readable structure helps you locate missing punctuation and makes later changes easier to review. Blank lines can separate setup, work, and output, but blank lines inside PHP mode do not print anything by themselves.

Indent code nested inside HTML consistently:

PHP example
<section>
    <h2><?= 'Current orders' ?></h2>
    <p><?= 'No orders have been loaded.' ?></p>
</section>

The spaces before the tags become HTML whitespace in the source document. Browsers usually collapse ordinary text whitespace, but generated formats such as plain text, JSON, and CSV have different rules. Formatting source and formatting output remain separate decisions.

Use Comments Only Inside The Correct Mode

PHP supports // for a line comment and /* ... */ for a block comment:

PHP example
<?php

// This comment ends at the source line boundary.
echo "visible\n";

/* This comment can span
   more than one source line. */
echo "also visible\n";

Comments are recognised while the parser is in PHP mode. HTML comments are markup, not a way to disable PHP execution:

PHP example
<!-- The PHP expression below still executes. -->
<p><?= 'Rendered by PHP' ?></p>

Do not place sensitive PHP operations inside an HTML comment and assume they are inactive. The PHP server executes PHP first; the browser receives the resulting HTML comment later.

Avoid using nested /* ... */ comments. A block comment ends at the first closing */, so attempting to comment out code that already contains block comments can create confusing syntax errors. Remove temporary code or rely on version control rather than building large commented-out sections.

Keep PHP Source Free Of Accidental Prefix Bytes

A code-only file should begin directly with <?php. Invisible bytes before the tag can count as outside output. One common source is a UTF-8 byte-order mark added by an editor.

Configure the editor to save PHP source as UTF-8 without a byte-order mark. If an application reports that headers were already sent from line 1 of a file that appears to begin correctly, inspect the file encoding and bytes as well as visible whitespace.

This is not a reason to fear Unicode text inside PHP strings or templates. It is a file-boundary issue: the source must not emit an unintended prefix before PHP has a chance to control the response.

Separate Code-Only Files From Templates

A code-only script usually has one PHP opening tag and no closing tag:

PHP example
<?php

// Setup and application instructions continue to the end of the file.
echo "Command complete\n";

A template deliberately alternates between PHP and HTML:

PHP example
<?php

$heading = 'Account';
?>
<main>
    <h1><?= $heading ?></h1>
    <p>Welcome to the account page.</p>
</main>

Do not switch modes for every tiny piece of punctuation. Keep ordinary markup outside PHP and use short echo tags for individual values. Keep calculations, data loading, and larger decisions out of the visible template when possible; later lessons introduce file organisation and application structure.

Inspect The Produced Source

When testing a mixed template through the CLI, PHP prints the resulting HTML as text:

php template.php

When testing through a web server, use the browser's view-source tool or curl to inspect the actual response body. The rendered page can hide whitespace, omitted tags, or malformed nesting that remains visible in the source.

A successful PHP syntax check proves only that PHP blocks parse:

php -l template.php

It does not validate HTML structure, prove that values were escaped for their output context, or guarantee that the intended web server executed the file. Use the appropriate check for each layer.

Common Structural Mistakes

Symptom Likely cause
PHP source appears in the browser Server did not send the file through PHP
unexpected token "echo" Previous statement may be missing a semicolon
<? appears in output Old short opening tag is disabled or not parsed
Blank output appears before a response Text, whitespace, or a byte-order mark precedes <?php
Headers cannot be changed Output may already have been emitted
Template value does not appear Expression was not placed inside an echo form
PHP operation runs inside an HTML comment HTML comments do not disable server-side PHP

What You Should Be Able To Do

After this lesson, you should be able to explain PHP parser mode, use <?php and <?= correctly, choose whether a closing tag belongs in a file, terminate statements explicitly, distinguish code-only scripts from mixed templates, recognise accidental outside output, and lint a file before checking its generated HTML.

The authoritative references are PHP's tag syntax, instruction separation, and comment syntax.

Practice

Practice: Build A Mixed PHP Template

Create orders.php as a complete minimal HTML document.

Requirements

  • begin with a full <?php block
  • assign $pageTitle = 'Orders' and $status = 'No orders loaded'
  • leave PHP mode before the document markup begins
  • include <!doctype html>, <html lang="en">, <head>, and <body>
  • print $pageTitle in both <title> and <h1> using <?= ... ?>
  • print $status inside a paragraph using <?= ... ?>
  • include one ordinary HTML paragraph that contains no PHP
  • do not use the old <? opening tag

Run php -l orders.php, then run php orders.php and inspect the generated HTML source. Confirm that no PHP tags or variable names appear in the output.

After the code, identify each point where the file enters or leaves PHP mode. Explain why these fixed course literals are safe to print directly, while later untrusted values will require output-context escaping.

Show solution
PHP example
<?php

$pageTitle = 'Orders';
$status = 'No orders loaded';
?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title><?= $pageTitle ?></title>
</head>
<body>
    <h1><?= $pageTitle ?></h1>
    <p><?= $status ?></p>
    <p>Use this page to review the current order queue.</p>
</body>
</html>

The file enters PHP mode at <?php, performs two assignments, and leaves PHP mode at the first ?>. The document markup then passes directly to the output. Each <?= enters PHP mode to print one expression, and each matching ?> returns to HTML.

Running the file through PHP produces HTML containing Orders and No orders loaded; it does not expose $pageTitle, $status, or the PHP tags.

The two values are fixed literals written by the developer, so they contain no untrusted markup in this exercise. A value originating from a form, URL, database, or external service needs escaping for the HTML context before output. That security rule is taught in the web and security tracks rather than being hidden inside this syntax exercise.

Practice: Repair A Broken Template Boundary

Save this intentionally invalid source as status.php. It is shown as text because PHP cannot parse it yet.

<?php

$status = 'Ready'
echo "Preparing page\n";
<h1><?= $status ?></h1>

The intended output is:

Preparing page
<h1>Ready</h1>

Task

  1. Run php -l status.php and record the first parse error.
  2. Add the missing statement terminator.
  3. Lint again and identify the remaining parser-mode problem.
  4. leave PHP mode before the <h1> markup
  5. keep the short echo tag for the heading value
  6. lint and execute the corrected file

Do not replace the HTML with an echo statement; the exercise is specifically about switching between PHP and template text.

Afterward, explain why PHP can parse <?= $status ?> only after the surrounding <h1> has been placed outside the original PHP block.

Show solution

The assignment first needs a semicolon. The HTML then needs to appear after PHP leaves parser mode.

PHP example
<?php

$status = 'Ready';
echo "Preparing page\n";
?>
<h1><?= $status ?></h1>

The corrected output is:

Preparing page
<h1>Ready</h1>

Without the assignment semicolon, PHP reaches echo while still expecting the first statement to continue. Fixing that reveals the next problem: <h1> is not a PHP instruction while the original full block remains open.

The first ?> moves the parser into outside-text mode, so <h1> is emitted as markup. <?= $status ?> then opens a new short echo block, prints the value, and closes that block before the closing HTML tag. Each piece is valid because it appears in the parser mode designed for it.

Practice: Choose The Correct File Structure

Create two files with different responsibilities.

File 1: health.php

This is a code-only CLI script. It must:

  • start with the full <?php tag
  • print health: ok followed by a newline
  • end after the final PHP statement
  • omit the closing ?> tag

File 2: badge.php

This is a mixed PHP and HTML template. It must:

  • assign $label = 'Ready' in a full PHP block
  • leave PHP mode before the markup
  • output <span class="badge">Ready</span>
  • use <?= $label ?> for the visible label
  • contain no old <? short opening tag
  • contain no PHP operation hidden inside an HTML comment

Lint and execute both files. Record their exact output.

Afterward, explain why health.php should omit its closing tag, why badge.php needs a closing tag before <span>, and why wrapping <?= $label ?> in <!-- ... --> would not stop PHP from executing it.

Show solution
PHP example
<?php

echo "health: ok\n";

Its output is:

health: ok

badge.php deliberately returns to HTML mode:

PHP example
<?php

$label = 'Ready';
?>
<span class="badge"><?= $label ?></span>

Its output is:

<span class="badge">Ready</span>

The code-only file has no reason to leave PHP mode. Omitting its closing tag prevents later trailing whitespace from becoming accidental output.

The template does need to leave PHP mode because <span> is markup rather than a PHP statement. The short echo tag briefly enters PHP mode only for the label value.

An HTML comment is processed after PHP has generated the response. Writing <!-- <?= $label ?> --> would still execute the PHP expression and produce <!-- Ready -->; it would hide markup from normal browser rendering, not disable the server-side PHP operation.