musonza/chat
Composer 安装命令:
composer require musonza/chat
包简介
Chat Package for Laravel
README 文档
README
Chat
Create a Chat application for your multiple Models
What to learn how to make a package like this? https://leanpub.com/laravel-package-development
Table of Contents
- Introduction
- Installation
- Usage
- Adding the ability to participate to a Model
- Enable the routes
- Get participant details
- Creating a conversation
- Creating a named conversation
- Get a conversation by Id
- Update conversation details
- Send a text message
- Send a message of custom type
- Get a message by id
- Get message sender
- Mark a message as read
- Mark whole conversation as read
- Unread messages count
- Delete a message
- Message Reactions
- Cleanup Deleted Messages
- Clear a conversation
- Get participant conversations
- Get a conversation between two participants
- Get common conversations among participants
- Remove participants from a conversation
- Add participants to a conversation
- Get messages in a conversation
- Filter messages by type
- Get messages with cursor pagination
- Filter conversations by name
- Get public conversations for discovery
- Get recent messages
- Get participants in a conversation
- Get all conversation partners
- Get participation entry for a Model in a conversation
- Update participation settings
- Data Transformers
- Message Encryption
- License
Checkout a simple Demo Application
Introduction
This package allows you to add a chat system to your Laravel ^5.4 application
Installation
From the command line, run:
composer require musonza/chat
Publish the assets:
php artisan vendor:publish --provider="Musonza\Chat\ChatServiceProvider"
This will publish database migrations and a configuration file musonza_chat.php in the Laravel config folder.
Configuration
See musonza_chat.php for configuration
Run the migrations:
php artisan migrate
Usage
You can mix Models as participants. For instance you can have Parents, Students and Professors models communicating
Adding the ability to participate to a Model
Add the Musonza\Chat\Traits\Messageable trait to any Model you want to participate in Conversations
For example, let's say we want out Bot model to chat with other Models:
use Illuminate\Database\Eloquent\Model; use Musonza\Chat\Traits\Messageable; class Bot extends Model { use Messageable; }
Enable the routes
The package includes routes for conversations, conversation participants, and messaging. These routes are hidden by default. To enable them, change should_load_routes to true, but make sure to configure the middleware correctly.
Get participant details
Since we allow Models with data that differ in structure to chat, we may want a uniform way to represent the participant details in a uniform way.
You can get the details as follows:
$participantModel->getParticipantDetails();
Assuming you have a column name for your model, this returns a default array ['name' => 'column_value']
You can however, customize this for your needs by adding an Eloquent Accessor that returns an array
with as much as you need to your model as follows:
public function getParticipantDetailsAttribute() { return [ 'name' => $this->someValue, 'foo' => 'bar', ]; }
Creating a conversation
You can start a conversation by passing an array of Models as participants
$participants = [$model1, $model2,..., $modelN]; $conversation = Chat::createConversation($participants);
Creating a conversation of type private / public
You may want to classify conversations as private or public
$participants = [$model1, $model2,..., $modelN]; // Create a private conversation $conversation = Chat::createConversation($participants)->makePrivate(); // Create a public conversation $conversation = Chat::createConversation($participants)->makePrivate(false); // Create a direct message // Make direct conversation after creation $conversation = Chat::createConversation($participants)->makeDirect(); // Specify intent for direct conversation before creation $conversation = Chat::makeDirect()->createConversation($participants);
Note: You will not be able to add additional participants to a direct conversation. Additionally you can't remove a participant from a direct conversation.
Creating a named conversation
You can assign a name to a conversation, which is useful for chatrooms or any scenario where you need to look up a conversation by a human-readable identifier.
$participants = [$model1, $model2]; // Create a named conversation $conversation = Chat::createConversation($participants, [], 'general'); // The name is accessible on the conversation echo $conversation->name; // 'general'
The name column is nullable, so existing conversations and conversations created without a name are unaffected.
Get a conversation by id
$conversation = Chat::conversations()->getById($id);
Update conversation details
$data = ['title' => 'PHP Channel', 'description' => 'PHP Channel Description']; $conversation->update(['data' => $data]);
Send a text message
$message = Chat::message('Hello') ->from($model) ->to($conversation) ->send();
Send a message of custom type
The default message type is text. If you want to specify custom type you can call the type() function as below:
$message = Chat::message('http://example.com/img') ->type('image') ->from($model) ->to($conversation) ->send();
To add more details about a message
Sometimes you might want to add details about a message. For example, when the message type is an attachment, and you want to add details such as attachment's filename, and attachment's file url, you can call the data() function and pass your data as an array.
$message = Chat::message('Attachment 1') ->type('attachment') ->data(['file_name' => 'post_image.jpg', 'file_url' => 'http://example.com/post_img.jpg']) ->from($model) ->to($conversation) ->send();
Get a message by id
$message = Chat::messages()->getById($id);
Get message sender
$sendModel = $message->sender;
Mark a message as read
Chat::message($message)->setParticipant($participantModel)->markRead();
Flag / mark a message
Chat::message($message)->setParticipant($participantModel)->toggleFlag(); Chat::message($message)->setParticipant($participantModel)->flagged(); // true
Mark whole conversation as read
Chat::conversation($conversation)->setParticipant($participantModel)->readAll();
Unread messages count
$unreadCount = Chat::messages()->setParticipant($participantModel)->unreadCount();
Unread messages count per Conversation
Chat::conversation($conversation)->setParticipant($participantModel)->unreadCount();
Delete a message
Chat::message($message)->setParticipant($participantModel)->delete();
Message Reactions
Add emoji or text-based reactions to messages:
// Add a reaction Chat::message($message)->setParticipant($participantModel)->react('👍'); // Add multiple different reactions Chat::message($message)->setParticipant($participantModel)->react('❤️');
Remove a reaction:
Chat::message($message)->setParticipant($participantModel)->unreact('👍');
Toggle a reaction (add if not present, remove if present):
$result = Chat::message($message)->setParticipant($participantModel)->toggleReaction('👍'); // $result = ['added' => true/false, 'reaction' => Reaction|null]
Get reactions summary with counts:
$summary = Chat::message($message)->reactionsSummary(); // ['👍' => 5, '❤️' => 3, '😂' => 1]
Check if participant has reacted:
// Check for specific reaction Chat::message($message)->setParticipant($participantModel)->hasReacted('👍'); // Check for any reaction Chat::message($message)->setParticipant($participantModel)->hasReacted();
Get all reactions on a message:
$reactions = Chat::message($message)->reactions();
You can also access reactions directly on the Message model:
$message->reactions; // All reactions $message->getReactionsSummary(); // Grouped counts $message->react($participant, '👍'); // Add $message->unreact($participant, '👍'); // Remove $message->hasReacted($participant, '👍'); // Check
Broadcasting: When broadcasting is enabled, MessageReactionAdded and MessageReactionRemoved events are broadcast to the conversation channel.
Cleanup Deleted Messages
What to cleanup when all participants have deleted a $message or $conversation?
Listen for \Musonza\Chat\Eventing\AllParticipantsDeletedMessage and
\Musonza\Chat\Eventing\AllParticipantsClearedConversation
Clear a conversation
Chat::conversation($conversation)->setParticipant($participantModel)->clear();
Archive a conversation (per participant)
Archiving is per-participant — like Gmail/Outlook — so one user can archive a thread without hiding it for the others. By default, archived conversations are excluded from a participant's listings. A new incoming message auto-unarchives the recipient (configurable).
// Archive / unarchive for a single participant Chat::conversation($conversation)->setParticipant($participantModel)->archive(); Chat::conversation($conversation)->setParticipant($participantModel)->unarchive(); // Or directly on the model $conversation->archive($participantModel); $conversation->unarchive($participantModel); // Default listing excludes archived Chat::conversations()->setParticipant($participantModel)->get(); // Show only archived conversations (e.g. an "Archive" inbox) Chat::conversations()->setParticipant($participantModel)->archived()->get(); // Show both archived and non-archived together Chat::conversations()->setParticipant($participantModel)->withArchived()->get();
To disable auto-unarchive on incoming messages, set unarchive_on_new_message => false in config/musonza_chat.php.
Get participant conversations
Chat::conversations()->setPaginationParams(['sorting' => 'desc']) ->setParticipant($participantModel) ->limit(1) ->page(1) ->get();
Get a conversation between two participants
$conversation = Chat::conversations()->between($participantModel1, $participantModel2);
Get common conversations among participants
$conversations = Chat::conversations()->common($participants);
$participants is an array of participant Models
Remove participants from a conversation
/* removing one user */ Chat::conversation($conversation)->removeParticipants([$participantModel]);
/* removing multiple participants */ Chat::conversation($conversation)->removeParticipants([$participantModel, $participantModel2,...,$participantModelN]);
Add participants to a conversation
/* add one user */ Chat::conversation($conversation)->addParticipants([$participantModel]);
/* add multiple participants */ Chat::conversation($conversation)->addParticipants([$participantModel, $participantModel2]);
Get messages in a conversation
Chat::conversation($conversation)->setParticipant($participantModel)->getMessages()
Filter messages by type
You can filter messages by their type (e.g., text, image, attachment) using the ofType method.
// Get only image messages $messages = Chat::conversation($conversation) ->setParticipant($participant) ->ofType('image') ->getMessages(); // Get only attachment messages $messages = Chat::conversation($conversation) ->setParticipant($participant) ->ofType('attachment') ->getMessages(); // Also works with cursor pagination $messages = Chat::conversation($conversation) ->setParticipant($participant) ->ofType('image') ->getMessagesWithCursor();
Get messages with cursor pagination
For real-time chat applications, cursor-based pagination is recommended over offset-based pagination. This prevents duplicate messages when new messages arrive between page loads.
// Get first page $messages = Chat::conversation($conversation) ->setParticipant($participantModel) ->setCursorPaginationParams([ 'perPage' => 25, 'sorting' => 'asc', ]) ->getMessagesWithCursor(); // Get next page using cursor from previous response $nextCursor = $messages->nextCursor()?->encode(); $moreMessages = Chat::conversation($conversation) ->setParticipant($participantModel) ->setCursorPaginationParams([ 'perPage' => 25, 'sorting' => 'asc', 'cursor' => $nextCursor, ]) ->getMessagesWithCursor();
API Endpoint: GET /conversations/{id}/messages-cursor
Query parameters:
participant_id(required)participant_type(required)perPage(optional, default: 25)sorting(optional:ascordesc)cursor(optional - from previous response'snext_cursor)
The response includes next_cursor and prev_cursor for navigation.
Get user conversations by type
// private conversations $conversations = Chat::conversations()->setParticipant($participantModel)->isPrivate()->get(); // public conversations $conversations = Chat::conversations()->setParticipant($participantModel)->isPrivate(false)->get(); // direct conversations / messages $conversations = Chat::conversations()->setParticipant($participantModel)->isDirect()->get(); // all conversations $conversations = Chat::conversations()->setParticipant($participantModel)->get();
Filter conversations by name
// Filter a participant's conversations by name $conversations = Chat::conversations()->setParticipant($participantModel)->name('general')->get(); // Filter public conversations by name $conversations = Chat::conversations()->isPrivate(false)->name('announcements')->get();
Get public conversations for discovery
You can list public conversations without being a participant. This is useful for building discovery pages where users can browse and join public chat rooms (similar to Telegram public groups).
// Get all public conversations (no participant required) $conversations = Chat::conversations() ->isPrivate(false) ->limit(10) ->page(1) ->get();
Note: This only works for public conversations. Attempting to list private conversations without setting a participant will throw an
InvalidConversationListException.
Get recent messages
$messages = Chat::conversations()->setParticipant($participantModel)->limit(25)->page(1)->get();
Pagination
There are a few ways you can achieve pagination
You can specify the limit and page as above using the respective functions or as below:
$paginated = Chat::conversations()->setParticipant($participant)
->setPaginationParams([
'page' => 3,
'perPage' => 10,
'sorting' => "desc",
'columns' => [
'*'
],
'pageName' => 'test'
])
->get();
You don't have to specify all the parameters. If you leave the parameters out, default values will be used.
$paginated above will return Illuminate\Pagination\LengthAwarePaginator
To get the conversations simply call $paginated->items()
Tip: For paginating messages in real-time chat applications, consider using cursor pagination instead. Cursor pagination prevents duplicate messages when new messages arrive between page loads.
Get participants in a conversation
$participants = $conversation->getParticipants();
Get all conversation partners
Get all unique models that a user has ever been in a conversation with:
// Get all models that a user has ever conversed with $partners = $user->conversationPartners();
This returns a collection of unique models, excluding the user themselves. If the same partner appears in multiple conversations, they will only be included once.
Get participation entry for a Model in a conversation
Chat::conversation($conversation)->getParticipation($model);
Update participation settings
Set Conversation settings for participant (example: mute_mentions, mute_conversation)
$settings = ['mute_mentions' => true]; Chat::conversation($conversation) ->getParticipation($this->alpha) ->update(['settings' => $settings]);
Data Transformers
Need to have more control on the data returned from the package routes? You can specify your own Model transformers and take advantage of Fractal.
All you need to do is specify the location of your transformers in the configuration
file musonza_chat.php as follows:
/** * Model Transformers */ 'transformers' => [ 'conversation' => \MyApp\Transformers\ConversationTransformer::class, 'message' => \MyApp\Transformers\MessageTransformer::class, 'participant' => \MyApp\Transformers\ParticipantTransformer::class, ]
Note: This only applies to responses from package routes.
Message Encryption
You can optionally encrypt message bodies at rest using Laravel's built-in encryption. When enabled, messages are encrypted using AES-256-CBC via Laravel's Crypt facade.
To enable encryption, set the encrypt_messages option in your musonza_chat.php config file:
'encrypt_messages' => true,
How it works:
- New messages are automatically encrypted before being stored in the database
- Messages are automatically decrypted when retrieved via the model
- Existing unencrypted messages remain readable (hybrid mode)
- An
is_encryptedcolumn tracks whether each message is encrypted
// Sending works the same - encryption is transparent $message = Chat::message('Secret message') ->from($user) ->to($conversation) ->send(); // Reading works the same - decryption is automatic echo $message->body; // "Secret message"
Note: Encryption uses your application's
APP_KEY. If you change yourAPP_KEY, previously encrypted messages will become unreadable.
License
Chat is open-sourced software licensed under the MIT license
musonza/chat 适用场景与选型建议
musonza/chat 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 277.99k 次下载、GitHub Stars 达 1.23k, 最近一次更新时间为 2016 年 03 月 18 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「messaging」 「chat」 「laravel」 「conversation」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 musonza/chat 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 musonza/chat 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 musonza/chat 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This simple PHP class allows you to easily generate Smartsupp.com JS chat code.
Client for the REST API plugin of the OpenFire Server
PHP SDK for Mobile Message SMS API
Azure service bus Transport
Official PHP client for NATS messaging system
统计信息
- 总下载量: 277.99k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1240
- 点击次数: 27
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2016-03-18
