galengidman's avatar

DB schema / Eloquent relationships for @username mentions

Hi all. I'm trying to figure out how to setup my models and relationships to store @username mentions. Here's the basic DB schema I want:

comments
- body = (text) <string of text containing @username mentions>
- ...

posts
- body = (text) <string of text containing @username mentions>
- ...

users
- id = (int)
- ...

mentions
- model_type = (varchar) App\Models\Comment | App\Models\Post
- model_id = (int)
- user_id (int)
- created_at (datetime)
- updated_at (datetime)

I want to be able to use $comment->mentions and $post->mentions to retrieve users mentioned in the post, and $user->mentions to retrieve posts and comments that have mentioned the user, and use the Eloquent attach/detach/sync methods to manage the relationships..

I believe mentions should be a pivot model, but I'm struggling to wrap my head around how to set this up past that.

0 likes
3 replies
coa989's avatar

@galengidman have you found a solution for this problem? The videos were not helpful for DB part.

galengidman's avatar

@coa989 Frankly, don't remember all my findings after all this time, but here's what I have in my code today:

Schema:

Schema::create('mentions', function (Blueprint $table) {
    $table->id();
    $table->timestamps();
    $table->morphs('mentionable');
    $table->unsignedBigInteger('user_id');
});

Models:

class Post extends Model
{
    use Mentionable;
}

class Comment extends Model
{
    use Mentionable;
}

Mentionable trait:

use Staudenmeir\EloquentHasManyDeep\HasRelationships;

trait Mentionable
{
    use HasRelationships;

    public function mentions()
    {
        return $this->morphMany(Mention::class, 'mentionable');
    }

    public function mentionedUsers()
    {
        return $this->hasManyDeepFromRelations(
            $this->mentions(),
            (new Mention)->user()
        );
    }
}

It looks like I didn't end up needing or creating a $user->mentions() relationship like I asked about in my OP.

1 like

Please or to participate in this conversation.