Alternative Syntax

JA JASWANT Updated 17 Oct 2026
7 min read ·Lesson 4 of 248
In this post

What Is the Alternative Syntax? In simple terms: PHP offers a second way to write control structures — if , foreach , for , while , and switch — that uses a colon ( : ) to open the block and a keyword

What Is the Alternative Syntax?

In simple terms: PHP offers a second way to write control structures — if, foreach, for, while, and switch — that uses a colon (:) to open the block and a keyword such as endif; or endforeach; to close it, instead of curly braces.

Technically: For if, while, for, foreach, and switch, the opening brace { can be replaced with : and the closing brace } with endif;, endwhile;, endfor;, endforeach;, or endswitch;. The behavior is identical; only the syntax differs.

Brace SyntaxAlternative Syntax
if (...) { ... }if (...): ... endif;
elseif (...) { ... }elseif (...): ...
else { ... }else: ...
foreach (...) { ... }foreach (...): ... endforeach;
for (...) { ... }for (...): ... endfor;
while (...) { ... }while (...): ... endwhile;
switch (...) { ... }switch (...): ... endswitch;

Why It Exists

In files that mix PHP and HTML, a closing brace on its own line says nothing about what it closes:

<?php } ?>
<?php } ?>
<?php } ?>

In a long template, matching these braces to their opening statements is difficult. The alternative syntax names each block's end:

<?php endif; ?>
<?php endforeach; ?>
<?php endif; ?>

That is why the alternative syntax is the standard for PHP templates, including WordPress themes and the plain-PHP view files of many frameworks.


if, elseif, else

Syntax

<?php if (condition): ?>
    ... HTML ...
<?php elseif (otherCondition): ?>
    ... HTML ...
<?php else: ?>
    ... HTML ...
<?php endif; ?>

Example

<?php $unread = 3; ?>
<?php if ($unread === 0): ?>
<p>No new messages.</p>
<?php elseif ($unread === 1): ?>
<p>You have 1 new message.</p>
<?php else: ?>
<p>You have <?= $unread ?> new messages.</p>
<?php endif; ?>

Output (HTML)

<p>You have 3 new messages.</p>

How It Works

  • Each condition line ends with : instead of {.
  • elseif and else also end with :.
  • endif; closes the whole structure.
  • Only the HTML of the matching branch is sent to the browser.

Important: In the alternative syntax, write elseif as one word. else if (...): causes a parse error, because else if is really an else containing a new if, which would need its own endif;.


foreach ... endforeach

<?php
$menu = [
    'Home' => '/',
    'Courses' => '/courses',
    'Contact' => '/contact',
];
$current = '/courses';
?>
<ul class="menu">
<?php foreach ($menu as $label => $url): ?>
    <li><a href="<?= $url ?>"<?= $url === $current ? ' class="active"' : '' ?>><?= $label ?></a></li>
<?php endforeach; ?>
</ul>

Output (HTML)

<ul class="menu">
    <li><a href="/">Home</a></li>
    <li><a href="/courses" class="active">Courses</a></li>
    <li><a href="/contact">Contact</a></li>
</ul>

The loop body is plain HTML with short echo tags. A ternary adds class="active" only to the current page's link.


for ... endfor

<?php $totalSteps = 3; ?>
<?php for ($step = 1; $step <= $totalSteps; $step++): ?>
<span class="step">Step <?= $step ?> of <?= $totalSteps ?></span>
<?php endfor; ?>

Output (HTML)

<span class="step">Step 1 of 3</span>
<span class="step">Step 2 of 3</span>
<span class="step">Step 3 of 3</span>

while ... endwhile

The alternative syntax works in pure PHP code as well, although braces are far more common there:

<?php
$countdown = 3;

while ($countdown > 0):
    echo "$countdown...\n";
    $countdown--;
endwhile;

echo "Go!\n";

Output

3...
2...
1...
Go!

In non-template code, coding standards generally recommend braces. Use the alternative syntax where it improves readability — mainly when switching between PHP and HTML.


switch ... endswitch

<?php $role = 'editor'; ?>
<nav>
<?php switch ($role):
    case 'admin': ?>
    <a href="/admin">Admin panel</a>
<?php break;
    case 'editor': ?>
    <a href="/posts">Manage posts</a>
<?php break;
    default: ?>
    <a href="/profile">My profile</a>
<?php endswitch; ?>
</nav>

Output (HTML)

<nav>
    <a href="/posts">Manage posts</a>
</nav>

The Whitespace Rule for switch

PHP does not allow any output — not even whitespace or a newline — between switch (...): and the first case. Writing them in separate PHP blocks with indentation in between causes a parse error:

<?php switch ($role): ?>
    <?php case 'admin': ?>    <!-- the spaces before this line are output -->

The safe pattern, shown in the example above, keeps switch (...): and the first case inside the same PHP block. Because of this quirk, if/elseif or a match expression that selects a value is often simpler than switch in templates.


Do Not Mix the Two Syntaxes in One Structure

A single control structure must use one syntax throughout:

<?php if ($isLoggedIn): ?>
    <p>Welcome!</p>
<?php else { ?>          <!-- parse error -->
    <p>Please log in.</p>
<?php } ?>

Different structures may use different syntaxes (for example, a braced if in the logic section and an alternative-syntax foreach in the template), but each one must be consistent from start to end.


Whitespace in Templates

PHP removes one newline directly after ?>. This is why lines that contain only a PHP control tag, such as <?php endif; ?>, do not leave blank lines in the output. Two consequences are worth knowing:

  • A line that ends with <?= $value ?> loses its newline, so the next line's content is joined to it. Ending such lines with HTML (for example </span>) keeps the line breaks.
  • Indentation before a <?php tag is output as text. It does not matter for HTML rendering, but it can affect whitespace-sensitive output such as plain-text emails.

HTML rendering ignores most whitespace differences, so this mainly affects how the generated source looks.


Practical Example: Product Listing Template

<?php
$products = [
    ['name' => 'Desk Lamp', 'price' => 1299, 'stock' => 4],
    ['name' => 'Notebook <A5>', 'price' => 60, 'stock' => 0],
];
?>
<?php if ($products === []): ?>
<p>No products found.</p>
<?php else: ?>
<ul class="products">
<?php foreach ($products as $product): ?>
    <li class="<?= $product['stock'] > 0 ? 'in-stock' : 'sold-out' ?>">
        <span class="name"><?= htmlspecialchars($product['name']) ?></span>
        <span class="price">₹<?= number_format($product['price']) ?></span>
<?php if ($product['stock'] === 0): ?>
        <span class="badge">Sold out</span>
<?php elseif ($product['stock'] < 5): ?>
        <span class="badge">Only <?= $product['stock'] ?> left</span>
<?php endif; ?>
    </li>
<?php endforeach; ?>
</ul>
<?php endif; ?>

Output (HTML)

<ul class="products">
    <li class="in-stock">
        <span class="name">Desk Lamp</span>
        <span class="price">₹1,299</span>
        <span class="badge">Only 4 left</span>
    </li>
    <li class="sold-out">
        <span class="name">Notebook <A5></span>
        <span class="price">₹60</span>
        <span class="badge">Sold out</span>
    </li>
</ul>

Step-by-Step Explanation

  1. Data first: the PHP block at the top prepares the data. In a real application, it would come from a database, and the template would contain only presentation.
  2. Empty state: if ($products === []): ... else: shows a message when there is nothing to list. Always handling the empty case avoids rendering an empty <ul>.
  3. Loop: foreach ... endforeach; repeats the <li> block for each product.
  4. Conditional class: a ternary inside <?= ?> chooses in-stock or sold-out for styling.
  5. Escaping: htmlspecialchars() converts <A5> into <A5>, so a product name can never break the HTML or inject a script.
  6. Badges: a nested if ... elseif ... endif; shows "Sold out" or a low-stock warning, and nothing for well-stocked items.
  7. Clean output: each line that contains only a control tag ends with ?>, so its newline is removed and no blank lines appear.

Every closing tag (endif;, endforeach;) tells the reader exactly which structure is ending, even in a much longer template.


Alternative Syntax and Template Engines

Template engines provide even more compact syntax built on the same idea, and they escape output automatically:

Plain PHP (alternative syntax)Blade (Laravel)Twig (Symfony)
<?php if ($x): ?>@if ($x){% if x %}
<?php endif; ?>@endif{% endif %}
<?php foreach ($items as $item): ?>@foreach ($items as $item){% for item in items %}
<?= htmlspecialchars($name) ?>{{ $name }}{{ name }}

Learning the alternative syntax makes these engines easy to understand, because they follow the same structure.


Common Mistakes

Writing else if: Instead of elseif:

Effect: Parse error.

Fix: Use elseif (...):.

Forgetting the Semicolon After endif, endforeach, …

Effect: Usually works when the closing ?> follows immediately (because ?> implies a semicolon), but fails in pure PHP code.

Fix: Always write endif;, endforeach;, and so on.

Mixing Braces and Alternative Syntax in One Structure

Effect: Parse error.

Fix: Use one syntax per structure.

Output Between switch and the First case

Effect: Parse error.

Fix: Put switch (...): and the first case in the same PHP block, or use if/elseif.

Forgetting to Escape Output in Templates

Effect: Broken HTML and XSS vulnerabilities.

Fix: Wrap every external value in htmlspecialchars() (or use a template engine that escapes automatically).


Best Practices

  • Use the alternative syntax in HTML templates; use braces in pure PHP logic.
  • Keep logic (queries, calculations) above or outside the template; keep templates to loops, conditions, and output.
  • Always handle the empty state of lists.
  • Escape every dynamic value with htmlspecialchars().
  • Use elseif as one word and end every structure with its matching end...; keyword.

Official reference: https://www.php.net/manual/en/control-structures.alternative-syntax.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Home PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope PHP Casting Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence Continue Statement Modify Strings PHP If...Else...Elseif PHP If Modify Strings PHP If Operators PHP Functions Concatenate Strings PHP If...Else User-defined Functions Slicing Strings Function Arguments PHP Shorthand if Escape Characters Default Argument Values PHP Nested if Pass by Reference String Interpolation Named Arguments PHP File Upload Variadic Functions Return Values Search in Strings Multibyte Strings Type Declarations in Functions PHP Numbers PHP Math PHP Floats PHP Random Numbers PHP Constants PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Cookies PHP Destructor PHP Access Modifiers Readonly Properties PHP Sessions PHP Inheritance Method Overriding PHP Filters The final Keyword CSRF Protection PHP Filters Advanced Session Security Secure Cookies PHP Magic Constants File Upload Security PHP Callback Functions PHP Operators Filesystem Security PHP JSON Arithmetic Operators Error Reporting in Production Hiding PHP Assignment Operators PHP Configuration (php.ini) Comparison Operators PHP Command Line (CLI) PHP Exceptions Increment / Decrement Operators Migrating to PHP 8 PHP Form Validation PHP Form Required PHP Form URL/E-mail Error Handling Form Input Sanitizing Escaping Output (htmlspecialchars) Custom Error Handler Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention Garbage Collection Project: Simple Blog PHP What is OOP PHP Classes/Objects The $this Keyword Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where Debugging PHP Project: Image Upload Gallery $_SESSION $_ENV PHP RegEx RegEx Patterns Heredoc and Nowdoc RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures Composer PHP Form Handling PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro PHP Class Constants Encryption with Sodium Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Variables Scope Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS What Is `$_SERVER` ? $_REQUEST $_POST $_GET $_FILES $_COOKIE PHP Type Juggling MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes PSR-4 Autoloading Installing Extensions (PECL / PIE) OPcache & Performance PHP-FPM Project: Contact Form with Email Project: Login & Registration System Project: CRUD App with MySQL Project: Shopping Cart with Sessions Project: REST API with PHP DateTime Class Timezones PHP Include Include vs Require PHP File Handling PHP File Open/Read PHP File Create/Write File Delete / Rename / Copy PHP Directories PHP CSV Files
Ask about this post
AI Ask about this post

Ask questions about Alternative Syntax and get answers drawn from it.

Signed-in readers only.