WireChat provides powerful search functionality for finding conversations and users quickly. Search can be customized and extended to match your application’s needs.
Chat List Search
Enable search in the conversation list:
use Wirechat\Wirechat\ Panel ;
Panel :: make ( 'admin' )
-> chatsSearch () // Enable conversation search
// ... other configuration
How It Works
The chat search queries both participant names and group information:
// src/Livewire/Chats/Chats.php:292-315
protected function applySearchConditions ( $query ) : Builder
{
$searchableFields = $this -> panel () -> getSearchableAttributes ();
$groupSearchableFields = [ 'name' , 'description' ];
return $query -> withDeleted () -> where ( function ( $query ) use ( $searchableFields , $groupSearchableFields ) {
// Search in participant names
$query -> whereHas ( 'participants' , function ( $subquery ) use ( $searchableFields ) {
$subquery -> whereHas ( 'participantable' , function ( $query2 ) use ( $searchableFields ) {
$query2 -> where ( function ( $query3 ) use ( $searchableFields ) {
foreach ( $searchableFields as $field ) {
$query3 -> orWhere ( $field , 'LIKE' , '%' . $this -> search . '%' );
}
});
});
});
// Search in group names and descriptions
return $query -> orWhereHas ( 'group' , function ( $groupQuery ) use ( $groupSearchableFields ) {
$groupQuery -> where ( function ( $query4 ) use ( $groupSearchableFields ) {
foreach ( $groupSearchableFields as $field ) {
$query4 -> orWhere ( $field , 'LIKE' , '%' . $this -> search . '%' );
}
});
});
});
}
Searchable User Attributes
Define which user fields should be searchable:
Panel :: make ( 'admin' )
-> searchableAttributes ([ 'name' , 'email' , 'username' ])
By default, WireChat searches the name field:
// src/Panel/Concerns/HasSearchableAttributes.php
protected array $searchableAttributes = [ 'name' ];
Multiple Fields
Search across multiple user attributes:
Panel :: make ( 'admin' )
-> searchableAttributes ([
'name' ,
'email' ,
'username' ,
'profile->bio' , // JSON column
])
User Search
Implement custom user search for starting new conversations:
Panel :: make ( 'admin' )
-> searchUsersUsing ( function ( string $search ) {
return User :: query ()
-> where ( function ( $q ) use ( $search ) {
$q -> where ( 'name' , 'like' , "%{ $search }%" )
-> orWhere ( 'email' , 'like' , "%{ $search }%" )
-> orWhere ( 'username' , 'like' , "%{ $search }%" );
})
-> where ( 'id' , '!=' , auth () -> id ()) // Exclude current user
-> limit ( 20 )
-> get ();
})
The search callback must return a Collection of models, not a query builder.
Default User Search
If no custom search is provided, WireChat uses the default implementation:
// src/Panel/Concerns/HasUsersSearch.php:47-56
return \App\Models\ User :: query ()
-> where ( function ( $q ) use ( $needle ) {
foreach ( $this -> getSearchableAttributes () as $field ) {
$q -> orWhere ( $field , 'like' , "%{ $needle }%" );
}
})
-> limit ( 20 )
-> get ();
Search Results
User search results are automatically formatted using the WirechatUserResource:
// src/Panel/Concerns/HasUsersSearch.php:24-28
public function searchUsers ( ? string $needle )
{
return WirechatUserResource :: collection (
$this -> runSearchCallback ( $needle )
);
}
Search in Conversations List
The conversation list automatically applies search when the user types:
// src/Livewire/Chats/Chats.php:188-192
public function updatedSearch ( $value )
{
$this -> conversations = []; // Clear previous results
$this -> reset ([ 'page' , 'canLoadMore' ]);
}
Search Behavior
Empty Search
When search is empty, conversations are filtered to exclude blanks and deleted chats: -> when ( trim ( $this -> search ?? '' ) == '' , function ( $query ) {
return $query -> withoutDeleted () -> withoutBlanks ();
})
Active Search
When searching, deleted conversations are included in results: -> when ( trim ( $this -> search ?? '' ) != '' , fn ( $query ) =>
$this -> applySearchConditions ( $query )
)
Advanced User Search
Implement complex search logic:
Panel :: make ( 'admin' )
-> searchUsersUsing ( function ( string $search ) {
$currentUser = auth () -> user ();
return User :: query ()
// Search by name, email, username
-> where ( function ( $q ) use ( $search ) {
$q -> where ( 'name' , 'like' , "%{ $search }%" )
-> orWhere ( 'email' , 'like' , "%{ $search }%" )
-> orWhere ( 'username' , 'like' , "%{ $search }%" );
})
// Exclude current user
-> where ( 'id' , '!=' , $currentUser -> id )
// Only active users
-> where ( 'status' , 'active' )
// Order by relevance
-> orderByRaw (
"CASE
WHEN name LIKE ? THEN 1
WHEN username LIKE ? THEN 2
WHEN email LIKE ? THEN 3
ELSE 4
END" ,
[ "{ $search }%" , "{ $search }%" , "{ $search }%" ]
)
-> limit ( 20 )
-> get ();
})
Searching with Relationships
Include related data in search:
Panel :: make ( 'admin' )
-> searchUsersUsing ( function ( string $search ) {
return User :: with ([ 'profile' , 'department' ])
-> where ( function ( $q ) use ( $search ) {
$q -> where ( 'name' , 'like' , "%{ $search }%" )
// Search in relationships
-> orWhereHas ( 'department' , function ( $dq ) use ( $search ) {
$dq -> where ( 'name' , 'like' , "%{ $search }%" );
})
-> orWhereHas ( 'profile' , function ( $pq ) use ( $search ) {
$pq -> where ( 'bio' , 'like' , "%{ $search }%" );
});
})
-> limit ( 20 )
-> get ();
})
Column Existence Check
WireChat safely checks for column existence before searching:
// src/Livewire/Chats/Chats.php:326-332
protected function columnExists ( $table , $field , & $columnCache )
{
if ( ! isset ( $columnCache [ $table ])) {
$columnCache [ $table ] = Schema :: getColumnListing ( $table );
}
return in_array ( $field , $columnCache [ $table ]);
}
Column existence is cached per request to improve performance when searching across multiple fields.
Optimize search for better performance:
Add Database Indexes
// In a migration
Schema :: table ( 'users' , function ( Blueprint $table ) {
$table -> index ( 'name' );
$table -> index ( 'email' );
$table -> index ( 'username' );
// Full-text search (MySQL 5.7+)
$table -> fullText ([ 'name' , 'email' , 'username' ]);
});
Use Full-Text Search
Panel :: make ( 'admin' )
-> searchUsersUsing ( function ( string $search ) {
return User :: query ()
-> whereFullText ([ 'name' , 'email' , 'username' ], $search )
-> limit ( 20 )
-> get ();
})
Implement Search Service
For large-scale applications, use dedicated search services:
use Laravel\Scout\ Searchable ;
class User extends Model
{
use Searchable ;
public function toSearchableArray ()
{
return [
'name' => $this -> name ,
'email' => $this -> email ,
'username' => $this -> username ,
];
}
}
// In panel configuration
Panel :: make ( 'admin' )
-> searchUsersUsing ( function ( string $search ) {
return User :: search ( $search )
-> take ( 20 )
-> get ();
})
Disable Search
To disable search functionality:
Panel :: make ( 'admin' )
-> chatsSearch ( false ) // Disable conversation search
Search UI Behavior
Real-time Search Search results update as users type in the search field
Deleted Conversations Deleted chats appear in search results for easy recovery
Pagination Reset Search automatically resets pagination to show fresh results
Empty State Clear feedback when no results match the search query
Testing Search
Test your search implementation:
use App\Models\ User ;
/** @test */
public function it_searches_users_by_name ()
{
$user1 = User :: factory () -> create ([ 'name' => 'John Doe' ]);
$user2 = User :: factory () -> create ([ 'name' => 'Jane Smith' ]);
$user3 = User :: factory () -> create ([ 'name' => 'Bob Johnson' ]);
$panel = Wirechat :: panel ( 'admin' );
$results = $panel -> searchUsers ( 'John' );
$this -> assertCount ( 2 , $results );
$this -> assertTrue ( $results -> contains ( 'id' , $user1 -> id ));
$this -> assertTrue ( $results -> contains ( 'id' , $user3 -> id ));
}
Best Practices
Limit Results Always limit search results (e.g., 20 users) for performance
Add Indexes Create database indexes on searchable fields
Case Sensitivity Use case-insensitive search with LIKE or ILIKE
Exclude Current User Remove the authenticated user from user search results
Next Steps
Private Chats Start conversations from search results
Theming Customize the search interface appearance
User Setup Configure user model for search
Permissions Control who can search and create conversations