-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Object-Oriented PHP
-
Section 5: Working with Data
-
Section 6: Modern PHP (PHP 8)
-
Section 7: Working with Files and Networking
-
Section 8: Common PHP Frameworks Overview
-
Section 9: Tooling and Ecosystem
-
Section 10: Practical Projects
-
Section 11: Interview Practice
-
Section 12: More Standard Library
-
Section 13: Data Structures and Algorithms in PHP
-
Section 14: More Practice Exercises
-
Section 15: More Security and Best Practices
-
Section 16: More Testing and Tooling
-
Section 17: WordPress-Style CMS Concepts
-
Section 18: Advanced OOP Practice
-
Section 19: More Web Fundamentals
-
Section 20: Database Practice
-
Section 21: PHP Manual: Array Functions
-
Section 22: PHP Manual: Date and Calendar Functions
-
Section 23: PHP Manual: Filesystem and Directory Functions
-
Section 24: PHP Manual: Filter and Var Handling
-
Section 25: PHP Manual: Math Functions
-
Section 26: PHP Manual: JSON and XML
-
Section 27: PHP Manual: Network and Stream Functions
-
Section 28: PHP Manual: Error and Exception Handling
-
Section 29: PHP Manual: Output Control and Misc
-
Section 30: PHP Manual: FTP, Zip, and Mail
-
Section 31: Modern PHP Frameworks Deep Dive
-
Section 32: PHP Design Patterns
-
Section 33: More Practice Exercises
-
Section 34: PHP Performance and Deployment
-
Section 35: More Interview Practice
-
Section 36: More PHP Standard Library
-
Section 37: PHP Concurrency and Async
-
Section 38: More Web Development Practice
-
Section 39: PHP Testing Deep Dive
-
Section 40: Composer and Package Development
-
Section 41: PHP Security Deep Dive
-
Section 42: More Practical Projects
-
Section 43: Legacy PHP Maintenance
-
Section 44: More Algorithm Practice
-
Section 45: Final Practice and Review
-
Section 46: PHP for E-Commerce Patterns
-
Section 47: PHP API Design Deep Dive
-
Section 48: PHP Caching Strategies
-
Section 49: PHP Queue and Background Jobs
-
Section 50: PHP Multi-Tenancy Patterns
-
Section 51: PHP Real-Time Features
-
Section 52: PHP CMS and Content Modeling
-
Section 53: PHP Internationalization
-
Section 54: More Framework-Specific Practice
-
Section 55: PHP Legacy Code Refactoring
-
Section 56: More Practice Projects Round 2
-
Section 57: PHP Command-Line Applications
-
Section 58: PHP and Microservices
-
Section 59: More Interview and Review Round 2
140: Practice Exercise: Building a Simple Templating Engine
Before we dive into the code, I want to address a hurdle I see almost every junior dev hit when they start thinking about templating. Most people assume that building a "templating engine" is just a fancy way of saying "I'm going to use include 'header.php'; and include 'footer.php';."
It's Just a Fancy Wrapper for include()
If you're just including files, you aren't using an engine; you're just organizing your files. The problem with the include approach is that it allows any PHP code to run inside your template. While that sounds powerful, it's a nightmare for maintenance. If your template file contains a complex SQL query or a loop that crashes the page, your presentation layer is now tightly coupled to your business logic. You've basically just moved the mess from one file to another.
A real templating engine treats the template as a string or a resource to be parsed, not as a script to be executed. The engine acts as a gatekeeper, deciding exactly what data gets passed in and how it's displayed, without letting the template "reach out" and touch the database itself.
Decoupling Data from Presentation with Token Replacement
The core of a simple engine is the "token." Instead of writing <?php echo $username; ?>, we use a placeholder that the engine recognizes—something like {{ username }}. This makes the template readable for designers who might not know a lick of PHP.
I usually start with a basic replacement loop. Here is the logic: we load the template file into a string, look for our tokens, and swap them out for values from an associative array. It's surprisingly simple when you strip away the complexity of frameworks like Twig or Blade.
class SimpleEngine {
public function render($templateFile, $data) {
$content = file_get_contents($templateFile);
foreach ($data as $key => $value) {
// We look for {{ key }} and replace it with the value
$content = str_replace('{{ ' . $key . ' }}', $value, $content);
}
return $content;
}
}
I'll be honest: str_replace is fine for a tiny project, but it's blunt. If you have a template with 50 variables, you're running 50 string searches. In a production environment, we'd use regular expressions or a compiled cache, but for our purposes, this proves the concept: the template is data, and the engine is the processor.
Adding Safety and Flexibility to Your Parser
There's a glaring security hole in the code above: XSS (Cross-Site Scripting). If $value contains a <script> tag from a user's profile, your engine will happily render it, and your site will be hacked. A professional engineer never trusts the data being injected into a template.
We need to wrap our values in htmlspecialchars(). I also recommend adding a way to handle "missing" tokens so your page doesn't just show {{ missing_var }} to the end user, which looks broken and unprofessional.
foreach ($data as $key => $value) {
$safeValue = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
$content = str_replace('{{ ' . $key . ' }}', $safeValue, $content);
}
Now, we've moved from "just including files" to a system that manages data flow, ensures security, and maintains a strict boundary between how the app works and how it looks. That is the essence of a templating engine.
📋 Practical Task
The Mini-Template Engine: User Profile Generator
Your task is to build a functional TemplateEngine class that can dynamically render a user profile page. You need to ensure that the engine is secure and can handle multiple variables.
- Create a file named
profile.html. Inside it, use placeholders like{{ name }},{{ bio }}, and{{ location }}. - Implement a
TemplateEngineclass with arender($filePath, $data)` method. - The
rendermethod must:- Read the content of the
profile.htmlfile. - Iterate through the
$dataarray and replace the corresponding placeholders. - Use
htmlspecialchars()on all values to prevent XSS attacks. - Return the final string.
- Read the content of the
- Test your engine by passing an associative array containing a name, a bio with some HTML tags (to test the escaping), and a location.
Example Test Case:
$data = [
'name' => 'Jane Doe',
'bio' => 'I love PHP and <script>alert("hack")</script>!',
'location' => 'New York'
];
$engine = new TemplateEngine();
echo $engine->render('profile.html', $data);
// The output should show the bio text literally, not execute the script or render the bold tag.
There are no comments for now.