Search by

lagdo / html-builder

lagdo

A full-featured HTML builder with a fluent api.

Package info

github.com/lagdo/html-builder

pkg:composer/lagdo/html-builder

Statistics

Installs: 20

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v1.4.1 2026-09-22 05:44 UTC

This package is auto-updated.

Last update: 2026-09-22 11:35:54 UTC


README

Build Status Scrutinizer Code Quality StyleCI

Latest Stable Version License

A full-featured HTML builder with a fluent api

This package provides an alternative to template engines for building complex HTML UIs in PHP.

The application UI becomes a library of PHP classes rather than a collection of templates written in a different language and tied to a specific template engine. Thanks to its dynamic HTML content and extensibility features, the library provides the full capabilities of modern template engines.

Installation

Install with Composer:

composer require lagdo/html-builder

Create a tag

A tag is created by calling the function with the same name on the HTML Builder. The HTML tree is built by passing the children tags as parameters to their parent.

$builder = new HtmlBuilder();

return $builder->build(
    $builder->div(
        $builder->html('Hello '),
        $builder->b(
            $builder->text('World')
        ),
        $builder->comment('Salutations')
    )
);

The output is:

<div>Hello&nbsp;<b>World</b><!--Salutations--></div>

Note: html(), text() and comment() are utility functions that output different types of contents.

Set an attribute

The attributes are set on HTML tags using the function named set followed by the attribute name in pascal case. The attribute name will be ouput in kebab case.

$builder = new HtmlBuilder();

return $builder->build(
    $builder->div($builder->text('Content'))
        ->setId('div-id')
        ->setClass('div-class')
        ->setDataKey('div-key')
);

The output is:

<div id="div-id" class="div-class" data-key="div-key">Content</div>

The when() method can be used to set an attribute only if a condition is met.

return $builder->build(
    $builder->div($builder->text('Content'))
        ->when($important, fn($component) => $component->addClass('important'))
);

The with() method calls the provided closure with the component as parameter. In the following example, the formatParagraph() will receive the div component as parameter.

function formatParagraph($component)
{
    $component->setClass('paragraph');
}

return $builder->build(
    $builder->div($builder->text('Content'))
        ->with(formatParagraph(...))
);

Dynamic HTML content

When building an application UI, the HTML content generally depends on the application data. Five functions are provided for dynamic HTML content generation.

The when() function generates the content only if the provided condition is true. The HTML content is generated by the provided closure.

return $builder->build(
    $builder->div(
        $builder->text('Welcome'),
        $builder->when($user !== null, fn() => $builder->html("&nbsp;{$user->name}"))
    )
);

The pick() function takes multiple conditions as input and returns the HTML content from the first which is true. Each condition is defined with when().

return $builder->build(
    $builder->div(
        $builder->pick(
            $builder->when($user === null, fn() => $builder->text('Welcome')),
            $builder->when($user->isAdmin, fn() => $builder->html("Welcome&nbsp;<b>{$user->name}</b>")),
            $builder->when(true, fn() => $builder->html("Welcome&nbsp;{$user->name}"))
        )
    )
);

The each() function generates the same content for each item in the provided array, iterator or generator. The HTML content is generated by the provided closure.

return $builder->build(
    $builder->ul(
        $builder->each($menuItems, fn($menuItem) => $builder->li($menuItem->title))
    )
);

The loop() function is the same as each(), but with more information provided to the closure. The second parameter is an instance of the LoopItem class, with the following public attributes.

  • index: the current loop index, starting from 0.
  • key: the current item key.
  • current: the current item value.
  • prevKey: the previous item key.
  • prev: the previous item value.
  • nextKey: the next item key.
  • next: the next item value.
  • isFirst: true when the current item is the first.
  • isLast: true when the current item is the last.
return $builder->build(
    $builder->ul(
        $builder->loop(
            $menuItems,
            fn($menuItem, $loop) => $builder->li($menuItem->title)
                ->setClass($loop->cycle('item-odd', 'item-even'))
                ->when(
                    $loop->changed(fn($item) => $item->group),
                    fn($menuComponent) => $menuComponent->setClass('item-first')
                )
        )
    )
);

The list() function simply returns the contents generated by its children. It is useful for example when a function needs to return a list of tags, without a wrapper.

return $builder->build(
    $builder->ul(
        $builder->each($menuItems, fn($menuItem) =>
            $builder->list(
                $builder->li($menuItem->title),
                $builder->comment($menuItem->group)
            )
        )
    )
);

Extending the builder

The HTML Builder can be extended with custom functions.

    public function registerBuilderHelper(string $prefix, Closure $helper): void;
    public function registerElementHelper(string $prefix, Closure $helper): void;
    public function registerComponentHelper(string $prefix, Closure $helper): void;

An extension is defined either for the builder itself, or for the HtmlComponent or HtmlElement classes.

The provided closure will be called anytime a method with the defined prefix is called. The closures are defined as follow:

use Lagdo\HtmlBuilder\Element\Element;
use Lagdo\HtmlBuilder\HtmlComponent;
use Lagdo\HtmlBuilder\HtmlElement;
use LogicException

/**
  * @throws LogicException
  */
function builderHelper(string $tagName, string $method, array $arguments): Element
{
    // Create and return a component
}

/**
  * @throws LogicException
  */
function elementHelper(HtmlElement $element, string $tagName, string $method, array $arguments): HtmlElement
{
    // Customize and return the $element object.
}

/**
  * @throws LogicException
  */
function componentHelper(HtmlComponent $component, string $tagName, string $method, array $arguments): HtmlComponent
{
    // Customize and return the $component object.
}

In the above functions, $method and $arguments are the name and parameters in the extension method call, $tagName is the method name without the prefix and converted to kebab case, and $element and $component are the items on which the extension is called.

For example, the Jaxon extension for the UI Builder defines the following helper.

$builder->registerBuilderHelper('jxn', builderHelper(...));

A call to $builder->jxnHtml($className) will actually call builderHelper('html', 'jxnHtml', [$className]).

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE.txt for more information.