Participant
Participant is the membership pivot model between a conversation and one of your application's models.
This is the model that makes Wirechat polymorphic.
It is one of the most important models to keep compatible because message visibility, role checks, and delete or clear behavior all depend on it.
Core fields:
| Field | Purpose |
|---|---|
conversation_id |
The thread this membership belongs to. |
participantable_id |
The underlying app model id. |
participantable_type |
The morph class for the underlying app model. |
role |
Participant role enum, including owner and admin. |
exited_at |
Timestamp used to mark members who left a conversation. |
last_active_at |
Participant activity timestamp. |
conversation_read_at |
Last read marker for unread logic. |
conversation_cleared_at |
Last clear-history marker. |
conversation_deleted_at |
Last delete-for-user marker. |
Important Relationships
participantable(): MorphTo
Returns the real app model behind the participant row.
$participant->participantable
conversation(): BelongsTo
Returns the parent conversation.
$participant->conversation
messages(): HasMany
Returns messages sent by this participant.
$participant->messages()->latest()->get()
latestMessage(): HasOne
Resolves the most recent message sent by this participant.
$participant->latestMessage
actions(): MorphMany
Returns actions recorded against this participant row.
$participant->actions()->latest()->get()
performedActions(): MorphMany
Returns actions this participant performed as an actor.
$participant->performedActions()->latest()->get()
Important Helpers
isAdmin(): bool
Returns true when the participant is an admin or the owner. The owner is also treated as an admin by Wirechat.
$participant->isAdmin()
isOwner(): bool
Returns true only when this participant is the conversation owner.
$participant->isOwner()
exitConversation(): bool
Marks the participant as exited while enforcing package rules such as blocking owners from leaving their own group.
$participant->exitConversation()
hasExited(): bool
Checks whether the participant already left the conversation.
$participant->hasExited()
isRemovedByAdmin(): bool
Checks whether an admin-removal action exists for this participant.
$participant->isRemovedByAdmin()
removeByAdmin(Model|Authenticatable $admin): void
Records the admin-removal action using the admin's participant row as the actor, then downgrades the removed member's role.
$participant->removeByAdmin(auth()->user())
hasDeletedConversation(bool $checkDeletionExpired = false): bool
Checks whether delete-for-user is active, optionally comparing it against the conversation's latest update timestamp.
$participant->hasDeletedConversation(true)
Important Query Helpers
whereParticipantable(Model|Authenticatable $model)
Filters participant rows for a specific app model.
Participant::query()->whereParticipantable(auth()->user())->first()
withExited()
Includes participants hidden by the default exited scope.
Participant::query()->withExited()->get()
withoutParticipantable(Model|Authenticatable $user)
Excludes a specific participantable model from the query.
$conversation->participants()->withoutParticipantable(auth()->user())->get()
Typical safe customizations:
- Add participant-level profile helpers.
- Add app-specific membership metadata.
- Add convenience methods that build on role and visibility state.
- Preserve the default global scopes unless you are intentionally replacing the membership rules.