Looking to hire Laravel developers? Try LaraJobs
This package is not available.

tags-for-laravel maintained by roundly-consulting

Description
Typed taxonomies for any Eloquent model: flat or nested, single- or multi-select, curated or free-form, tenant-scoped and translatable, with autocomplete, usage counts and query scopes.
Last update
2026/10/20 14:09 (dev-main)
License
Downloads
52

Comments
comments powered by Disqus

Tags for Laravel

Typed taxonomies for any Eloquent model: flat labels or nested category trees, single- or multi-select, curated or free-form, global or tenant-scoped, and translatable in every locale — with autocomplete, usage counts and query scopes that never N+1.

Installation

Requires PHP 8.4, Laravel 12 or 13, and PostgreSQL 12+ or MySQL 8.0.23+.

composer require roundly-consulting/tags-for-laravel
php artisan vendor:publish --tag="tags-migrations"
php artisan migrate

Tag names are stored per locale: make sure your app locale is in translatable.locales (default en, sk).

Usage

Make a model taggable:

use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Tags\Concerns\HasTags;
use RoundlyConsulting\Tags\Contracts\Taggable;

final class Concert extends Model implements Taggable
{
    use HasTags;
}

Declare your types, build a tree, tag, query and suggest:

use RoundlyConsulting\Tags\Facades\Tags;

// Declare your tag types once, in a service provider
Tags::define('genre')->hierarchical()->single();   // a curated category tree, one per model
Tags::define('label')->max(5);                     // free-form labels, up to five

// Build the tree (names are translatable; a plain string is the current locale)
$music = Tags::type('genre')->make(['en' => 'Music', 'sk' => 'Hudba'])->color('#f24e29')->create();
$jazz = Tags::type('genre')->make('Jazz')->under($music)->create();

// Tag any model that uses HasTags
$concert->syncTags($jazz, 'genre');
$concert->attachTags(['Live', 'Outdoor'], 'label');     // unknown labels are created on the fly

// Query: "music" also matches everything under it
Concert::withAnyTags(['music'], 'genre', descendants: true)->get();
Concert::withAllTags(['live', 'outdoor'], 'label')->get();

// Read without N+1
foreach (Concert::with('tags')->get() as $concert) {
    echo $concert->tagOf('genre')?->name;                         // Jazz
    echo $concert->tagsOf('label')->pluck('name')->join(', ');    // Live, Outdoor
}

// Autocomplete and popularity
Tags::type('label')->suggest('liv');    // prefix matches first, in every locale
Tags::type('label')->popular(10);

Documentation

The full documentation — configuration, every feature and its API, and testing — lives on our website: roundly-consulting.com/open-source/docs/tags-for-laravel

Release notes are in CHANGELOG.md. To contribute, see the contributing guide.

Support our work

This package is free and open source, built and maintained by Roundly Consulting. If it saves you time, please consider supporting our open-source work — a one-time donation, a monthly pledge on Patreon or a crypto donation helps fund maintenance, new features and new packages.

License

The MIT License (MIT). See LICENSE.md.