Rewriting

Node Builders

Node builders are utility factories to help create new Blade constructs in your rewriters. Their main purpose is to reduce the amount of manual string concatenation you need to perform.

#Element Builder

Use the element builder to construct HTML elements with attributes, children, and various closing styles.

The following example creates a div with an id and a class:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->id('myDiv')
7 ->addClass('mt-4');

produces:

1<div id="myDiv" class="mt-4"></div>

You may also specify that the element should be either self-closing or a void element:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// <myElement />
6echo Builder::element('myElement')
7 ->selfClosing();
8
9// <myElement>
10echo Builder::element('myElement')
11 ->void();

#Attributes

Use attr to set a standard key-value attribute:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->attr('data-role', 'container');

outputs:

1<div data-role="container"></div>

For boolean attributes (no value), use boolAttr:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->boolAttr('hidden');

renders as:

1<div hidden></div>

Blade dynamic attributes (:name="expr" syntax) are created with bladeAttr:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->bladeAttr('class', '$classes');

produces:

1<div :class="$classes"></div>

When an element needs multiple attributes that share the same stripped name (e.g., both a static class and a bound :class), use appendAttr to add attributes without deduplication. Unlike attr, which overwrites any existing attribute with the same name, appendAttr always appends:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->attr('class', 'container')
7 ->appendAttr(':class', '$dynamicClasses');

produces:

1<div class="container" :class="$dynamicClasses"></div>

Shorthand methods id and class set those attributes directly. Use addClass to append to existing classes rather than replacing them:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->class('container mx-auto')
7 ->addClass('p-4');

outputs:

1<div class="container mx-auto p-4"></div>

#Populating Children

Use children to set the element's child nodes. You may pass any combination of builders and raw strings:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('ul')
6 ->children(
7 Builder::element('li')->text('First'),
8 Builder::element('li')->text('Second'),
9 );

renders as:

1<ul><li>First</li><li>Second</li></ul>

For a single text child, use the text shorthand:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('p')
6 ->text('Hello, world!');

produces <p>Hello, world!</p>.

To add children after existing ones, use append:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::element('div')
6 ->text('Hello')
7 ->append(Builder::element('span')->text(' world'));

outputs:

1<div>Hello<span> world</span></div>

#Directive Builder

Use the directive builder to create Blade directive nodes like @include, @if, or @csrf:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// @include('partials.header')
6echo Builder::directive('include', "('partials.header')");
7
8// @if($show)
9echo Builder::directive('if', '($show)');
10
11// @csrf
12echo Builder::directive('csrf');

These produce @include('partials.header'), @if($show), and @csrf respectively.

When inserting a directive adjacent to other content, safeDirective ensures proper spacing:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::safeDirective('if', '($condition)');

To create a modified copy of an existing DirectiveNode:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5$modified = Builder::directiveFrom($existingDirective, '($newArgs)');

#Text Builder

Create a plain text node with Builder::text:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::text('Hello, world!');

This produces the literal text Hello, world!.

#Echo/Interpolation Builders

Blade interpolation nodes come in three variants (escaped, raw, and triple). Each has a dedicated builder:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// {{ $name }}
6echo Builder::echo('$name');
7
8// {!! $html !!}
9echo Builder::rawEcho('$html');
10
11// {{{ $value }}}
12echo Builder::tripleEcho('$value');

#PHP Builders

Create raw PHP tag nodes for <?php ?> and <?= ?> syntax:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// <?php echo "hello"; ...
6echo Builder::phpTag('echo "hello";');
7
8// <?=$variable ...
9echo Builder::phpEchoTag('$variable');

These produce <?php echo "hello"; ?> and <?=$variable ?> respectively.

Both methods accept an optional second argument to omit the closing ?> tag:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// <?php echo "hello";
6echo Builder::phpTag('echo "hello";', hasClose: false);

#Comment Builders

Build HTML or Blade comments:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// <!-- This is a comment -->
6echo Builder::comment('This is a comment');
7
8// {{-- TODO: fix this --}}
9echo Builder::bladeComment('TODO: fix this');

#Raw Text Builders

When you need to insert arbitrary source text without any transformation, use raw:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5echo Builder::raw('<custom-element attr="val">content</custom-element>');

outputs:

1<custom-element attr="val">content</custom-element>

When mixing strings and builders, normalize converts strings to RawBuilder instances while passing builders through unchanged. Use normalizeAll for arrays:

1<?php
2
3use Forte\Rewriting\Builders\Builder;
4
5// RawBuilder
6$node = Builder::normalize('some text');
7
8// TextBuilder (unchanged)
9$node = Builder::normalize(Builder::text('hi'));
10
11// array<NodeBuilder>
12$nodes = Builder::normalizeAll(['some text', Builder::text('hi')]);

#See also

  • Rewriters: Use builders to create nodes during rewriting
  • Traversal: Navigate and query the document tree
  • Documents: Parse templates and access the document API