Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel User Tags Laravel Package

mujahidabbas/laravel-user-tags

Laravel User Tags lets you attach custom tags to user models, making it easy to categorize, filter, and segment users. It offers a simple API for adding, removing, and querying tags, so you can organize users with lightweight labels throughout your Laravel application.

View on GitHub
Deep Wiki
Context7

Getting Started

v1.0.0 is the initial release, so there is no upgrade/migration path to consider yet. Treat it as a focused per-user tagging layer for Eloquent models: useful for favorites, bookmarks, inbox labels, saved filters, and other “this user marked this record” workflows.

Start here:

  1. Install using the exact Composer package command from the README.
  2. Publish/run any package migrations and confirm the tag table schema, indexes, and foreign keys.
  3. Add the HasUserTags trait to the models that should be taggable.
  4. Read the trait and query-scope source after installation to confirm method signatures and whether user context comes from auth() or an explicit user argument.
  5. Use the simplest case first: authenticated users favoriting shared records.
class Post extends Model
{
    use HasUserTags; // import the trait namespace from the package README
}

Typical authenticated-user flow:

$post->attachUserTag('favorite');

$favorites = Post::withAnyUserTags(['favorite'])->get();

The first valuable use case is per-user favorites or labels on shared records. Do not use this as a replacement for a global taxonomy unless you intentionally want each user’s tags isolated from everyone else’s.

Implementation Patterns

Use the three write methods as the core mutation API:

$post->attachUserTag('important');
$post->detachUserTag('important');
$post->syncUserTags(['important', 'reviewed']);

Use the query scopes for user-specific filtering:

Post::withAnyUserTags(['important', 'reviewed'])->get();
Post::withAllUserTags(['important', 'reviewed'])->get();
Post::withoutUserTags(['archived'])->get();

A common controller pattern:

public function index(Request $request)
{
    $validated = $request->validate([
        'tags' => ['sometimes', 'array'],
        'tags.*' => ['string', 'max:50'],
    ]);

    $tags = $validated['tags'] ?? [];

    return Post::query()
        ->when($tags, fn ($query) => $query->withAnyUserTags($tags))
        ->paginate();
}

For “replace this user’s tags on this record” flows, wrap syncUserTags() in a transaction and authorize the action before mutating:

DB::transaction(function () use ($post, $request) {
    $post->syncUserTags($request->array('tags'));
});

For tests, assert isolation explicitly. The key behavior is not just “the tag exists,” but “user A’s tags do not affect user B’s queries”:

$this->actingAs($userA);
$post->attachUserTag('favorite');

$this->actingAs($userB);
$this->assertSame(0, Post::withAnyUserTags(['favorite'])->count());

If the package exposes a tag relationship or query builder relation, use it for display screens to avoid repeatedly issuing per-model tag queries. If it does not, keep read paths query-scope based and avoid loading tags one model at a time.

Gotchas and Tips

  • Confirm the user-context contract first. The release notes list method names but not full signatures. Verify whether methods use auth()->user() implicitly or require an explicit user argument. This matters most in jobs, commands, tests, and service classes where no authenticated user exists.
  • Do not rely on ambient auth in background work. If the package reads the current authenticated user, explicitly set/authenticate the user context before tagging or querying in queued jobs and artisan commands.
  • Validate and normalize tags in your app. Decide whether tags are case-sensitive, trimmed, lowercased, or restricted in length. Doing this at the request/form-request layer keeps user tag namespaces consistent.
  • Test empty-array behavior. Check what withAnyUserTags([]), withAllUserTags([]), withoutUserTags([]), and syncUserTags([]) do in your installed version. The empty-list case is a common source of accidental “return everything” or “remove everything” bugs.
  • Check the migration indexes. For day-to-day query performance, the tag table should have appropriate composite indexes for user, tag, and taggable model identifiers. Add indexes in a follow-up migration if the package schema is missing them for your workload.
  • Handle user deletion. Confirm whether tag rows are cleaned up by foreign-key cascade, polymorphic cleanup, or not at all. Add a cleanup job/observer if orphaned tag rows would be a problem.
  • User-scoped is not team-scoped. If your application has teams, organizations, or tenants, this package’s isolation is per user. For team labels, either encode team context into tag names or wrap/extend the package with your own team-aware layer.
  • Pin the version during early adoption. v1.0.0 is a new public API. Pin the exact version in composer.json until you have reviewed subsequent releases and confirmed backward compatibility.
  • Check framework/runtime constraints. This release supports Laravel 10–12 and PHP 8.1–8.3. Confirm your deployment matrix before adopting, especially if any service still runs Laravel 9 or PHP 8.0.
  • Use policies for shared records. Tagging is user-scoped, but the underlying model may still require authorization. Do not let a user tag a record they cannot view or update unless that is an intentional product rule.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route