# **Chapter 8: Expression Tags - Controlled Dynamic Content** ## **8.1 The Philosophy: Safe, Limited Template Expressions** Expression tags in SartajPHP represent a carefully designed compromise between power and safety. Unlike PHP's unrestricted `<?php ?>` tags or template engines that allow arbitrary code execution, SartajPHP's expression tags provide a **controlled, limited subset of PHP syntax** specifically designed for template logic. ### **8.1.1 The Security Problem with Full PHP in Templates** Consider the dangers of allowing full PHP in templates: ```php <!-- ❌ DANGEROUS: Full PHP access --> <?php // Could execute dangerous code system($_GET['cmd']); // Or leak sensitive data echo file_get_contents('/etc/passwd'); // Or modify application state $_SESSION['admin'] = true; ?> ``` Even without malicious intent, template PHP often becomes messy: ```php <!-- ❌ MESSY: Business logic in templates --> <?php $user = getUserFromDatabase($userId); $orders = getRecentOrders($user); $total = calculateOrderTotal($orders); if ($user->isPremium()) { $discount = applyPremiumDiscount($total); } echo formatCurrency($total - $discount); ?> ``` ### **8.2.2 The SartajPHP Solution: Limited but Powerful** SartajPHP expression tags provide just enough power for presentation logic while preventing security issues and messy code: ```html <!-- ✅ SAFE & CLEAN: Expression tags --> #{$userId = $parentgate->getUserIdFromSession()}# <div class="order-summary"> <h2>Order Total: ##{$parentgate->formatCurrency($orderTotal)}#</h2> #{if $parentgate->isPremium() }# <p class="discount">Premium Discount Applied: ##{$parentgate->formatCurrency($premiumDiscount)}# </p> #{endif}# <p>Final Amount: ##{$parentgate->formatCurrency($orderTotal - $discount)}#</p> </div> ``` **Key limitations that ensure safety:** 1. **No function definition** (can't create new functions) 2. **No class definition** (can't create new classes) 3. **Limited function calls** (only allowed functions) 4. **No superglobal access** (no `$_GET`, `$_POST`, etc.) 5. **Controlled variable scope** (limited to template context) ## **8.2 Expression Tag Syntax and Types** ### **8.2.1 Two Tag Types** SartajPHP provides two expression tag formats for different purposes: **Output Tags (`##{ }#`) - Display Results:** ```html <!-- Evaluates expression and outputs result --> <p>Welcome, ##{$userName}#!</p> <p>Total: $##{calculateTotal($items)}#</p> <p>Status: ##{$isActive ? 'Active' : 'Inactive'}#</p> ``` **Silent Tags (`#{ }#`) - Execute Without Output:** ```html <!-- Executes code but doesn't output anything --> #{ $counter = 0; }# #{ $items = getItems(); }# #{ $user = loadUserData(); }# <!-- Useful for setup before output --> #{ $fullName = $firstName . ' ' . $lastName; }# <p>Hello, ##{$fullName}#</p> ``` ### **8.2.2 Output Modifiers** Expression tags support output modifiers for different contexts: ```html <!-- Default: HTML escaped --> <p>##{$userInput}#</p> <!-- "&lt;script&gt;" becomes "&lt;script&gt;" --> <!-- Raw output (use with caution!) --> <p>##{raw:$trustedHtml}#</p> <!-- HTML rendered as-is --> <!-- JSON output (for JavaScript) --> <script> var userData = ##{json:$userArray}#; </script> <!-- URL encoded --> <a href="/search?q=##{url:$searchTerm}#">Search</a> <!-- Combined modifiers --> <script> // JSON inside JavaScript string var message = "##{json:htmlspecialchars($message)}#"; </script> ``` ### **8.2.3 Tag Nesting and Combination** Expression tags can be combined but not nested: ```html <!-- ❌ INVALID: Nested expression tags --> <p>##{ "Result: " . ##{$value}# }#</p> <!-- ✅ VALID: Single expression with concatenation --> <p>##{ "Result: " . $value }#</p> <!-- ✅ VALID: Multiple separate tags --> #{ $prefix = "Result: "; }# <p>##{$prefix . $value}#</p> <!-- ✅ VALID: Complex single expression --> <p>##{ "User: " . $user->name . " (" . ($user->isActive ? 'Active' : 'Inactive') . ")" }#</p> ``` ## **8.3 Supported Syntax and Features** Based on provided examples, here's what SartajPHP expression tags support: ### **8.3.1 Variable Assignment and Arithmetic** ```html <!-- Basic assignment and arithmetic --> #{ $x = 3; $y = 4; }# <p>Calculation: ##{$x - ($y * 2)}#</p> <!-- -5 --> <p>Multiplication: ##{$x * 8}#</p> <!-- 24 --> <!-- Multiple assignments --> #{ $a = 10; $b = 20; $c = 30; }# <p>Complex: ##{($a + $b) * $c}#</p> <!-- 900 --> <p>Mixed: ##{$a * $b + $c / 2}#</p> <!-- 215 --> <!-- Increment/Decrement --> #{ $counter = 0; $total = 0; }# #{ $counter = $counter + 1; $total = $total + 10; }# #{ $counter = $counter + 1; $total = $total + 20; }# <p>Count: ##{$counter}#, Total: ##{$total}#</p> <!-- 2, 30 --> ``` ### **8.3.2 String Operations** ```html <!-- String concatenation --> #{ $firstName = "John"; $lastName = "Doe"; }# <p>Full Name: ##{$firstName . " " . $lastName}#</p> <!-- String functions --> #{ $text = "hello world"; }# <p>Original: ##{$text}#</p> <p>Uppercase: ##{strtoupper($text)}#</p> <p>Length: ##{strlen($text)}#</p> <p>Substring: ##{substr($text, 0, 5)}#</p> <!-- String interpolation (concatenation style) --> <p>Welcome ##{$firstName}# ##{$lastName}#!</p> ``` ### **8.3.3 Control Structures** **If/Elseif/Else Statements:** ```html #{ $a = 2; $b = 2; }# <div> #{if $a != 3 }# <div>if worked (a != 3)</div> #{elseif $b == 2 }# <div>elseif worked (b == 2)</div> #{else}# <div>else worked</div> #{endif}# </div> <!-- Complex conditions --> #{ $isLoggedIn = true; $userRole = 'admin'; }# <div> #{if $isLoggedIn && $userRole === 'admin' }# <p>Welcome Admin!</p> #{endif}# </div> <!-- Nested if statements --> #{ $x = 5; $y = 10; }# <div> #{if $x > 0 }# #{if $y > 5 }# <span>Both conditions true</span> #{endif}# #{endif}# </div> ``` **Ternary Operator:** ```html #{ $status = "active"; $points = 75; }# <p>Status: ##{($status == "active") ? "Online" : "Offline"}#</p> <p>Result: ##{($points > 50 && $status == "active") ? "Pass" : "Fail"}#</p> <!-- Nested ternary --> <p>##{true ? "A" : (false ? "B" : "C")}#</p> <!-- A --> <p>##{true ? (false ? "B" : "C") : "D"}#</p> <!-- C --> <!-- Complex nested ternary --> #{ $a = 1; $b = 2; $c = 3; $d = 4; $e = 6; $f = 6; }# <p>##{ $a > $b ? ($c < $d ? "X" : "Y") : ($e == $f ? "Z" : "W") }#</p> <!-- Z --> ``` ### **8.3.4 Function Calls** Expression tags support a limited set of PHP functions: ```html <!-- Date and time functions --> <p>Current Date: ##{date('Y-m-d')}#</p> <p>Formatted: ##{date('F j, Y, g:i a')}#</p> <p>Timestamp: ##{time()}#</p> <!-- String functions --> #{ $filename = "document.pdf"; }# <p>Extension: ##{pathinfo($filename, PATHINFO_EXTENSION)}#</p> <p>Basename: ##{basename($filename)}#</p> <!-- Math functions --> <p>Square root: ##{sqrt(16)}#</p> <p>Absolute: ##{abs(-5)}#</p> <p>Round: ##{round(3.14159, 2)}#</p> <!-- Array functions (when arrays are available) --> #{ $colors = ["red", "green", "blue"]; }# <p>Count: ##{count($colors)}#</p> <p>First: ##{$colors[0]}#</p> ``` ### **8.3.5 Comparison and Logical Operators** ```html #{ $price = 100; $quantity = 3; $inStock = true; $onSale = false; }# <!-- Comparison operators --> <p>##{$price > 50 ? "Expensive" : "Cheap"}#</p> <p>##{$quantity >= 1 ? "In cart" : "Empty"}#</p> <p>##{$price == 100 ? "Exactly 100" : "Not 100"}#</p> <p>##{$price != 50 ? "Not 50" : "Is 50"}#</p> <!-- Logical operators --> <p>##{$inStock && $quantity > 0 ? "Available" : "Unavailable"}#</p> <p>##{$inStock || $onSale ? "Can purchase" : "Cannot purchase"}#</p> <p>##{!$onSale ? "Regular price" : "On sale"}#</p> <!-- Combined conditions --> <p>##{ ($price < 200 && $inStock) || $onSale ? "Good deal" : "Consider carefully" }#</p> ``` ## **8.4 Variable Scope and Availability** Understanding what variables are available in expression tags is crucial. ### **8.4.1 Predefined Variables** These variables are always available in expression tags: ```html <!-- $parentapp - The current Application instance --> <p>Site: ##{$parentgate->siteName}#</p> <p>User: ##{$parentgate->currentUser->name}#</p> <!-- $frontobj - The current FrontFile object --> <p>Template: ##{$frontobj->getFilePath()}#</p> <!-- $sphp_settings - Framework settings --> <p>Base URL: ##{$sphp_settings->getBase_url()}#</p> <p>Version: ##{$sphp_settings->getVersion()}#</p> <!-- $metadata - Page metadata --> <p>Title: ##{$metadata->get('title')}#</p> <p>Description: ##{$metadata->get('description')}#</p> <!-- Direct Access as variable of $metadata property --> <p>Title: ##{$title}#</p> ``` ### **8.4.2 App-Provided Variables** Variables can be passed from Gate to FrontFile: **In App:** ```php public function page_new() { // Set variables for FrontFile $this->frtMain->addProp('pageTitle', 'Welcome Page'); $this->frtMain->addProp('userList', $this->getUsers()); $this->frtMain->addProp('currentTime', time()); // Also available as properties $this->pageTitle = 'Welcome Page'; $this->setFrontFile($this->frtMain); } ``` **In FrontFile:** ```html <h1>##{$pageTitle}#</h1> <p>Loaded at: ##{date('H:i:s', $currentTime)}#</p> ``` ### **8.4.3 Variable Inheritance Chain** Variables are resolved in this order: 1. **Local variables** (defined in same Front File) 2. **FrontFile properties** (set via `addProp()` or `$frontobj->var`) 3. **Gate properties** (set via `$this->var` in App) 4. **Predefined variables** (`$parentapp`, `$frontobj`, etc.) ```html <!-- Local variable takes precedence --> #{ $title = "Local Title"; }# <p>##{$title}#</p> <!-- "Local Title" --> <!-- Without local, uses FrontFile Metadata property --> <p>##{$pageTitle}#</p> <!-- From $frontobj->pageTitle --> <!-- Without either, uses Component Object --> <p>##{$txtname->getValue()}#</p> <!-- From $frontobj->getComponent('txtname') --> ``` ### **8.4.4 Scope Limitations** **Variables DO persist** within the same FrontFile: ```html #{ $counter = 0; }# <p>First: ##{$counter}#</p> <!-- 0 --> #{ $counter = $counter + 1; }# <p>Second: ##{$counter}#</p> <!-- 1 --> ``` **Variables DO NOT persist** across different FrontFiles or requests. **Variables CANNOT access:** ```html <!-- ❌ NO superglobals --> <p>##{$_GET['param']}#</p> <!-- Error --> <!-- ❌ NO loop access --> <p>##{for($c=0;$c<9;$c++>){}}#</p> <!-- Error --> <!-- ❌ NO arbitrary object creation --> <p>##{new DateTime()}#</p> <!-- Error --> ``` ## **8.5 Execution Timing and Order** Expression tags execute at specific times during FrontFile processing, which affects what data is available. ### **8.5.1 Three Execution Contexts** **Context 1: Fusion Attributes and code tag on-init="true" Parse time** ```html <!-- fui-*: Parse Phase --> <input id="txt1" type="text" runat="server" fui-setDefaultValue="##{getDefaultEmail()}#"> <!-- This code block runs First in Parse Phase --> <code on-init="true"> $counter=1 : ##{$counter=1}# </code> ``` **Context 2: Fusion Attributes and code tag on-endrender="true" Render time** ```html <!-- fur-*: Render Phase --> <input id="txt1" type="text" runat="server" fur-setValue="##{$currentUser->email}#"> <div id="showall" runat="server" path="uikit/data/Pagination.php" fun-setFieldNames="profile_name,permission_id" fun-setAJAX="" > <div>##{$showall->getRow('profile_name')}#</div> </div> <!-- This code block runs in Render Phase --> <code on-endrender="true"> $counter=4 : ##{$counter=$counter+1;$counter}# </code> ``` **Context 3: Normal HTML Content execute after render** (Lowest Priority) ```html <p>Welcome, ##{$userName}#!</p> <p>Today is ##{date('Y-m-d')}#</p> ``` - Executes **after all Components have rendered** - Cannot affect Component rendering - Good for final output composition ### **8.5.2 Practical Timing Example** ```html <!-- Example showing execution order with counter value --> <!-- This Expression Tag runs First in After render Phase --> <p>Outside: $counter=6 : ##{$counter=$counter+1;$counter}#</p> <!-- This code block runs First in Parse Phase --> <code on-init="true"> $counter=1 : ##{$counter=1}# </code> <br /> <!-- This code block runs in Render Phase --> <code on-endrender="true"> $counter=4 : ##{$counter=$counter+1;$counter}# </code> <br /> <!-- This fusion runs in Parse Phase --> <input id="txtField" type="text" runat="server" fui-setDefaultValue="$counter=2 : ##{$counter=$counter+1;$counter}#"> <!-- This code block runs First in Parse Phase --> <code on-init="true"> $counter=3 : ##{$counter=$counter+1;$counter}# </code> <br /> <!-- This Expression Tag runs in After render Phase --> $counter=7 : ##{$counter=$counter+1;$counter}# <!-- This fusion runs in Render Phase --> <div id="div1" runat="server" fur-_data-message="$counter=5 : ##{$counter=$counter+1;$counter}#"> <!-- This Expression Tag runs in After render Phase --> <p>Final: $counter=8 : ##{$counter=$counter+1;$counter}#</p> </div> <!-- This executes last (normal HTML) --> <!-- This Expression Tag runs in After render Phase and at last from Top to Down Approach --> <p>Outside: $counter=9 : ##{$counter=$counter+1;$counter}#</p> ``` **Expected output:** - `code` Top code bloack first evaluate and create,set and print $counter value: "1" (Parse Phase) - `div` data-message: "5" (Render Phase) - "Final: 8" (after render) - "Outside: 9" (normal HTML) ### **8.5.3 The Rule of Thumb** > **Expression tags in normal HTML execute AFTER everything else.** > > If you need to affect Component rendering, use Fusion attributes (`fur-*`). > If you need early execution, use `fui-*` or do it in the App. > if you need execution in sequence of Components use code block with specific event bind ## **8.6 Advanced Patterns and Techniques** ### **8.6.1 Template Loops (Simulated)** While expression tags don't support `for` or `foreach` loops directly, you can simulate them: **Method 1: Using App-prepared data:** ```html <!-- In Gate --> public function loopgen() { $items = ['Apple', 'Banana', 'Cherry']; $strout = ""; foreach($items as $i=>$item){ $strout .= '<li>'. $item . '</li>'; } return $strout; } <!-- In FrontFile --> <ul> ##{raw:$parentgate->loopgen()}# </ul> ``` **Method 2: Using Component for loops:** ```html <!-- use render phase and save useless processing of server --> <code on-endrender="true"> #{$items = ['Apple', 'Banana', 'Cherry']}# </code> <!-- Using ForLoop Component --> <div id="loop1" runat="server" path="slibpath/comp/server/ForLoop.php" fun-setLoopTo="3"> <p>Item ##{$items[$loop1->counter]}#</p> </div> ``` ### **8.6.2 Complex Condition Styling** ```html <!-- code block make sure that variables create before use by component --> <code on-endrender="true"> #{ $userStatus = 'active'; $unreadCount = 5; $isAdmin = true; }# </code> <div id="div1" runat="server" class="user-badge" fur-_class="badge ##{$userStatus == 'active' ? 'badge-success' : 'badge-secondary'}# ##{$unreadCount > 0 ? 'has-notifications' : ''}# ##{$isAdmin ? 'admin-badge' : ''}#"> <span class="username">##{$username}#</span> #{if $unreadCount > 0 }# <span class="notification-count"> ##{$unreadCount}# </span> #{endif}# #{if $isAdmin }# <span class="admin-icon" title="Administrator">⚙️</span> #{endif}# </div> ``` ### **8.6.3 Dynamic Attribute Generation** ```html <!-- Generate dynamic HTML attributes --> <code on-endrender="true"> #{ $buttonId = "btnSubmit"; $buttonClass = "btn-primary"; $isDisabled = false; $dataAttrs = [ 'user-id' => 123, 'action' => 'submit', 'confirm' => 'true' ]; $str2 = ''; }# </code> <!-- foreach just name of object|array in front file with fun-setObject="dataAttrs" and it will automatically read variable and loop it --> <div id="loop1" runat="server" path="slibpath/comp/server/ForEachLoop.php" fun-setObject="dataAttrs"> ##{$str2 = $str2 . ' ' . $loop1->key . ' = "' . $loop1->item . '"'}# <br/> </div> <!-- SartajPHP need valid attribute format like name=value pair so change < and > character to compose html tag in expression tags otherwise get error --> #{$str1 = '<button id="' . $buttonId . '" class="btn ' . $buttonClass . '" >'}# #{$str1 = $str1 . ' Submit Form</button>'}# ##{raw:$str1}# ``` ## **8.7 Performance Optimization** ### **8.7.1 Minimize Expression Complexity** ```html <!-- ❌ INEFFICIENT: Complex calculation in template --> <p>##{ // This recalculates every time $total = 0; foreach ($items as $item) { $total += $item->price * $item->quantity; } $total = $total * (1 - $discount); formatCurrency($total); }#</p> <!-- ✅ EFFICIENT: Pre-calculate in Gate --> <p>##{formatCurrency($precalculatedTotal)}#</p> <!-- In App: --> public function page_new() { $total = $this->calculateOrderTotal($items); $this->frtMain->addProp('precalculatedTotal', $total); } ``` ## **8.8 Security Best Practices** ### **8.8.1 Always Escape Output** ```html <!-- ✅ SAFE: Auto-escaped (default) --> <div>##{$userComment}#</div> <!-- ✅ EXPLICIT: Manual escaping --> <div>##{htmlspecialchars($userComment)}#</div> <!-- ❌ CAREFUL: Raw output only for trusted content --> <div>##{raw:$adminGeneratedHtml}#</div> ``` ### **8.8.2 Validate Before Use** ```html <!-- Check data before using --> #{if isset($userInput) && is_string($userInput) }# <p>Input: ##{$userInput}#</p> #{else}# <p>No valid input provided</p> #{endif}# <!-- Sanitize numbers --> #{ $userId = (int)$inputUserId; }# <p>User ID: ##{$userId}#</p> ``` ## **8.9 Debugging Expression Tags** ### **8.9.1 Enable Debug Output** ```html <!-- Add debug attributes to see expression results --> <div data-debug="true" data-expression="##{$variableName}#"> <!-- Content --> </div> <!-- Debug multiple variables --> <template-debug> Variable: ##{$var}# Type: ##{gettype($var)}# Is Set: ##{isset($var) ? 'Yes' : 'No'}# Is Empty: ##{empty($var) ? 'Yes' : 'No'}# </template-debug> ``` ### **8.9.2 Common Errors and Solutions** **Error: "Undefined variable"** ```html <!-- ❌ ERROR: Variable not defined --> <p>##{$undefinedVar}#</p> <!-- Error --> <!-- ✅ SOLUTION: Check existence first --> #{if isset($undefinedVar) }# <p>##{$undefinedVar}#</p> #{else}# <p>Variable not available</p> #{endif}# ``` **Error: "Function not allowed"** ```html <!-- ❌ ERROR: Function not in allowed list --> <p>##{exec('ls')}#</p> <!-- Error --> <!-- ✅ SOLUTION: Use allowed functions or Gate methods --> <p>##{date('Y-m-d')}#</p> <!-- Allowed --> <p>##{$parentgate->safeFunction()}#</p> <!-- From Gate --> ``` **Error: "Syntax error in expression"** ```html <!-- ❌ ERROR: Invalid syntax --> <p>##{ if true { echo "yes"; } }#</p> <!-- Error --> <!-- ✅ SOLUTION: Use correct expression syntax --> <p>##{true ? "yes" : "no"}#</p> <!-- Ternary --> #{if true }# <p>yes</p> #{endif}# ``` ### **8.9.3 Development Tools** Add debugging helpers to your App: ```php // In Gate base class or helper public function debugExpression($expression, $label = '') { if ($this->debug->debugmode > 1) { $result = eval("return $expression;"); error_log("Expression Debug [$label]: $expression = " . print_r($result, true)); return $result; } return null; } ``` **Usage:** ```html <!-- In FrontFile during development --> #{ $debugResult = $parentgate->debugExpression('2+2', 'test'); }# <p>Debug: ##{$debugResult}#</p> ``` ## **8.10 Real-World Examples** ### **8.10.1 E-commerce Product Display** ```html <!-- Product display with dynamic pricing --> #{ $product = $parentgate->currentProduct; $user = $parentgate->currentUser; $inCart = $parentgate->isInCart($product->id); $inStock = $product->stock > 0; $onSale = $product->sale_price < $product->regular_price; $discountPercent = $onSale ? round((1 - $product->sale_price / $product->regular_price) * 100) : 0; }# <div class="product-card" data-product-id="##{$product->id}#" fur-_class="card ##{$inStock ? '' : 'out-of-stock'}##"> <!-- Sale badge --> #{if $onSale }# <div class="sale-badge"> Save ##{$discountPercent}#% </div> #{endif}# <!-- Product image --> <img src="##{$product->image_url}#" alt="##{htmlspecialchars($product->name)}#" class="card-img-top"> <!-- Product info --> <div class="card-body"> <h5 class="card-title">##{$product->name}#</h5> <!-- Price display --> <div class="product-price"> #{if $onSale }# <span class="regular-price text-muted"> <s>$##{number_format($product->regular_price, 2)}#</s> </span> <span class="sale-price text-danger"> $##{number_format($product->sale_price, 2)}# </span> #{else}# <span class="price"> $##{number_format($product->regular_price, 2)}# </span> #{endif}# </div> <!-- Stock status --> <div class="stock-status"> #{if $inStock }# <span class="in-stock text-success"> In Stock (##{$product->stock}# available) </span> #{else}# <span class="out-of-stock text-danger"> Out of Stock </span> #{endif}# </div> <!-- Add to cart button --> <div class="add-to-cart"> #{if $inStock }# <button class="btn ##{$inCart ? 'btn-secondary' : 'btn-primary'}#" ##{$inCart ? 'disabled' : ''}# onclick="addToCart(##{$product->id}#)"> ##{$inCart ? 'In Cart' : 'Add to Cart'}# </button> #{else}# <button class="btn btn-outline-secondary" disabled> Notify When Available </button> #{endif}# </div> <!-- Quick stats --> <div class="product-stats mt-2"> <small class="text-muted"> ⭐ ##{number_format($product->rating, 1)}# (##{$product->review_count}# reviews) | 🔥 ##{$product->sold_count}# sold </small> </div> </div> </div> ``` ## **8.11 Chapter Summary** Expression tags provide a powerful yet safe way to add dynamic logic to SartajPHP FrontFiles: 1. **Two Tag Types:** - `##{ }#` - Output tags (display results) - `#{ }#` - Silent tags (execute without output) 2. **Supported Syntax:** - Variable assignment and arithmetic - String operations and concatenation - If/elseif/else conditional statements - Ternary operators (including nested) - Limited function calls (safe functions only) - Comparison and logical operators 3. **Key Limitations (for safety):** - No function or class definitions - No access to superglobals (`$_GET`, `$_POST`, etc.) - No arbitrary object creation - Limited function whitelist 4. **Execution Timing:** - Normal HTML: After all Components render - Fusion attributes: Depends on prefix (`fui-*`, `fur-*`, `fun-*`) - Cannot affect Component rendering from normal HTML expressions 5. **Best Practices:** - Keep expressions simple; complex logic belongs in App - Always escape output (default behavior) - Pre-calculate expensive operations in App - Use Fusion attributes when you need to affect Components - Validate data before using in expressions Expression tags strike the perfect balance between template flexibility and application security. They provide enough power for sophisticated presentation logic while preventing the common security pitfalls of allowing arbitrary PHP in templates. In the next chapter, we'll explore Multi-Application Architecture—how to build complex systems by combining multiple focused applications within a single SartajPHP project. ---