PHPackages                             parisek/twig-attribute - 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. parisek/twig-attribute

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

parisek/twig-attribute
======================

A Twig extension for adding attributes to an element

v1.6.1(1mo ago)33.7k↑2080%1[1 issues](https://github.com/parisek/twig-attribute/issues)2GPL-2.0-or-laterPHPPHP ^8.3CI passing

Since Jan 17Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/parisek/twig-attribute)[ Packagist](https://packagist.org/packages/parisek/twig-attribute)[ Docs](https://github.com/parisek/twig-attribute)[ RSS](/packages/parisek-twig-attribute/feed)WikiDiscussions main Synced today

READMEChangelog (9)Dependencies (11)Versions (17)Used By (2)

parisek/twig-attribute
======================

[](#parisektwig-attribute)

A Twig 3 extension that gives templates a `create_attribute()` function for collecting, sanitizing, and rendering HTML attributes — backed by a vendored, maintained port of Drupal's `Attribute` class.

The package ships its own port (under `Drupal\Component\Attribute`) rather than depending on Drupal core. The vendored sources are refreshed from Drupal 11.x on each release; the API matches what Drupal templates expect.

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

[](#installation)

```
composer require parisek/twig-attribute
```

Requires PHP ^8.3 and Twig ^3.0. No Drupal dependencies.

Usage
-----

[](#usage)

Plain PHP:

```
$twig = new \Twig\Environment($loader);
$twig->addExtension(new \Parisek\Twig\AttributeExtension());
```

Symfony service:

```
services:
  Parisek\Twig\AttributeExtension:
    tags: [{ name: twig.extension }]
```

In templates
------------

[](#in-templates)

```
{% set my_attribute = create_attribute() %}
{% set my_classes = [
  'kittens',
  'llamas',
  isKitten ? 'cats' : 'dogs',
] %}

  {{ content }}

```

```

  {{ content }}

```

The full API (class methods, escape semantics, `without` filter behavior) mirrors [Drupal's Attribute class](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Template%21Attribute.php/class/Attribute/11.x).

Upgrading from 1.5.x to 1.6.0
-----------------------------

[](#upgrading-from-15x-to-160)

**Action required: none for the vast majority of consumers.** Run `composer update parisek/twig-attribute`.

What changes under the hood:

- The vendored `Drupal\Component\Attribute\*` classes are refreshed from Drupal 11.x core. Existing methods (`addClass`, `setAttribute`, `removeAttribute`, `hasClass`, `merge`, `toArray`, `__toString`, iterator support) keep their signatures and render output.
- New methods become available — your existing templates ignore them unless you opt in:
    - `hasAttribute(string $name): bool` — check existence without throwing.
    - `removeClass(...$classes): static` — symmetric counterpart of `addClass`.
    - `getClass(): AttributeArray` — read the class collection.
    - `jsonSerialize(): string` — JSON encoding support (returns the rendered attribute string).
    - `__clone()` — deep-clone correctness.
- The package now ships its own test suite (`tests/AttributeTest.php`, 18 methods, pure PHPUnit). Run `vendor/bin/phpunit` to verify the install if you want extra confidence.
- Composer constraints tightened to **Twig 3+ and PHP ^8.3**. Both were already required transitively by `drupal/core-utility ^10.0 || ^11.0`in 1.5.x, so this change doesn't shrink the real install matrix.
- Both `drupal/core-render` and `drupal/core-utility` are **no longer required** by this package. `Html::escape()` is inlined as a 5-LOC private helper. `NestedArray::mergeDeep` and `PlainTextOutput::renderFromHtml`are inlined as minimal `Parisek\Twig\Internal\*` shims.

### Edge cases that may need action

[](#edge-cases-that-may-need-action)

- **You were reaching `Drupal\Component\Render\…` or `Drupal\Component\Utility\…` classes through this package's transitive install.** Unusual, but possible if you wrote framework-level code on top of the Attribute classes. Fix: add the relevant `drupal/core-*`package to your own `composer.json` `require`. This is the correct long-term shape regardless — relying on transitive availability is fragile.
- **You're on PHP &lt; 8.3 or Twig 2.** You couldn't actually install 1.5.x cleanly against modern Drupal 10/11 either, so this is more about cleaning up your constraints. Bump PHP/Twig in your own project, or pin `parisek/twig-attribute` to `1.5.*` to stay on the previous floor.

### Direct PHP usage

[](#direct-php-usage)

If your code does `new \Drupal\Component\Attribute\AttributeCollection(...)`in PHP (instead of using `create_attribute()` from Twig), the refresh adds methods but doesn't remove any. Your existing calls keep working in 1.6.0.

Development
-----------

[](#development)

```
composer install
vendor/bin/phpunit              # 41 tests
vendor/bin/phpstan analyse      # level 5
```

Source-of-truth for the vendored Drupal port is Drupal 11.x core at `git.drupalcode.org/project/drupal/-/tree/11.x/core/lib/Drupal/Core/Template`. When the upstream changes meaningfully, copy the relevant files into `.upstream/` (gitignored scratch dir) and re-port. See `docs/refresh-decisions.md`for the rationale behind the inline shims that let this package drop `drupal/core-render` and `drupal/core-utility`.

Use cases
---------

[](#use-cases)

- [Drupal — Pattern Lab](https://patternlab.io/)
- [WordPress — Timber](https://wordpress.org/plugins/timber-library/)
- [Pimcore — Templates](https://pimcore.com/en)
- [parisek/styleguide](https://github.com/parisek/styleguide) — the package that drove the 1.6.0 refresh.

###  Health Score

56

—

FairBetter than 97% of packages

Maintenance87

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community18

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 94.4% of commits — single point of failure

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

Every ~245 days

Total

9

Last Release

32d ago

PHP version history (3 changes)v1.0.0PHP &gt;=7.3.0

v1.4.0PHP &gt;=8.1.0

v1.6.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/0f60a7484412a046d60bd8de9c5fb773cd9d59f00a1b455284fa718b786a4d93?d=identicon)[parisek](/maintainers/parisek)

---

Top Contributors

[![parisek](https://avatars.githubusercontent.com/u/10908003?v=4)](https://github.com/parisek "parisek (17 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

drupaldrupal-10drupal-9phppimcore-bundlesymfony-bundletimbertwigtwig-attributetwig-extensiontwigattribute

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/parisek-twig-attribute/health.svg)

```
[![Health](https://phpackages.com/badges/parisek-twig-attribute/health.svg)](https://phpackages.com/packages/parisek-twig-attribute)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.1k](/packages/craftcms-cms)[symfony/ux-twig-component

Twig components for Symfony

22018.6M356](/packages/symfony-ux-twig-component)[symfony/ux-live-component

Live components for Symfony

1647.0M128](/packages/symfony-ux-live-component)[symfony/ux-toolkit

A tool to easily create a design system in your Symfony app with customizable, well-crafted Twig components

16126.1k1](/packages/symfony-ux-toolkit)[mati365/ckeditor5-symfony

CKEditor 5 integration for Symfony

262.6k](/packages/mati365-ckeditor5-symfony)

PHPackages © 2026

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