Introduction
Getting Started
Forte is a Blade parser and AST manipulation library. To get started using Forte, install it with Composer:
composer require fortephp/forte
Forte does not require additional configuration. To extend Blade without writing a parser extension or rewriter, use Enclaves. Enclaves apply built-in or community-provided transformations to selected templates.
#Parsing Your First Template
You can parse a Blade template by calling Forte::parse with the template string:
<?php
use Forte\Facades\Forte;
$document = Forte::parse('Hello, {{ $name }}');
You will receive an instance of Forte\Ast\Document\Document, which gives you a single entry point for querying, traversing, rewriting, and rendering templates.
#Inspecting and Rendering
The fastest way to understand Forte is to parse a template and render it back out. Unmodified documents preserve the original source exactly:
<?php
use Forte\Facades\Forte;
$template = <<<'BLADE'
<div class="container">
{{-- A comment --}}
@if ($show)
<p>Hello, {{ $name }}!</p>
@endif
</div>
BLADE;
$doc = Forte::parse($template);
$doc->render() === $template; // true
From there, you can inspect nodes, run XPath queries, or apply rewrites. Start with node identity and positions before moving into queries and transformations.
#The Parse Pipeline
Parsing happens in three phases, each feeding into the next.
#Lexer
The lexer scans source into a flat token stream. Specialized scanners recognize HTML elements, Blade directives, echoes, comments, PHP blocks, and raw PHP tags. Each token records its type and source offsets.
#Tree Builder
The tree builder assembles the token stream into Node objects. It pairs tags,
matches directive blocks such as @if...@endif, resolves component slots, and
nests children under their parents. When possible, malformed input becomes a
partial tree with diagnostics on the document.
#Document
The resulting tree is wrapped in a Document instance. The document is the public entry point for everything else, including querying, iterating, rewriting, and rendering.
#Node Indices
Every node in the tree gets a numeric index via $node->index(). This is the node's position in the document's internal flat array. Indices are stable within a single document instance but will change after rewriting.
#Immutability
Documents are immutable. All mutation methods, such as apply, rewrite, rewriteWith, return a new Document. The original is never modified.
<?php
use Forte\Facades\Forte;
use Forte\Rewriting\NodePath;
$original = Forte::parse('<div class="old">Hello</div>');
$modified = $original->rewriteWith(function (NodePath $path) {
if ($path->isTag('div')) {
$path->addClass('new');
}
});
$original->render(); // '<div class="old">Hello</div>'
$modified->render(); // '<div class="old new">Hello</div>'
The $original document is unchanged after the rewrite. This makes it safe to hold references to earlier versions while building transformation chains.
#Rewriting
Mutation works through a visitor-based system:
- One or more visitors walk the tree, inspecting nodes and queuing operations (replace, remove, wrap, insert, etc.) through the
NodePathAPI. - Operations are committed as a batch, producing a new
Document. - Multiple rewriters can be composed into a
RewritePipeline, where each rewriter operates on the document produced by the previous one.
Because operations are batched, Forte avoids creating excessive intermediate documents when a rewriter touches many nodes.
#XPath
Forte supports XPath querying by converting the AST into a DOM tree:
- The
DomMapperwalks the AST and builds aDOMDocumentwhere each Blade construct is represented as a namespaced element (e.g.,forte:if,forte:echo). - Standard
DOMXPathevaluates the query expression against this DOM. - Results are mapped back to AST nodes using
data-forte-idxattributes that reference each node's index.
This means you can use familiar XPath 1.0 syntax to search Blade templates without manually traversing the tree.
#Extensions
The extension system hooks into the parse pipeline at multiple points:
- Extensions register trigger characters with the lexer (e.g.,
#for a hashtag extension). - When the lexer encounters a trigger character, it invokes the extension's tokenizer, which may emit custom tokens.
- The tree builder consults registered tree extensions to convert custom tokens into custom node kinds.
- Custom nodes participate in DOM mapping, so they are queryable with XPath just like built-in nodes.
Extensions are registered through ParserOptions and managed by an ExtensionRegistry that handles dependency resolution and conflict detection.
#See Also
Continue with these related Forte guides:
- Documents: Full API for working with parsed documents
- Basic Nodes: Learn about the node types in the AST
- Rewriters: The visitor pattern and NodePath API
- Enclaves: Extend Blade with isolated compilation environments
- Parser Extensions: Teach the parser new syntax