Control structures allow you to add logic to your templates. They use the {% %} syntax and support common programming constructs like conditionals and loops.
{% if (age >= 18) %}
<p>You are an adult.</p>
{% endif %}{% if (isLoggedIn) %}
<p>Welcome back, {{ username }}!</p>
{% else %}
<p>Please log in.</p>
{% endif %}{% if (score >= 90) %}
<span class="grade-a">Grade: A</span>
{% elseif (score >= 80) %}
<span class="grade-b">Grade: B</span>
{% elseif (score >= 70) %}
<span class="grade-c">Grade: C</span>
{% else %}
<span class="grade-f">Grade: F</span>
{% endif %}{% if (user.age >= 18 && user.verified) %}
<p>Full access granted.</p>
{% endif %}
{% if (isAdmin || isModerator) %}
<button>Manage Content</button>
{% endif %}
{% if (!isDeleted && (isPublished || isDraft)) %}
<article>{{ content }}</article>
{% endif %}{% if (user) %}
{% if (user.isPremium) %}
<div class="premium-content">
{{ premiumContent }}
</div>
{% else %}
<div class="free-content">
{{ freeContent }}
</div>
{% endif %}
{% else %}
<p>Please log in to view content.</p>
{% endif %}The for loop provides traditional C-style iteration with initialization, condition, and update.
{% for (i = 0; i < 5; i++) %}
<p>Item {{ i }}</p>
{% endfor %}Output:
<p>Item 0</p>
<p>Item 1</p>
<p>Item 2</p>
<p>Item 3</p>
<p>Item 4</p>{% for (i = 10; i > 0; i--) %}
<div>{{ i }}</div>
{% endfor %}{% for (i = 0; i < 100; i = i + 10) %}
<span>{{ i }}</span>
{% endfor %}<ul>
{% for (i = 0; i < items.length; i++) %}
<li>{{ i + 1 }}. {{ items[i] }}</li>
{% endfor %}
</ul>The foreach loop iterates over collections, arrays, and maps.
<ul>
{% foreach (fruit in fruits) %}
<li>{{ fruit }}</li>
{% endforeach %}
</ul>Java Context:
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry");
ctx.add("fruits", fruits);{% foreach (item in items) %}
<div>{{ item }}</div>
{% endforeach %}<dl>
{% foreach (key, value in config) %}
<dt>{{ key }}</dt>
<dd>{{ value }}</dd>
{% endforeach %}
</dl>Java Context:
Map<String, String> config = new HashMap<>();
config.put("theme", "dark");
config.put("language", "en");
ctx.add("config", config);{% foreach (category in categories) %}
<h2>{{ category.name }}</h2>
<ul>
{% foreach (product in category.products) %}
<li>{{ product.name }} - ${{ product.price }}</li>
{% endforeach %}
</ul>
{% endforeach %}If a collection is empty or null, the foreach body won't execute:
{% foreach (item in emptyList) %}
<p>This won't be displayed</p>
{% endforeach %}While loops execute as long as a condition is true.
{% while (count < 5) %}
<p>Count: {{ count }}</p>
{% count = count + 1 %}
{% endwhile %}Note: Be careful with while loops to avoid infinite loops. Ensure the condition will eventually become false.
{% while (hasMore && index < maxItems) %}
<div>{{ items[index] }}</div>
{% index = index + 1 %}
{% endwhile %}Control loop execution with break and continue statements.
Exit a loop early:
{% for (i = 0; i < 100; i++) %}
{% if (i == 10) %}
{% break %}
{% endif %}
<p>{{ i }}</p>
{% endfor %}
<!-- Stops at 9 -->{% foreach (item in items) %}
{% if (item == "STOP") %}
{% break %}
{% endif %}
<li>{{ item }}</li>
{% endforeach %}Skip to the next iteration:
{% for (i = 0; i < 10; i++) %}
{% if (i % 2 == 0) %}
{% continue %}
{% endif %}
<p>Odd number: {{ i }}</p>
{% endfor %}
<!-- Only displays odd numbers -->{% foreach (user in users) %}
{% if (!user.active) %}
{% continue %}
{% endif %}
<div class="user">{{ user.name }}</div>
{% endforeach %}Include other templates to create modular, reusable components.
{% include 'header.jhp' %}
<main>
<h1>{{ title }}</h1>
<p>{{ content }}</p>
</main>
{% include 'footer.jhp' %}{% include 'partials/navigation.jhp' %}
{% include '../shared/sidebar.jhp' %}layout.jhp:
<!DOCTYPE html>
<html>
<head>
{% include 'partials/head.jhp' %}
</head>
<body>
{% include 'partials/header.jhp' %}
<main>
<!-- Content here -->
</main>
{% include 'partials/footer.jhp' %}
</body>
</html>JHP enforces security by:
- Restricting includes to the base directory (if configured)
- Detecting circular includes
- Limiting include depth (default: 15 levels)
Circular Include Detection:
<!-- page1.jhp -->
{% include 'page2.jhp' %}
<!-- page2.jhp -->
{% include 'page1.jhp' %} <!-- Error: Circular include detected -->You can combine different control structures:
{% if (categories) %}
{% foreach (category in categories) %}
<section>
<h2>{{ category.name }}</h2>
{% if (category.items) %}
<ul>
{% for (i = 0; i < category.items.length && i < 10; i++) %}
<li>{{ category.items[i].name }}</li>
{% endfor %}
</ul>
{% else %}
<p>No items in this category.</p>
{% endif %}
</section>
{% endforeach %}
{% else %}
<p>No categories available.</p>
{% endif %}- Keep Logic Simple - Complex logic belongs in Java code, not templates
- Avoid Deep Nesting - Extract complex structures into separate templates
- Use Meaningful Variable Names - Make templates readable
- Watch for Infinite Loops - Always ensure loop conditions will terminate
- Prefer Foreach Over For - When iterating collections, foreach is cleaner
- Learn about Functions
- Explore Context & Variables
- Review Configuration options