PHPackages                             tmsperera/headless-chat - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. tmsperera/headless-chat

ActiveLibrary[Queues &amp; Workers](/categories/queues)

tmsperera/headless-chat
=======================

Integrate chat on Laravel applications.

0.8.5(1y ago)425[3 PRs](https://github.com/tmsperera/headless-chat/pulls)MITPHPPHP ^8.2

Since Mar 21Pushed 1y ago1 watchersCompare

[ Source](https://github.com/tmsperera/headless-chat)[ Packagist](https://packagist.org/packages/tmsperera/headless-chat)[ Patreon](https://patreon.com/tmsperera)[ RSS](/packages/tmsperera-headless-chat/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (5)Versions (20)Used By (0)

💬 Headless Chat for Laravel
===========================

[](#-headless-chat-for-laravel)

A flexible, customizable and headless package designed to integrate chat functionality into Laravel applications.

Why Headless Chat?
==================

[](#why-headless-chat)

- Models and database tables can be overridden
- Uses Actions resolved from Service Container

Contents
========

[](#contents)

- [Installation](#installation)
- [Usage](#usage)
    - [Send a direct message](#send-a-direct-message)
    - [Reply to a message](#reply-to-a-message)
    - [Mark message as read](#mark-message-as-read)
    - [Delete a sent message](#delete-a-sent-message)
    - [Get conversations](#get-conversations)
    - [Get conversations with metrics](#get-conversations-with-metrics)
    - [Get unread conversation count](#get-unread-conversation-count)
    - [Group Messages](#group-messages)
        - [Create a group conversation](#create-a-group-conversation)
        - [Join a group conversation](#join-a-group-conversation)
        - [Send message to a group conversation](#send-message-to-a-group-conversation)
- [Advanced Usage](#advanced-usage)
    - [Override Models](#override-models)
    - [Override Actions](#override-actions)

Installation
============

[](#installation)

1. Install the package via composer.

    ```
    composer require tmsperera/headless-chat

    ```

    > ℹ️ Package will automatically register itself.
2. Publish migrations and config using:

    ```
    php artisan vendor:publish --tag=headless-chat

    ```

    > ℹ️ To publish only migrations:
    >
    > ```
    > php artisan vendor:publish --tag=headless-chat-migrations
    >
    > ```

    > ℹ️ To publish only configurations:
    >
    > ```
    > php artisan vendor:publish --tag=headless-chat-config
    >
    > ```
3. Run migrations.

    ```
    php artisan migrate

    ```
4. Implement your "User" Model from [Participant](%5BChatable%5D(/src/Contracts/Participant.php)) contract.

    ```
    use TMSPerera\HeadlessChat\Contracts\Participant;

    class User extends Model implements Participant
    {
        ...
    }
    ```

    > ℹ️ Any Eloquent Model can be used as a Participant
5. Use [Chatable](/src/Traits/Chatable.php) trait in User Model.

    ```
    use TMSPerera\HeadlessChat\Contracts\Participant;
    use TMSPerera\HeadlessChat\Traits\Chatable;

    class User extends Model implements Participant
    {
        use Chatable;
        ...
    }
    ```

Usage
=====

[](#usage)

Having [Chatable](/src/Traits/Chatable.php) trait inside the User model gives you important abilities. And also this package provides standalone [Actions](/src/Actions) to use anywhere your application needs.

Feel free to refer source code to have a better understanding

- [/src/Contracts/Participant.php](/src/Contracts/Participant.php)
- [/src/Traits/Chatable.php](/src/Traits/Chatable.php)
- [/src/HeadlessChat.php](/src/HeadlessChat.php)
- [/src/Actions](/src/Actions)

Send a direct message
---------------------

[](#send-a-direct-message)

Sends a message using the chat package.

### Example:

[](#example)

```
use TMSPerera\HeadlessChat\DataTransferObjects\MessageDto;

$sender = User::query()->find(1);
$recipient = User::query()->find(2);

$message = $sender->createDirectMessage(
    recipient: $recipient,
    messageDto: new MessageDto(
        type: 'text',
        content: 'Hello!',
        metadata: [ 'foo' => 'bar' ],
    ),
);
```

### Signature:

[](#signature)

```
/**
 * @throws InvalidParticipationException
 */
public function createDirectMessage(
    Participant $recipient,
    MessageDto $messageDto,
): Message;
```

Reply to a message
------------------

[](#reply-to-a-message)

Headless Chat also supports message replies.

### Example:

[](#example-1)

```
use TMSPerera\HeadlessChat\DataTransferObjects\MessageDto;

$sender = User::query()->find(1);
$message = $sender->conversations->messages->first();

$sender->createReplyMessage(
    parentMessage: $message,
    messageDto: new MessageDto(
        type: 'text',
        content: 'Reply Message',
        metadata: [ 'foo' => 'bar' ],
    ),
);
```

### Signature:

[](#signature-1)

```
/**
 * @throws InvalidParticipationException
 */
public function createReplyMessage(
    Message $parentMessage,
    MessageDto $messageDto,
): Message;
```

Mark message as read
--------------------

[](#mark-message-as-read)

Marks a message as read.

### Example:

[](#example-2)

```
$sender = User::query()->find(1);
$message = $sender->conversations->messages->first();
$recipient = User::query()->find(2);

$recipient->readMessage($message);
```

### Signature:

[](#signature-2)

```
/**
 * @throws ReadBySenderException
 * @throws InvalidParticipationException
 * @throws MessageAlreadyReadException
 */
public function readMessage(Message $message): ReadReceipt;
```

Delete a sent message
---------------------

[](#delete-a-sent-message)

Delete a message sent by a Participant.

### Example:

[](#example-3)

```
$sender = User::query()->find(1);
$message = $sender->conversations->messages->first();

$sender->deleteSentMessage($message);
```

### Signature:

[](#signature-3)

```
/**
 * @throws InvalidParticipationException
 * @throws MessageOwnershipException
 */
public function deleteSentMessage(Message $message): void;
```

Get conversations
-----------------

[](#get-conversations)

Conversations for a particular Participant can be accessed by an Eloquent Relationship.

### Example:

[](#example-4)

```
$sender = User::query()->find(1);

$sender->conversations;
```

### Signature:

[](#signature-4)

```
public function conversations(): BelongsToMany;
```

Get conversations with metrics
------------------------------

[](#get-conversations-with-metrics)

Just as conversations, you also can retrieve conversations with useful metrics using `conversationsWithMetrics` relation.

### Example:

[](#example-5)

```
$sender = User::query()->find(1);

$sender->conversationsWithMetrics;
```

### Signature:

[](#signature-5)

```
public function conversationsWithMetrics(): BelongsToMany;
```

### Returns

[](#returns)

`conversationsWithMetrics` will return a collection of Conversations with each Conversation including special attributes which are...

- `total_message_count`: Total messages for Conversation
- `read_message_count`: Total **read** messages for Conversation
- `unread_message_count`: Total **unread** messages for Conversation
- `latest_message_at`: Created at of the latest message for Conversation

Get unread conversation count
-----------------------------

[](#get-unread-conversation-count)

Returns count of unread conversations for a Participant.

### Example:

[](#example-6)

```
$sender = User::query()->find(1);

$sender->getUnreadConversationCount();
```

### Signature:

[](#signature-6)

```
public function getUnreadConversationCount(): int;
```

Group Messages
--------------

[](#group-messages)

Headless Chat package is designed to support group chats. Here is how to create group chat...

### Create a group conversation

[](#create-a-group-conversation)

```
use TMSPerera\HeadlessChat\HeadlessChat;

$user1 = User::query()->find(1);
$user2 = User::query()->find(1);

$conversation = HeadlessChat::createConversation(
    participants: [$user1, $user2],
    conversationDto: new ConversationDTO(
        conversationType: ConversationType::GROUP,
    ),
);
```

#### Signature:

[](#signature-7)

```
/**
 * @throws ParticipationLimitExceededException
 */
public static function createConversation(
    array $participants,
    ConversationDto $conversationDto,
): Conversation;
```

### Join a group conversation

[](#join-a-group-conversation)

```
$user3 = User::query()->find(3);
$conversation = Conversation::query()->find(1);

$participation = $user3->joinConversation($conversation);
```

#### Signature:

[](#signature-8)

```
/**
 * @throws ParticipationLimitExceededException
 * @throws ParticipationAlreadyExistsException
 */
public function joinConversation(
    Conversation $conversation,
    array $participationMetadata = [],
): Participation;
```

### Send message to a group conversation

[](#send-message-to-a-group-conversation)

```
use TMSPerera\HeadlessChat\DataTransferObjects\MessageDto;

$sender = User::query()->find(1);
$conversation = Conversation::query()->find(1);

$message = $sender->createMessage(
    conversation: $conversation,
    messageDto: new MessageDto(
        type: 'text',
        content: 'Hello!',
        metadata: [ 'foo' => 'bar' ],
    ),
);
```

#### Signature:

[](#signature-9)

```
/**
 * @throws InvalidParticipationException
 */
public function createMessage(
    Conversation $conversation,
    MessageDto $messageDto,
): Message;
```

Advanced Usage
==============

[](#advanced-usage)

Override Models
---------------

[](#override-models)

Some applications may not be able to use the default database tables provided by Headless Chat package. In such cases you can swap the database tables or even models to be used by this package.

To swap a database table or model used in package follow the below steps:

1. Publish Headless Chat configurations using.

    ```
    php artisan vendor:publish --tag=headless-chat-config

    ```
2. Modify the published migrations in `create_headless_chat_tables.php` to set custom database table name and foreign key constrains.

    ```
    // Schema::create('messages', function (Blueprint $table) {
    Schema::create('custom_messages', function (Blueprint $table) {
        ...
    });

    Schema::create('read_receipts', function (Blueprint $table) {
       ...
       $table->foreignId('message_id')
          // ->constrained(table: 'messages', column: 'id');
          ->constrained(table: 'custom_messages', column: 'id');
       ...
    });
    ```
3. Create new custom Model extending from the [Models](/src/Models) defined in Headless Chat package.

    ```
    use TMSPerera\HeadlessChat\Models\Message;

    class CustomMessage extends Message
    {
        protected $table = 'custom_messages';
    }
    ```

    > ⚠️ You need to keep relationship names same as in Headless Chat Models in order to function the package. However, the referenced column names of relationships can be modified as per your custom database table columns.
4. Modify `config/headless-chat.php` to point the new model.

    ```
    return [
        'models' => [
            'message' => App\Models\CustomMessage::class,
            ...
        ],
        ...
    ];
    ```

💡 Ultimately, the models are resolved from Laravel Service Container, so you can also override the Model class inside the `register` method of your `AppServiceProvider` instead of modifying or even publishing the `headless-chat` config just as below.

```
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Models\CustomMessage;
use TMSPerera\HeadlessChat\Models\Message;

class AppServiceProvider extends ServiceProvider
{
      public function register(): void
      {
          $this->app->bind(Message::class, function ($app) {
              return $app->make(CustomMessage::class);
          });
      }
}
```

Override Actions
----------------

[](#override-actions)

All actions used inside Headless Chat package are resolved from Laravel Service Container. If you ever need to modify the behaviour of any Action used in Headless Chat package, you can add a binding inside `register` method of your `AppServiceProvider`.

```
namespace App\Providers;

use App\Actions\CustomSendDirectMessageAction;
use Illuminate\Support\ServiceProvider;
use TMSPerera\HeadlessChat\Actions\CreateDirectMessageAction;

class AppServiceProvider extends ServiceProvider
{
      public function register(): void
      {
          $this->app->bind(CreateDirectMessageAction::class, function ($app) {
              return $app->make(CustomSendDirectMessageAction::class);
          });
      }
}
```

References
==========

[](#references)

- [Headless Chat - Packagist](https://packagist.org/packages/tmsperera/headless-chat)

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance49

Moderate activity, may be stable

Popularity11

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~3 days

Total

16

Last Release

369d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8e4462c3986b4d02aee4445d61aee63678527664beb7f1551fe7196e8d4a53d7?d=identicon)[tmsperera](/maintainers/tmsperera)

---

Top Contributors

[![tmsperera](https://avatars.githubusercontent.com/u/26657051?v=4)](https://github.com/tmsperera "tmsperera (249 commits)")

---

Tags

messagelaravelpackageheadlessmessagingchatchattingtmsperera

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/tmsperera-headless-chat/health.svg)

```
[![Health](https://phpackages.com/badges/tmsperera-headless-chat/health.svg)](https://phpackages.com/packages/tmsperera-headless-chat)
```

###  Alternatives

[nahid/talk

Talk is a Laravel based realtime messaging, chatting and conversation system. It helps to develop users messaging, chatting and conversations in easy way.

1.6k58.1k4](/packages/nahid-talk)[convenia/pigeon

3233.0k](/packages/convenia-pigeon)[arcanedev/laravel-messenger

Simple messaging system for Laravel

891.5k](/packages/arcanedev-laravel-messenger)[baklysystems/laravel-chat-messenger

Laravel chat package

121.8k](/packages/baklysystems-laravel-chat-messenger)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
