Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Latte by Example

Hi! 👋

I spent three years writing Twig before I met Latte. Two things made me switch, and they are the two things this course is built around.

The first one I felt every single day. In Twig, string concatenation is ~. In PHP it is .. I never once managed to keep that straight, and not because it is hard - because I had spent the morning in PHP, where it is ., and my fingers had opinions. Same with {% set x = 1 %} versus $x = 1, with {{ user.name }} that might be a property or a getter or an array key (Twig decides at runtime, you find out later), with filter names that almost match the PHP functions but not quite. Every one of those is a tiny context switch. Individually trivial, a hundred times a day, in a language you are not writing in the other window.

Latte does not have a language. Inside the braces you write PHP - $user->name, $a . $b, ??, match, arrow functions, named arguments. Nothing to look up, nothing to switch to. I was productive in an afternoon, and I have never since typed the wrong concatenation operator.

The second one took longer to appreciate, and matters more. Every engine escapes by default these days - Twig and Blade included - and every one of them calls htmlspecialchars() and considers the job done. But escaping is not one job. A value in HTML text, in an unquoted attribute, inside <script>, and in a href need four different treatments, and one function cannot be right in all four. Naive auto-escaping is not safety; it is the feeling of safety, which is worse.

Latte parses the HTML. It knows which of those four places your value is landing in and escapes it accordingly, every time, without being asked. It is the first and still the only PHP template engine that does this.

Do not take my word for it - take the XSS quiz: nine snippets, and the question is which ones you would have escaped correctly by hand. I got six, after years of writing PHP for a living. The three I missed were not exotic.

So: small programs, real output, one idea at a time. Let's go.

Requirements

PHP 8.4 or newer.

Installation

git clone https://github.com/nette-examples/latte-by-example
cd latte
composer install

How to use this course

Run the first chapter:

php 01-hello-world/example.php

It prints HTML straight to your terminal, so you can read it immediately (or pipe it into a file and open it in a browser - your call). Then open that chapter's readme.md, which walks you through what just happened, and finish with Try it yourself. Those exercises are the part that actually sticks; everything before them is me talking.

Chapters build on each other, so go in order. I promise never to use something in the code that I have not explained yet.

Want to poke at Latte without cloning anything? fiddle.nette.org runs it in the browser.

Chapters

# Chapter What it covers Level
01 Hello World The engine, the cache directory, {$var} - and why not to just write <?= $x ?> Beginner
02 Expressions and Filters PHP expressions in tags, {var}, {default}, filters, {=…}, nullsafe ?| Beginner
03 Conditions {if}, the in operator, the short ternary, and keeping the output clean Beginner
04 Loops {foreach}, $iterator, {sep}, {first}, {last}, {skipIf} Beginner
05 n:attributes Tags as HTML attributes, n:class, n:tag-if, n:ifcontent Beginner
06 Context-Aware Escaping One hostile reviewer, six contexts, six defences - and printing HTML you trust Intermediate
07 Smart HTML Attributes null drops an attribute, boolean flags, arrays in class/style, JSON in data- Intermediate
08 Including Templates {include}, passing variables to a partial, and what a partial should own Intermediate
09 Layouts and Blocks {layout}, {block} with defaults, {include parent} Intermediate
10 Definitions and Horizontal Reuse {define} with parameters, {import}, and which reuse tool to pick Intermediate
11 Embedding Components {embed}: a layout for a piece of a page, used three times on one page Intermediate
12 The Type System Parameters as a class, {templateType}, {varType}, and why tools care Intermediate
13 Custom Filters and Functions addFilter(), addFunction(), and which one a piece of logic should be Advanced
14 Your Own Extension and Tag Latte\Extension, a custom {alert} tag, and the reference rule in node classes Advanced
15 Loaders Templates from strings or a database, and how a loader drives the cache Advanced
16 The Sandbox Rendering templates you did not write, and the policy that keeps them polite Expert
17 Development and Production What to switch on where, the linter, and debugging with Tracy Practical

That is the whole course. If you work through it in order you will have met every part of Latte I use day to day.

What this course does not cover

Three things you will meet in the wild and will not find here, so you know they exist and where to look.

More tags and filters than fit in a course. Latte ships with dozens of tags and around fifty filters. You have met the ones that carry most templates; the rest are in the tag overview and the filter overview, both of which are single pages worth skimming once so you remember what is available. A few I use regularly and never found room for: {capture} to collect output into a variable, {spaceless}, {ifset}, {try} for a fragment that may fail, and {iterateWhile} for grouped listings.

Translations. TranslatorExtension adds {_'text'} and {translate}, and can translate static strings at compile time so each language gets its own compiled template. If your site is multilingual, start here.

Everything Latte gains inside Nette. Used with the framework, a whole layer of tags appears that this course never shows, because they come from other packages: n:href and {link} for URLs, {control} for components, {snippet} for AJAX, {form}, {label}, {input} and n:name for forms, {cache} for caching a fragment, {asset} for versioned assets. If you open a Nette project and meet n:href, it is not something you missed - those tags come from Nette itself, and the tag overview lists them with links to the package that documents each one.

Checking your own templates

Latte comes with a linter that catches syntax errors and references to tags or filters that do not exist. Point it at your own project, it is the cheapest CI step you will ever add:

composer lint-templates

This repository also checks itself - composer check runs the linter, static analysis, and a script verifying that the output printed in each chapter still matches what the example produces.

Further reading

Happy templating!

About

Latte Examples

Resources

Stars

6 stars

Watchers

3 watching

Forks

Used by

Contributors

Languages