Users
Wirechat uses your application's user model for panel access, feature access, profile display, and user search.
Use this page when you need to decide who can use Wirechat, who can start conversations, how users appear in chat, or which users are returned in search.
User Access
Define access methods on your user model to control how each authenticated user can interact with Wirechat.
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
The canCreateChats() method controls whether a user can start one-to-one conversations through Wirechat's built-in UI.
public function canCreateChats(): bool
{
return $this->hasVerifiedEmail();
}
You can use your own application rules:
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
The canCreateGroups() method controls whether a 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().
It returns true by default. Override it to add blocking, friendship checks, or custom access rules.
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.
You may override this by defining the getWirechatNameAttribute() method:
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 will use the getWirechatProfileUrlAttribute() method
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 provides a flexible way to control how users are searched when starting new conversations or adding members to a group.
By default, a simple search is performed on your User model, but you can fully customize this behavior.
Customizing Searchable Attributes
If no custom callback is defined, Wirechat will search your User model using the attributes you specify:
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
To fully control the search logic, define a callback using searchUsersUsing().
Always wrap your results in WirechatUserResource to maintain a consistent structure:
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: Always return results using
WirechatUserResource. This ensures a consistent structure withid,type,wirechat_name, andwirechat_avatar_urlacross both Livewire and API responses.
In this example:
- Only active users are returned.
- The search is limited to the
namefield. - Using
WirechatUserResourceguarantees standardized responses.
Once configured, all user searches whether starting chats, creating groups, or adding members will follow your defined logic and return standardized results.
Conversations
You can access a user's conversations i.e the conversations they are a member of , either through the Wirechat UI or programmatically.
- 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