Users
Wirechat uses your application's user model for panel access, feature access, profile display, unread counts, conversation membership, and user search.
User-model methods control how Wirechat renders panels, starts conversations, displays users, and searches for recipients.
User Access
Define access methods on your authenticated application user model, usually app/Models/User.php. Method snippets without a class wrapper belong on that model unless a panel provider is shown.
Panel Access
Wirechat calls canAccessWirechatPanel() when a user opens a panel route. Return false to deny access to that panel.
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Wirechat\Wirechat\Contracts\WirechatUser;
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Traits\InteractsWithWirechat;
class User extends Authenticatable implements WirechatUser
{
use InteractsWithWirechat;
// ...
public function canAccessWirechatPanel(Panel $panel): bool
{
return $this->hasVerifiedEmail();
}
}
Because the current $panel is available, you can apply different rules per panel:
public function canAccessWirechatPanel(Panel $panel): bool
{
if ($panel->getId() === 'admin') {
return $this->is_admin && $this->hasVerifiedEmail();
}
return true;
}
Controlling 1-to-1 Chat Creation
On the same user model, canCreateChats() controls whether the authenticated user can start one-to-one conversations through Wirechat's built-in UI.
public function canCreateChats(): bool
{
return $this->hasVerifiedEmail();
}
The method can return any application rule:
public function canCreateChats(): bool
{
if ($this->conversations()->count() >= 100) {
return false;
}
if ($this->created_at->gt(now()->subDay())) {
return false;
}
return $this->hasVerifiedEmail();
}
When this method returns false, Wirechat hides the New Chat action and blocks UI-based chat creation. Existing conversations remain accessible.
If your app calls createConversationWith() directly, apply your own check around that call.
Controlling Group Creation
On the same user model, canCreateGroups() controls whether the authenticated user can create group conversations through Wirechat's built-in UI.
public function canCreateGroups(): bool
{
return $this->subscription?->active === true;
}
Combine it with verification, roles, account age, or any other application rule:
public function canCreateGroups(): bool
{
return $this->hasVerifiedEmail()
&& ($this->is_premium || $this->hasRole('admin'));
}
public function canCreateGroups(): bool
{
return $this->reputation_score >= 50
&& $this->account_age_days >= 30;
}
When this method returns false, Wirechat hides the New Group action and blocks UI-based group creation. The user can still participate in groups they already belong to.
If your app calls createGroup() directly, apply your own check around that call.
Controlling Who Can Message Whom
The canSendMessageTo(Model $recipient) method controls whether a user may send messages or message requests to a specific recipient.
Wirechat checks this method in the UI and when calling sendMessageRequestTo(), createConversationWith(), and sendMessage().
Wirechat's default implementation returns true. Define the method on your user model when private messages need blocking, friendship checks, or another application-specific access rule.
use Illuminate\Database\Eloquent\Model;
public function canSendMessageTo(Model $recipient): bool
{
return ! $this->hasBlocked($recipient)
&& ! $recipient->hasBlocked($this);
}
use Illuminate\Database\Eloquent\Model;
public function canSendMessageTo(Model $recipient): bool
{
return $this->friends()
->where('friend_id', $recipient->getKey())
->exists();
}
When this method returns false, Wirechat rejects private message creation and sending with a 403 response.
Unread Counts
User models using InteractsWithWirechat can retrieve unread message totals across all conversations:
$user->getUnreadCount();
Pass a conversation to scope the unread count to one thread:
$conversation = $user->conversations()->first();
$user->getUnreadCount($conversation);
Attributes
User attributes define how names, avatars, and profile links appear throughout chats.
User’s Name
By default, Wirechat uses the name attribute from your User model. Define getWirechatNameAttribute() on the user model to return a different display name:
use Wirechat\Wirechat\Traits\InteractsWithWirechat;
use Wirechat\Wirechat\Contracts\WirechatUser;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements WirechatUser
{
use InteractsWithWirechat;
public function getWirechatNameAttribute(): string
{
return $this->display_name ?? $this->name;
}
}
Avatar URL
Set the URL that should be used for the user’s avatar across chats, member lists, and chat info:
namespace App\Models;
use Wirechat\Wirechat\Traits\InteractsWithWirechat;
use Wirechat\Wirechat\Contracts\WirechatUser;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements WirechatUser
{
use InteractsWithWirechat;
public function getWirechatAvatarUrlAttribute(): string
{
return $this->avatar_url ?? asset('images/default-avatar.png');
}
}
Profile URL
When a user's name or avatar is clicked, Wirechat uses getWirechatProfileUrlAttribute() on the user model to determine where to redirect:
use Wirechat\Wirechat\Traits\InteractsWithWirechat;
use Wirechat\Wirechat\Contracts\WirechatUser;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements WirechatUser
{
use InteractsWithWirechat;
public function getWirechatProfileUrlAttribute(): string
{
return route('profile.show', $this->id);
}
}
Searching Users
Wirechat searches users when someone starts a new conversation or adds members to a group.
By default, Wirechat searches the configured attributes on your User model. Panel-level callbacks can replace that query when your application needs stricter filtering.
Customizing Searchable Attributes
Without a custom callback, Wirechat searches your User model using the attributes configured on the panel:
use Wirechat\Wirechat\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->searchableAttributes(['name', 'email', 'username']);
}
In this example, a query like "john" will match users where the name, email, or username contains "john".
Customizing the Search
For full control over recipient search, define a searchUsersUsing() callback on the panel. Return WirechatUserResource results so Livewire and API responses keep the same shape:
use Wirechat\Wirechat\Panel;
use Wirechat\Wirechat\Http\Resources\WirechatUserResource;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->searchUsersUsing(function (string $needle) {
return WirechatUserResource::collection(
\App\Models\User::query()
->where('is_active', true)
->where('name', 'like', "%{$needle}%")
->limit(20)
->get()
);
});
}
Important: Return custom search results as
WirechatUserResourceinstances so each result includes the expectedid,type,wirechat_name, andwirechat_avatar_urlvalues.
The example only returns active users and limits matching to the name field. The same callback is used when starting chats, creating groups, and adding members.
Conversations
The conversations() relationship returns conversations where the user is an active participant.
- Via Wirechat UI
Navigate to the /chats route to view your active conversations. Conversations that you have deleted, groups you have exited, or conversations without any messages will not appear in the list.
- Programmatically
$auth = auth()->user();
$conversations = $auth->conversations()->get();
You can also apply scopes to filter conversations:
Exclude Blank Conversations
$conversations = $auth->conversations()->withoutBlanks()->get();
Exclude Deleted Conversations
$conversations = $auth->conversations()->withoutDeleted()->get();
Note: Scopes only take effect when the user is authenticated.
Conversation Membership
Check whether a user is part of a conversation using the belongsToConversation() method:
$conversation = Wirechat\Wirechat\Models\Conversation::first();
$user->belongsToConversation($conversation); // Returns a boolean
Check if a Conversation Exists Between Users
$anotherUser = User::first();
$user->hasConversationWith($anotherUser); // Returns a boolean