PHPackages                             mujahidabbas/laravel-user-tags - 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. [Database &amp; ORM](/categories/database)
4. /
5. mujahidabbas/laravel-user-tags

ActiveLibrary[Database &amp; ORM](/categories/database)

mujahidabbas/laravel-user-tags
==============================

User-scoped tagging for Laravel Eloquent models

v1.0.0(3mo ago)01MITPHPPHP ^8.1|^8.2|^8.3CI passing

Since Jan 27Pushed 3mo agoCompare

[ Source](https://github.com/MujahidAbbas/laravel-user-tags)[ Packagist](https://packagist.org/packages/mujahidabbas/laravel-user-tags)[ Docs](https://github.com/MujahidAbbas/laravel-user-tags)[ RSS](/packages/mujahidabbas-laravel-user-tags/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (7)Versions (2)Used By (0)

Laravel User Tags
=================

[](#laravel-user-tags)

[![Latest Version on Packagist](https://camo.githubusercontent.com/67991ec8de31279241cebdef64be33d8b7dfffc122fd557a2a3288c575794251/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d756a6168696461626261732f6c61726176656c2d757365722d746167732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mujahidabbas/laravel-user-tags)[![GitHub Tests Action Status](https://camo.githubusercontent.com/1ad506783f00026605774504a0068c56e638da4d14f2d3d1911a43fc615e3a4f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d756a6168696461626261732f6c61726176656c2d757365722d746167732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/mujahidabbas/laravel-user-tags/actions?query=workflow%3Arun-tests+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/5dbc32140d6007d7e5d5487045dbeeddf7aa061d421030b6f0ddccbe14f1b21c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d756a6168696461626261732f6c61726176656c2d757365722d746167732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mujahidabbas/laravel-user-tags)[![License](https://camo.githubusercontent.com/98b3ae20a82dafccac188ce9b369c6764578e2d13ec3ca1d55b48307ac39255b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6d756a6168696461626261732f6c61726176656c2d757365722d746167733f7374796c653d666c61742d737175617265)](LICENSE.md)

User-scoped tagging for Laravel Eloquent models. Each user has their own private set of tags that are invisible to and independent from other users' tags.

```
// User A tags an article
$article->attachUserTag('important'); // Creates User A's "important" tag

// User B tags the same article
Auth::login($userB);
$article->attachUserTag('important'); // Creates User B's separate "important" tag

// Query User A's tagged articles (only sees their own tags)
Auth::login($userA);
$articles = Article::withAnyUserTags(['important'])->get();
```

Why This Package?
-----------------

[](#why-this-package)

If you've used [spatie/laravel-tags](https://github.com/spatie/laravel-tags) and wondered how to give each user their own private tag namespace, this package is for you.

**The problem:** Global tagging packages share tags across all users. User A's "important" tag is the same as User B's "important" tag.

**The solution:** This package isolates tags per user. Each user has their own private set of tags that are completely invisible to and independent from other users' tags.

**Use cases:**

- Personal CRM systems where users organize their own contacts
- Bookmark managers with private collections
- Note-taking apps with personal organization
- Any multi-user app where users need private categorization

Requirements
------------

[](#requirements)

- PHP 8.1, 8.2, or 8.3
- Laravel 10.x, 11.x, or 12.x

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

[](#installation)

You can install the package via composer:

```
composer require mujahidabbas/laravel-user-tags
```

Publish and run the migrations:

```
php artisan vendor:publish --tag="user-tags-migrations"
php artisan migrate
```

Optionally, you can publish the config file:

```
php artisan vendor:publish --tag="user-tags-config"
```

Configuration
-------------

[](#configuration)

The published config file (`config/user-tags.php`) contains:

```
return [
    // Your User model class
    'user_model' => 'App\\Models\\User',

    // Table names (customize if needed)
    'tables' => [
        'tags' => 'user_tags',
        'taggables' => 'user_taggables',
    ],
];
```

Usage
-----

[](#usage)

### Preparing Your Model

[](#preparing-your-model)

Add the `HasUserTags` trait to any Eloquent model you want to tag:

```
use Illuminate\Database\Eloquent\Model;
use MujahidAbbas\LaravelUserTags\Traits\HasUserTags;

class Article extends Model
{
    use HasUserTags;
}
```

### Attaching Tags

[](#attaching-tags)

Use `attachUserTag()` to add tags to a model. Tags are automatically created if they don't exist:

```
// Attach a single tag (uses authenticated user)
$article->attachUserTag('important');

// Attach multiple tags at once
$article->attachUserTag(['important', 'read-later', 'favorites']);

// Attach with a specific user (useful in queues, commands, etc.)
$article->attachUserTag('important', $user);
```

Tags are user-scoped, so User A's "important" tag is completely separate from User B's "important" tag.

### Detaching Tags

[](#detaching-tags)

Use `detachUserTag()` to remove tags from a model. Non-existent tags are silently ignored:

```
// Detach a single tag
$article->detachUserTag('important');

// Detach multiple tags
$article->detachUserTag(['important', 'read-later']);

// Detach with a specific user
$article->detachUserTag('important', $user);
```

Note: This only removes the association; the tag itself is not deleted.

### Syncing Tags

[](#syncing-tags)

Use `syncUserTags()` to replace all of a user's tags on a model with a new set:

```
// Replace all current user's tags with exactly these
$article->syncUserTags(['priority', 'work']);

// Sync with a specific user
$article->syncUserTags(['priority', 'work'], $user);
```

**Important:** `syncUserTags()` only affects the specified user's tags. Other users' tags on the same model remain untouched.

### Accessing Tags

[](#accessing-tags)

The `userTags()` relationship returns all tags attached to a model (from all users):

```
// Get all tags on this model
$tags = $article->userTags;

// Eager load tags
$articles = Article::with('userTags')->get();

// Filter to a specific user's tags
$myTags = $article->userTags->where('user_id', auth()->id());
```

### Querying by Tags

[](#querying-by-tags)

Query models that have specific tags using scope methods:

```
// Get posts with ANY of these tags (OR logic)
$posts = Post::withAnyUserTags(['important', 'urgent'])->get();

// Get posts with ALL of these tags (AND logic)
$posts = Post::withAllUserTags(['priority', 'review'])->get();

// Get posts WITHOUT specific tags
$posts = Post::withoutUserTags(['archived', 'spam'])->get();

// Chain scopes
$posts = Post::withAnyUserTags(['tech', 'science'])
    ->withoutUserTags(['archived'])
    ->get();

// With a specific user (useful in queues, commands)
$posts = Post::withAnyUserTags(['important'], $user)->get();
```

**Note:** Query scopes respect user isolation - User A's scope queries only consider User A's tags.

### Using a Custom User

[](#using-a-custom-user)

All tag methods accept an optional user parameter. This is useful when the authenticated user is not available:

```
// In a queue job
public function handle()
{
    $user = User::find($this->userId);
    $article->attachUserTag('processed', $user);
}

// In a console command
$user = User::find($userId);
$article->syncUserTags(['archived'], $user);
```

If no user is authenticated and none is passed, a `NoAuthenticatedUserException` is thrown:

```
use MujahidAbbas\LaravelUserTags\Exceptions\NoAuthenticatedUserException;

try {
    $article->attachUserTag('important');
} catch (NoAuthenticatedUserException $e) {
    // Handle missing user
}
```

Important: MorphMap Configuration
---------------------------------

[](#important-morphmap-configuration)

This package uses polymorphic relationships to attach tags to any model. By default, Laravel stores the full class name (e.g., `App\Models\Article`) in the database.

**Why MorphMap matters:**

- If you rename or move a model class, existing tag associations break
- Full class names are verbose and expose your application structure
- Consistent short names make database queries cleaner

**Recommended: Configure MorphMap in your AppServiceProvider:**

```
use Illuminate\Database\Eloquent\Relations\Relation;

public function boot(): void
{
    Relation::enforceMorphMap([
        'article' => \App\Models\Article::class,
        'post' => \App\Models\Post::class,
        'comment' => \App\Models\Comment::class,
        // Add all models that use HasUserTags
    ]);
}
```

This ensures stable, clean identifiers in your `user_taggables` table instead of full class paths.

Alternatives
------------

[](#alternatives)

If you need **global tags** (shared across all users), use [spatie/laravel-tags](https://github.com/spatie/laravel-tags) instead. It's excellent for content categorization, blog post tags, and similar use cases where tags are public.

This package is designed to **complement** spatie/laravel-tags, not replace it. You can use both in the same application:

- `spatie/laravel-tags` for public/global tags (e.g., blog categories)
- `mujahidabbas/laravel-user-tags` for private/user-scoped tags (e.g., personal bookmarks)

Testing
-------

[](#testing)

```
composer test
```

Static Analysis
---------------

[](#static-analysis)

```
composer analyse
```

Code Style
----------

[](#code-style)

```
composer format
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Roadmap
-------

[](#roadmap)

Future releases may include:

- Tag management utilities (`Tag::forUser()`, tag search/autocomplete)
- Events (`UserTagAttached`, `UserTagDetached`, `UserTagCreated`)
- Tag metadata (colors, icons via JSON column)
- Tag usage statistics

See the [GitHub issues](https://github.com/mujahidabbas/laravel-user-tags/issues) for feature requests and discussions.

Credits
-------

[](#credits)

- [Mujahid Abbas](https://github.com/MujahidAbbas)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance80

Actively maintained with recent releases

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

105d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/974c77ba95dbdf0677810fba7860aba792bdb0e4ba639f10016f160dda899bdc?d=identicon)[MujahidAbbas](/maintainers/MujahidAbbas)

---

Top Contributors

[![MujahidAbbas](https://avatars.githubusercontent.com/u/21082153?v=4)](https://github.com/MujahidAbbas "MujahidAbbas (6 commits)")

---

Tags

eloquentlaravellaravel-packagephptagginglaraveleloquenttagstagginguser-tags

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/mujahidabbas-laravel-user-tags/health.svg)

```
[![Health](https://phpackages.com/badges/mujahidabbas-laravel-user-tags/health.svg)](https://phpackages.com/packages/mujahidabbas-laravel-user-tags)
```

###  Alternatives

[rtconner/laravel-tagging

Use PHP traits to extend Laravel Eloquent Models to allow Tags. Models can be marked as Taggable.

8833.1M14](/packages/rtconner-laravel-tagging)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[cviebrock/eloquent-taggable

Easy ability to tag your Eloquent models in Laravel.

567694.8k3](/packages/cviebrock-eloquent-taggable)[cybercog/laravel-love

Make Laravel Eloquent models reactable with any type of emotions in a minutes!

1.2k302.7k1](/packages/cybercog-laravel-love)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)

PHPackages © 2026

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