humweb/taggables
Composer 安装命令:
composer require humweb/taggables
包简介
A powerful and flexible tagging package for Laravel with polymorphic relationships and user-scoped tags support
README 文档
README
A powerful and flexible tagging package for Laravel applications with polymorphic relationships support and user-scoped tags.
Features
- 🏷️ Polymorphic tagging - Tag any Eloquent model
- 👤 User-scoped tags - Personal tags for each user alongside global tags
- 📁 Tag types - Organize tags into categories
- 🔍 Advanced queries - Filter models by tags with ease
- 🚀 Performance optimized - Eager loading and query optimization
- 📊 Tag statistics - Popular tags, tag clouds, and more
- 🎯 Type hinting - Full IDE support with proper return types
- ✨ Laravel conventions - Follows Laravel best practices
Installation
You can install the package via composer:
composer require humweb/taggables
Publish the migrations:
php artisan vendor:publish --tag="taggable-migrations"
Run the migrations:
php artisan migrate
Optionally, publish the config file:
php artisan vendor:publish --tag="taggable-config"
Usage
Making a Model Taggable
Add the HasTags trait to any model you want to make taggable:
use Humweb\Taggables\Traits\HasTags; use Illuminate\Database\Eloquent\Model; class Post extends Model { use HasTags; }
Basic Tagging Operations
$post = Post::find(1); // Add global tags (available to all users) $post->tag('laravel'); $post->tag(['php', 'javascript']); // Add user-specific tags $post->tagAsUser(['favorite', 'important'], $user); // Remove tags $post->untag('laravel'); $post->untag(['php', 'javascript']); $post->untag(); // Remove all tags // Remove user-specific tags $post->untagAsUser(['favorite'], $user); // Replace all tags $post->retag(['vue', 'tailwind']); $post->retagAsUser(['personal', 'work'], $user); // Sync tags (like Laravel's sync method) $post->syncTags(['laravel', 'php', 'mysql']); $post->syncTagsAsUser(['todo', 'urgent'], $user);
User-Scoped Tags
The package supports both global tags (available to all users) and user-specific tags:
// Create a global tag $post->tag('laravel'); // Available to all users // Create a user-specific tag $post->tagAsUser('personal-project', $user); // Mix global and user tags $post->tag(['php', 'laravel']); // Global $post->tagAsUser(['favorite', 'todo'], $user); // User-specific // Get only user tags $userTags = $post->userTags($user->id); // Get only global tags $globalTags = $post->globalTags(); // Get all tags (user + global) $allTags = $post->tags; // Returns both by default
Checking Tags
// Check if the model has a specific tag (checks user + global by default) if ($post->hasTag('laravel', $user->id)) { // ... } // Check for global tag only if ($post->hasGlobalTag('laravel')) { // ... } // Check for user tag only if ($post->hasUserTag('favorite', $user)) { // ... } // Check if the model has any of the given tags if ($post->hasAnyTag(['laravel', 'php'], $user->id)) { // ... } // Check if the model has all of the given tags if ($post->hasAllTags(['laravel', 'php'], $user->id)) { // ... }
Querying by Tags
// Get all posts with any of the given tags (includes user + global tags) $posts = Post::withAnyTags(['laravel', 'php'], null, $userId)->get(); // Get posts with user-specific tags only $posts = Post::withUserTags(['favorite', 'todo'], $user)->get(); // Get posts with global tags only $posts = Post::withGlobalTags(['laravel', 'php'])->get(); // Get all posts with all of the given tags $posts = Post::withAllTags(['laravel', 'php'], null, $userId)->get(); // Get all posts without the given tags $posts = Post::withoutTags(['draft', 'archived'], null, $userId)->get(); // Simple single tag query $posts = Post::taggedWith('laravel', $userId)->get();
Using Tag Types
Tag types allow you to categorize your tags:
// Tag with type $post->tag(['important', 'urgent'], 'priority'); $post->tagAsUser(['personal', 'work'], $user, 'category'); // Get tags of a specific type $priorityTags = $post->tagsWithType('priority'); $userCategories = $post->tagsWithType('category', $user->id); // Query by tags with type $posts = Post::withAnyTags(['important', 'urgent'], 'priority', $userId)->get();
Working with the Tag Model
use Humweb\Taggables\Models\Tag; // Find or create a tag $tag = Tag::findOrCreate('laravel'); // Global tag $tag = Tag::findOrCreateForUser('personal', $user); // User tag $tag = Tag::findOrCreateGlobal('php'); // Explicitly global // Find or create with type $tag = Tag::findOrCreate('important', 'priority', $user->id); // Find or create multiple tags $tags = Tag::findOrCreateMany(['laravel', 'php', 'mysql'], null, $user->id); // Search tags $tags = Tag::containing('lara')->get(); // Get tags by user $userTags = Tag::forUser($user->id)->get(); $globalTags = Tag::global()->get(); $mixedTags = Tag::forUserWithGlobal($user->id)->get(); // Get tags by type $priorityTags = Tag::withType('priority')->get(); // Get popular tags $popularTags = Tag::popularTags(10, $user->id); // Mixed popular tags $userPopular = Tag::popularUserTags(10, $user->id); // User's popular tags $globalPopular = Tag::popularGlobalTags(10); // Global popular tags // Get tag cloud (tags with usage weight) $tagCloud = Tag::tagCloud($user->id); // Mixed cloud $globalCloud = Tag::tagCloud(); // Global only // Get unused tags $unusedTags = Tag::unusedTags($user->id)->get(); // Check tag ownership $tag = Tag::find(1); if ($tag->isGlobal()) { // This is a global tag } elseif ($tag->isOwnedBy($user)) { // This is the user's tag }
Tag Suggestions
// Get tag suggestions based on partial input $suggestions = Tag::suggestTags('lara', $user->id); // Returns user + global tags $suggestions = Tag::suggestTags('lara'); // Returns only global tags // Get related tags (tags often used together) $tag = Tag::findOrCreate('laravel'); $relatedTags = $tag->relatedTags($user->id);
Events
The package fires events during tagging operations:
TagAttached- Fired when a tag is attached to a modelTagDetached- Fired when a tag is detached from a modelTagsSynced- Fired when tags are synced
use Humweb\Taggables\Events\TagAttached; // In your EventServiceProvider protected $listen = [ TagAttached::class => [ SendTagNotification::class, ], ];
Artisan Commands
Clean up unused tags:
php artisan tags:cleanup # Clean up only user tags php artisan tags:cleanup --user=123 # Clean up only global tags php artisan tags:cleanup --global
Advanced Usage
Custom Tag Model
You can extend the Tag model for additional functionality:
namespace App\Models; use Humweb\Taggables\Models\Tag as BaseTag; class Tag extends BaseTag { // Add your custom methods public function isPublic(): bool { return $this->isGlobal() || $this->metadata['public'] ?? false; } }
Update the config to use your custom model:
// config/taggable.php return [ 'tag_model' => \App\Models\Tag::class, ];
Eager Loading
// Eager load all tags $posts = Post::with('tags')->get(); // Eager load only user tags $posts = Post::with(['tags' => function ($query) use ($userId) { $query->where('user_id', $userId); }])->get(); // Eager load only global tags $posts = Post::with(['tags' => function ($query) { $query->whereNull('user_id'); }])->get(); // Eager load tags with specific type $posts = Post::with(['tags' => function ($query) { $query->where('type', 'technology'); }])->get();
Caching
The package supports caching for better performance:
// config/taggable.php return [ 'cache' => [ 'enabled' => true, 'key_prefix' => 'taggable', 'ttl' => 3600, // 1 hour ], ];
Configuration
The full configuration file:
return [ // The tag model to use 'tag_model' => \Humweb\Taggables\Models\Tag::class, // Table names 'tables' => [ 'tags' => 'tags', 'taggables' => 'taggables', ], // Slug generation 'slugger' => null, // null defaults to Str::slug // Tag name validation rules 'rules' => [ 'name' => ['required', 'string', 'max:255'], ], // Auto-delete unused tags 'delete_unused_tags' => false, // User scoping configuration 'user_scope' => [ // Enable user-scoped tags 'enabled' => true, // Allow creation of global tags (null user_id) 'allow_global_tags' => true, // Include global tags when querying user tags 'mix_user_and_global' => true, ], // Cache configuration 'cache' => [ 'enabled' => true, 'key_prefix' => 'taggable', 'ttl' => 3600, ], ];
Migration Notes
The tags table includes a user_id column for user-scoped tags:
Schema::create('tags', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('slug'); $table->foreignId('user_id')->nullable()->constrained()->cascadeOnDelete(); $table->string('type')->nullable()->index(); $table->integer('order_column')->default(0); $table->json('metadata')->nullable(); $table->timestamps(); // Same slug can exist for different users/types $table->unique(['slug', 'user_id', 'type']); $table->index(['user_id', 'type', 'order_column']); });
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
humweb/taggables 适用场景与选型建议
humweb/taggables 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.22k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 05 月 24 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「tags」 「tagging」 「laravel」 「polymorphic」 「humweb」 「taggables」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 humweb/taggables 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 humweb/taggables 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 humweb/taggables 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Tags plugin for CakePHP
A powerfull cacher based on laravels file cache driver
Phalcon PHP Meta tags service
A tool for scraping URL resources (oEmbed, OpenGraph, Twitter cards, JSON-LD)
The tag extension for the yii framework
A patch for TYPO3 to easily add tags just like categories to any element
统计信息
- 总下载量: 1.22k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 7
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-05-24