A Model to Hold Tags for both Reviews and Threads

You are thinking on the right lines. Think of tags as a generic entity. A tag can be assigned to anything and anyone, therefore tags are polymorphic as you have pointed out.

Having said that, a typical tag table could look like this.

Schema::create('tags', function (Blueprint $table) {
            $table->increments('id');
            $table->json('name');
            $table->json('slug');
        });

The tags table will store the individual tags, think of it like a pool of tags. This would be a great place to ensure tags are unique.

You would then have a taggables table. This table is nothing more than a collection of foreign keys. This is the table that will store the tag against an entity, in your case tags against reviews and threads or anything else you can think of.

A taggables table may look like the following.

Schema::create('taggables', function (Blueprint $table) {
            $table->integer('tag_id')->unsigned();
            
            $table->uuid('taggable_id');
            $table->string('taggable_type');

            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
        });

The taggable_id column would be id of the thing you want to tag, e.g. id of a review or a thread.

The taggable_type column would be the class name of the model being tagged e.g. App\Models\Thread or App\Models\Review.

Any model that needs to allow tagging should have a relation with the taggable table that needs to be defined on the model itself perhaps a trait would do the trick.

Finally the tag assignment in your controller or wherever would look something like the following.

$review->syncTags(...);

OR

If you want to save time and don’t want to reinvent the wheel, look into Spatie’s tags library built for this very purpose see here.

Hope this helps. Good luck!

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top