Skip to content

Latest commit

 

History

History
377 lines (297 loc) · 7.12 KB

File metadata and controls

377 lines (297 loc) · 7.12 KB

Control Structures

Introduction

Control structures allow you to add logic to your templates. They use the {% %} syntax and support common programming constructs like conditionals and loops.

If Statements

Basic If

{% if (age >= 18) %}
    <p>You are an adult.</p>
{% endif %}

If-Else

{% if (isLoggedIn) %}
    <p>Welcome back, {{ username }}!</p>
{% else %}
    <p>Please log in.</p>
{% endif %}

If-ElseIf-Else

{% 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 %}

Complex Conditions

{% 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 %}

Nested If Statements

{% 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 %}

For Loops

The for loop provides traditional C-style iteration with initialization, condition, and update.

Basic For Loop

{% 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>

Counting Down

{% for (i = 10; i > 0; i--) %}
    <div>{{ i }}</div>
{% endfor %}

Custom Increment

{% for (i = 0; i < 100; i = i + 10) %}
    <span>{{ i }}</span>
{% endfor %}

Using Loop Variable

<ul>
{% for (i = 0; i < items.length; i++) %}
    <li>{{ i + 1 }}. {{ items[i] }}</li>
{% endfor %}
</ul>

Foreach Loops

The foreach loop iterates over collections, arrays, and maps.

Iterating Over Lists

<ul>
{% foreach (fruit in fruits) %}
    <li>{{ fruit }}</li>
{% endforeach %}
</ul>

Java Context:

List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry");
ctx.add("fruits", fruits);

Iterating Over Arrays

{% foreach (item in items) %}
    <div>{{ item }}</div>
{% endforeach %}

Iterating Over Maps (with Key)

<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);

Nested Foreach

{% foreach (category in categories) %}
    <h2>{{ category.name }}</h2>
    <ul>
    {% foreach (product in category.products) %}
        <li>{{ product.name }} - ${{ product.price }}</li>
    {% endforeach %}
    </ul>
{% endforeach %}

Empty Collections

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

While loops execute as long as a condition is true.

Basic While Loop

{% 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 with Complex Condition

{% while (hasMore && index < maxItems) %}
    <div>{{ items[index] }}</div>
    {% index = index + 1 %}
{% endwhile %}

Break and Continue

Control loop execution with break and continue statements.

Break Statement

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 %}

Continue Statement

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 %}

Template Includes

Include other templates to create modular, reusable components.

Basic Include

{% include 'header.jhp' %}

<main>
    <h1>{{ title }}</h1>
    <p>{{ content }}</p>
</main>

{% include 'footer.jhp' %}

Include with Relative Paths

{% include 'partials/navigation.jhp' %}
{% include '../shared/sidebar.jhp' %}

Nested Includes

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>

Include Security

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 -->

Combining Control Structures

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 %}

Best Practices

  1. Keep Logic Simple - Complex logic belongs in Java code, not templates
  2. Avoid Deep Nesting - Extract complex structures into separate templates
  3. Use Meaningful Variable Names - Make templates readable
  4. Watch for Infinite Loops - Always ensure loop conditions will terminate
  5. Prefer Foreach Over For - When iterating collections, foreach is cleaner

Next Steps