PHPackages                             nixn/hiccup - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. nixn/hiccup

ActiveLibrary[Templating &amp; Views](/categories/templating)

nixn/hiccup
===========

An HTML templating engine, based on PHP code (strings, arrays, classes and inheritance). It is a (sophisticated) port of \[Hiccup for Clojure\](https://github.com/weavejester/hiccup).

v0.8(1y ago)06MITPHPPHP ^8.2

Since Jan 18Pushed 1y ago1 watchersCompare

[ Source](https://github.com/nixn/hiccup-php)[ Packagist](https://packagist.org/packages/nixn/hiccup)[ RSS](/packages/nixn-hiccup/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (1)Versions (2)Used By (0)

hiccup-php
==========

[](#hiccup-php)

An HTML rendering and templating engine, based on PHP code (strings, arrays, classes and inheritance). It is a (sophisticated) port of [Hiccup for Clojure](https://github.com/weavejester/hiccup).

Installation
------------

[](#installation)

Via composer:

```
composer require nixn/hiccup

```

Usage
-----

[](#usage)

The library consists of two main parts: the `Hiccup` class and the `Template` interface with its counterpart, the abstract class `Template_Base`.

### Hiccup

[](#hiccup)

This is the class which renders HTML from a number of data structures (including `Template`). It has a single main method: `static function html(mixed ...$elements): string` (and several helper methods), and it interprets the different elements passed to it as HTML structure(s) (recursively), joins them together and returns the resulting HTML string.

Possible elements (PHP types):

#### null

[](#null)

A null value renders nothing, it effectively is ignored (equivalent to an empty string as result).

#### string

[](#string)

A string is taken as the leaf value of an HTML structure, best described as textual tag content. It is automatically escaped, unless you use `Hiccup::raw()` to protect it; then it is passed as-is to the output string.

#### (another) scalar or `\Stringable` value

[](#another-scalar-or-stringable-value)

That includes values like booleans, integers, floats, etc., all of which have a natural string representation, or objects of classes implementing `\Stringable` but not `Template`. They are converted to an escaped string too, but without the possibility to be protected by `Hiccup::raw()` directly. If you want that, you have to convert it yourself, e.g. by calling `Hiccup::raw("$my_stringable_object")`.

#### `Template`s

[](#templates)

These objects are handled differently. The method (Template::)`hiccup(): mixed` is called on them, which can return any Hiccup element, which is then rendered recursively. Due to the nature of PHP, which can return only one value from a function, often it will be the result of the call `Hiccup::each()`, which is an iterable (see below), but it can also be any other element from this list.

#### iterable (except array)

[](#iterable-except-array)

An iterable is taken as a list of sibling elements. They are rendered behind one another, calling `html()` recursively on them. An array is explicitely not handled as an iterable, because it is ... (see below).

#### array

[](#array)

Arrays are the heart of the Hiccup "language", they denote HTML tags and their children and make up the structure of HTML. They start with a string, which is the tag name; optionally followed by an associative array, which is rendered as the attributes of this tag; and finally followed by zero or more child elements, which are rendered as siblings (just like in `Hiccup::each()` or with an iterable) below this tag in the result.

The tag name can have modifications (suffixes), which are interpreted as attributes, to enable easy and fast declaration of the tag attributes. In detail that are:

- `#` - renders to the attribute `id=""`
- `.` - renders to the attribute `class=""`, repeatable (all classes are set)
- `[]` - renders to the attribute `=""` (all attributes but `class` allowed)
    These can only be last, after any id or class modifications.

For better readability the values (``, ``, ``, `` and the tag name itself) can have whitespace after them, but not before (except ``) and also not in between.

Example:

```
['form #the-form .form.pretty [method]post [action]/my-script.php', ['title' => 'Please fill out!'],
  ['label', /*...*/],
  ['input', /*...*/],
]
```

(The title could not be written into the tag name string, because the value has whitespace!)

In the attributes array the elements have some different value possibilities:

- boolean value
    - `true` - renders to just ``
        (e.g. `['option', ['selected' => true]]` =&gt; ``)
    - `false` - not rendered (just omitted)
- for the `class` attribute there are other possibilities:
    - sequential strings array - all non-falsy values are rendered as class names
        (`['class' => ['a', 'b', $c ? 'c' : null, 'd']]` with falsy `$c` =&gt; `class="a b d"`)
    - associative array - all keys with a non-falsy value are rendered as class names
        (`['class' => ['a' => true, 'b' => false, 'c' => 'something']]` =&gt; `class="a c"`)

Hiccup has some helper functions to ease templating:

- `static function raw(?string $html): self`
    Wraps a string, and outputs it as-is (not HTML-escaped) on rendering.
- `static function foreach(?iterable $items, callable $action): iterable`
    Takes `$items` (which may be null), calls `$action` on every item and renders the results as siblings.
- `static function each(mixed ...$elements): iterable`
    Effectively just returns `$elements` as an iterable, most useful as a return value from a `Template` class.
- `static function join(mixed $separator, mixed ...$elements): iterable`
    Like the usual join(), but this `$separator` may be any Hiccup element.
- `static function lines(mixed ... $lines): iterable`
    A convenience method. Calls `Hiccup::join(Hiccup::raw("\n"), ...$lines)`.

### `Template`

[](#template)

The `Template` interface is the connection between the rendering and the class based templating. As described above a class which implements `Template` is a valid Hiccup element and will be called for its Hiccup code for rendering. Through inheritance and composition (usual class operations) it is possible to create the most complex templates, still as easy managable as a class structure, even with more power than with other templating engines, which always try to resemble the class structure in some way. Here it can be used directly (and is demonstrated below).

#### `Template_Base`

[](#template_base)

This abstract class is a helper class to make the template classes a breeze. It has two main functions:

##### Dynamic Methods

[](#dynamic-methods)

It uses the PHP magic method `__call(string $name, array $args): mixed`. That means every template class (which derives from `Template_Base`) can just use a call like `$this->content()` and if a subclass overrides it, it can deliver that content. If not, `null` is returned and rendered into nothing.

##### Namespacing

[](#namespacing)

Every derived template class can be assigned a parent and optional affixes, which is used in the dynamic call: If a parent is set, the call is redirected to it with the affixes appended, so the parent has control over its subtemplates and their calls.

Both is best explained by an example:

```
class Log extends Template_Base
{
    public function hiccup(): mixed
    {
        return Hiccup::each(
            (new OutputLine('debug message'))->set_parent($this, 'debug_'),
            (new OutputLine('usual message'))->set_parent($this, 'usual_'),
            (new OutputLine('error message'))->set_parent($this, 'error_'),
        );
    }

    protected function debug_p_class(): string
    {
        return 'gray';
    }

    protected function error_p_class(): string
    {
        return 'red';
    }
}

class OutputLine extends Template_Base
{
    public function __construct(private string $message) {}

    public function hiccup(): mixed
    {
        return ['p', ['class' => $this->p_class()], $this->message];
    }
}
```

### `HTML5`

[](#html5)

`nixn\hiccup\HTML5` is a pre-defined template class which can be used as a base for HTML5 pages. It contains the basic boilerplate with default but overridable values and can be the base of every generated template in a web page, which has to display HTML content. You may start with just overriding `body(): mixed` and put your content there, optionally `title(): string` too, and you are good to go for a basic page.

```
class IndexPage extends HTML5
{
    protected function title(): string
    {
        return 'Hello, world!';
    }

    protected function body(): mixed
    {
        return ['h1', 'Welcome, everyone! ', ['small', ':-)']];
    }
}

echo Hiccup::html(new IndexPage());
```

### Bootstrap example

[](#bootstrap-example)

With a really tiny bit more effort we can build the base page for a [Bootstrap](https://getbootstrap.com) layout.

```
class Page extends HTML5
{
    public function __construct(
        private bool $include_popper,
    )
    {}

    protected function head_end(): mixed
    {
        return ['link [rel]stylesheet [crossorigin]anonymous', [
            'href' => "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css",
            'integrity' => "sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH",
        ]];
    }

    protected function body(): mixed
    {
        return Hiccup::each(
            $this->content(),
            $this->include_popper ? ['script [crossorigin]anonymous', [
                'src' => 'https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js',
                'integrity' => "sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r",
            ]] : null,
            ['script [crossorigin]anonymous', [
                'src' => "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.min.js",
                'integrity' => "sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy",
            ]],
            $this->body_end(),
        );
    }
}
```

And use it:

```
class IndexPage extends Page
{
    public function __construct()
    {
        parent::__construct(false);
    }

    protected function content(): mixed
    {
        return ['h1.bg-secondary', 'Hello, world!'];
    }
}

echo Hiccup::html(new IndexPage());
```

License
-------

[](#license)

Copyright © 2025 nix

Distributed under the MIT license, available in the file [LICENSE](LICENSE).

Donations
---------

[](#donations)

If you like hiccup-php, please consider dropping some bitcoins to `1nixn9rd4ns8h5mQX3NmUtxwffNZsbDTP`.

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance41

Moderate activity, may be stable

Popularity4

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

485d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9264283df9cf60b086ad43eba0784549135c69cb42b2755fa62eef11c002770f?d=identicon)[nixn](/maintainers/nixn)

### Embed Badge

![Health badge](/badges/nixn-hiccup/health.svg)

```
[![Health](https://phpackages.com/badges/nixn-hiccup/health.svg)](https://phpackages.com/packages/nixn-hiccup)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[whitecube/nova-flexible-content

Flexible Content &amp; Repeater Fields for Laravel Nova.

8053.0M25](/packages/whitecube-nova-flexible-content)[mopa/bootstrap-bundle

Easy integration of twitters bootstrap into symfony2

7042.9M33](/packages/mopa-bootstrap-bundle)[limenius/react-bundle

Client and Server-side react rendering in a Symfony Bundle

3871.2M](/packages/limenius-react-bundle)[nicmart/string-template

StringTemplate is a very simple string template engine for php. I've written it to have a thing like sprintf, but with named and nested substutions.

2101.7M30](/packages/nicmart-string-template)[symfony/ux-icons

Renders local and remote SVG icons in your Twig templates.

555.8M69](/packages/symfony-ux-icons)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
