A Laravel chat package. You can use this package to create a chat/messaging Laravel application.

Overview

chat

Build Status Downloads Packagist

Chat

Create a Chat application for your multiple Models

Table of Contents

Click to expand

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

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;
}

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.

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();

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();

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();

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()

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();

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()

Get participants in a conversation

$participants = $conversation->getParticipants();

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.

License

Chat is open-sourced software licensed under the MIT license

Comments
  • musonza send message issue

    musonza send message issue

    Hi sir

    i am beginner and i am install this plugin step by step. but creating message function "createConversation" but this function return required fields. i am searching in google but not any find solution.

    Any one help me step by step .

    opened by guptanand 15
  • Facade Not Found

    Facade Not Found

    I installed the package, placed the Alias and ServiceProvider in config/app.php and I am getting the following error.

    Class 'Musonza\Chat\Facades\ChatFacade::class' not found

    This is happening in the browser and PHPUnit tests when using a method on the Chat facade.

    opened by c-fitzmaurice 15
  • Conversation with hundreds of participants cause error on mass insert: Prepared statement contains too many placeholders

    Conversation with hundreds of participants cause error on mass insert: Prepared statement contains too many placeholders

    Describe the bug One of conversation has ~20k participants and when new message is added, the conversation generator crash with this mysql error: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders

    To Reproduce Steps to reproduce the behavior:

    1. Normal instalation
    2. Add conversation
    3. Add hundreds of thousands of participants
    4. Create a message and see the error: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders

    Expected behavior No error and all notifications created.

    Screenshots image image

    I need to refactor this createCustomNotifications method on src/Models/MessageNotification.php:

    public static function createCustomNotifications($message, $conversation)
        {
            $notification = [];
    
            foreach ($conversation->participants as $participation) {
                $is_sender = ($message->participation_id == $participation->id) ? 1 : 0;
    
                $notification[] = [
                    'messageable_id'   => $participation->messageable_id,
                    'messageable_type' => $participation->messageable_type,
                    'message_id'       => $message->id,
                    'participation_id' => $participation->id,
                    'conversation_id'  => $conversation->id,
                    'is_seen'          => $is_sender,
                    'is_sender'        => $is_sender,
                    'created_at'       => $message->created_at,
                ];
            }
    
            self::insert($notification);
        }
    

    How I do?

    My idea: or chunk participant list in support number of MySQL, or work with jobs, sending the responsability to queue.

    opened by silasrm 11
  • Adds ability to use any Laravel model as Chat participant

    Adds ability to use any Laravel model as Chat participant

    Checklist

    • [x] Ability to use any Laravel model as participant :zap:
    • [x] Update package readme, functions, tables, Models to not refer participants as users
    • [x] Add tests with different Model types as participants. Passing right now because there is one Model type in use
    • [x] Direct Messaging instead of referring to it as private
    • [x] Package routes
    • [x] Conversation settings for participant (example: mute_mentions, mute_conversation)
    • [x] Fire additional events (ConversationStarted, ParticipantJoined, ParticipantLeft)
    • [x] Model Transformers
    • [x] https://github.com/musonza/chat/issues/104
    • [x] https://github.com/musonza/chat/issues/165
    • [ ] https://github.com/musonza/chat/issues/65

    Demo https://github.com/musonza/chat-demo/tree/multiple-model-recipients

    Release Candidate https://github.com/musonza/chat/releases/tag/v4.0.0-rc6

    enhancement feature 
    opened by musonza 10
  • How can i setup pusher with your demo?

    How can i setup pusher with your demo?

    Hii @musonza

    I have one query regarding your demo example. I have setup in local system and working very well but this is not real time messaging system. This is look like page refresh and normal ajax or vue post request.

    So how can i make this demo to real time messaging system. If you have real time message system demo then you can share me.

    Please explain if possible then how can convert your demo example to real time messaging system.

    Can we add socket type setting to make real time system in your package of chatting? Do you thing about it?

    Thanks for demo.

    opened by bhavin-zwt 9
  • MessageWasSent event not working

    MessageWasSent event not working

    #66 Hello, I have:

    Broadcast::channel('mc-chat-conversation.{conversation_id}', function($user) { return $user; });

    App.js:

    mounted() { Echo.private('mc-chat-conversation.' + this.convId) .listen('MessageWasSent', (e) => { console.log(e); this.chat.message.push(e.message); this.chat.user.push(e.user); this.chat.time.push(this.getTime()); console.log(e); }) .listenForWhisper('typing', (e) => { if(e.name != '') this.typing = 'НабираСт сообщСниС..'; else this.typing = null; }); }

    Controller:

    broadcast(new MessageWasSent($message))->toOthers();

    But event not received data to other user, why??? console.log(e) get empty result.

    I think, that event MessageWasSent not know, that need send message to other user. He can only receive a message? Why??

    opened by ExsyDev 8
  • Need for 'data' column in message table

    Need for 'data' column in message table

    A column ('data') to store details about each message was added. For instance, if our message type is an image, we can add the image link, or if it is a link we can store the link and attachment details in it. The conversation table already has this column, I think there is a need for this in the message table too.

    opened by azimi-ali 7
  • getMessages() returns only 25 messages but I need all

    getMessages() returns only 25 messages but I need all

    Hi, great work

    But here I faced an issue, when I try to get all messages for user Chat::conversation($conversation)->setUser($user)->getMessages() I get only 25 of them.

    In your ConversationService class getMessages method there is no way to pass any paginate params. I don't know is it bug or not but is there are a way to fetch all the messages for user? Thank you

    opened by gomer1996 7
  • Mark message is read function

    Mark message is read function

    I have function:

    public function setMessagesSeen(Conversation $conversation, Request $request) {
    $v = Validator::make($request->all(), [
        'message' => 'required|string|max:4000',
    ]);
    
    $user = User::find(Auth::id());
    
    $conversations = Chat::conversation($conversation->id);
    
    //$message = Chat::conversations($conversations)->for($user)->getMessages()->where('body', $request->message)->where('user_id', '<>', $user->id);
    
    //$message->markRead();
    
    //var_dump($message); exit;
    
    broadcast(new MessageIsSeen($message));
    
    return response('ok'); }
    

    I have a post request:

    methods: {
        seenMessage() {
            if(this.message.length != 0) {
                axios.post('/setMessagesSeen/' + this.convId, {
                    message: this.message,
                })
                .then( response => { $('li').removeClass('unread'); }) 
                .catch( response => { console.log(response) } )
            }
    },
    

    How I can correctly read message for users? I need add/remove class to div in app.js, when message is readed for user. But how check this and mark correctly read message, I need message id?

    opened by ExsyDev 7
  • Getting SQL error

    Getting SQL error

    Hi Musonza,

    I am getting an sql error when I used the getMessages method.

    my code ::

    public function chats() { $currentuser = Auth::user();

    		$conversations = Chat::getConversationBetween($currentuser, 1);
    
    		$messages = Chat::conversations()->for($currentuser)->limit(25)->page(1)->get();
    
    		//return view('chats',['conversation' => $conversations, 'messages' => $messages]);
    
    		//return $messages;
    }
    

    it shows the below error ::

    Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '>'$."message_id"' = mc_messages.id where mc_messages.conversation_id in ' at line 1 (SQL: select notifications., mc_messages. from mc_messages inner join notifications on notifications.data->'$."message_id"' = mc_messages.id where mc_messages.conversation_id in (1) order by mc_messages.id desc)

    Please Suggest me something :)

    opened by jayant1993 7
  • How I can start conversation with oneself but before that check if there already conversation exists?

    How I can start conversation with oneself but before that check if there already conversation exists?

    Could you please explain how I can start conversation with oneself with existing structure of the table (but before that check if there is already conversation with oneself)? Also before starting conversation with oneself I have already other conversations.

    question 
    opened by siarheipashkevich 7
  • how to get conversations with unreadCount

    how to get conversations with unreadCount

    How can I add unreadCount to

    $chats =   Chat::conversations()->setPaginationParams([
                'page' => request()->get('page', 1),
                'perPage' => 10,
                'sorting' => "desc",
                'columns' => [
                    '*'
                ],
            ])
                ->setParticipant(request()->user())
                ->get();
    
    
    opened by samehdoush 1
  • $conversation = Chat::conversations()->between($participantModel1, $participantModel2); is not work

    $conversation = Chat::conversations()->between($participantModel1, $participantModel2); is not work

    I try

    $user1 = User::find(1); $user2 = User::find(2); $conversation = Chat::conversations()->between($user1, $user2); return $conversation;

    in my controller

    opened by tayzapd 2
  • Make connection on models configurable

    Make connection on models configurable

    This allows developers to override default connection on package models by adding a key of database_connection in config/musonza_chat.php. I would like to use this in a project I am working on right now but I am unable to because I need to use a different database connection from the default. This change will not affect existing applications already using the default connection. No configuration changes are need for migrations, one can simply pass --database[=DATABASE] at the time of migration.

    Please accept my pull request so that I may use this package. Thank you!

    opened by inmanturbo 0
  • Method ConversationService::common() does not exist

    Method ConversationService::common() does not exist

    According to the documentation, you can Get common conversations among participants using:

    $conversations = Chat::conversations()->common($participants);
    

    But that method doesn't exist.

    Steps to reproduce the behavior:

    $participants = [$model1, $model2];
    $conversations = Chat::conversations()->common($participants);
    

    Expected behavior Return a list of conversations between $model1 and $model2.

    Additional context The between() method could be used for this, however, that method only works for 2 models and conversations that are private.

    opened by mooxnl 1
  • Get all participant Models that a Model ever had a conversation with

    Get all participant Models that a Model ever had a conversation with

    I'm trying to retrieve a list of all the Models (participants) that a certain Model ever had a conversation with.

    My chat screen has 3 columns:

    1. list of contacts (grouped, so each contact is displayed only once and sorted by latest message first)
    2. list of conversations with the selected contact
    3. messages inside the selected conversation

    My question is regarding the first column. Is this possible?

    I tried it with this query to get all participants for User with id 1, which works, but doesn't group the participants:

    Musonza\Chat\Models\Conversation::query()
        ->whereHas('participants', function($query) {
            $query->whereHasMorph(
                'messageable',
                [User::class],
                function ($query) {
                    $query->where('id', 1);
                })
                ->groupBy(['messageable_type', 'messageable_id']);
        })
        ->get()
    
    opened by mooxnl 0
Releases(v6.0.1)
Owner
Tinashe Musonza
Tinashe Musonza
Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud Messaging (FCM).

Laravel-FCM Introduction Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud M

Rahul Thapa 2 Oct 16, 2022
Collection of classes you can use to standardize data formats in your Laravel application.

Laravel Formatters This package is a collection of classes you can use to standardize data formats in your Laravel application. It uses the Service Co

Michael Rubel 88 Dec 23, 2022
Foreman is a Laravel scaffolding application that automates common tasks you typically perform with each new Laravel app you create

Foreman is a Laravel scaffolding application that automates common tasks you typically perform with each new Laravel app you create. The directives you want Forman to perform are outlined in a JSON based template file.

Indatus 145 Apr 13, 2022
Simple user messaging package for Laravel

Laravel Messenger This package will allow you to add a full user messaging system into your Laravel application. Leave some feedback How are you using

Chris Gmyr 2.3k Dec 29, 2022
Migrator is a GUI migration manager for Laravel which you can create, manage and delete your migration.

Migrator Migrator is a GUI migration manager for Laravel which you can create, manage and delete your migration. Installation: To install Migrator you

Reza Amini 457 Jan 8, 2023
you can use this package with your develop operation....

Laravel Debugbar This is a package to integrate PHP Debug Bar with Laravel. It includes a ServiceProvider to register the debugbar and attach it to th

Eng Hasan Hajjar 2 Sep 30, 2022
If you are beginner in WordPress plugin development or if you want to develop your own store product plugin you use this plugin

hirwa-products-plugin If you are beginner in WordPress plugin development or if you want to develop your own store product plugin you use this plugin

NIYIBIZI HIRWA 1 Aug 23, 2022
Laravel Rocket chat Debugher, push all logs to rocket chat channels

Laravel Rocket chat Debugher, push all logs to rocket chat channels

Novaday 4 Jun 13, 2022
Talk is a real-time users messaging and chatting system Laravel.

Laravel-Talk Talk is a Laravel 5 based user conversation (inbox) system with realtime messaging. You can easily integrate this package with any Larave

Nahid Bin Azhar 1.5k Dec 30, 2022
Shoutout messaging library for laravel

Laravel Shoutout Messaging Shoutout messaging library for Laravel Laravel PHP framework Shoutout Messaging Requirements PHP 5.6+ Laravel 5.5+ Installa

Dasun Dissanayake 12 Jul 17, 2022
Manage your staff from one place. Featuring Staff leave management πŸ–, payslips πŸ’΅ generation & emailing, messaging πŸ“¨and more πŸ› ! Built with ❀️ with Laravel

Staff Management System This little buddy can help you manage your staff database! Built with ?? with Laravel #FEATURES 1 Staff management/ database S

Ezekiel Oladejo 45 Jan 3, 2023
Aliyun oss filesystem storage adapter for laravel 5. You can use Aliyun OSS just like laravel Storage as usual

Aliyun oss filesystem storage adapter for laravel 5. You can use Aliyun OSS just like laravel Storage as usual

jacob 517 Dec 29, 2022
A Laravel package that allows you to use multiple ".env" files in a precedent manner. Use ".env" files per domain (multi-tentant)!

Laravel Multi ENVs Use multiple .envs files and have a chain of precedence for the environment variables in these different .envs files. Use the .env

Allyson Silva 48 Dec 29, 2022
🐍 Web application made in PHP with Laravel where you can interact via API with my Snake game which is made in Python

Snake web application Project of the web application where you can interact via API with Snake game which is available to download on it. Application

Maciek Iwaniuk 1 Nov 26, 2022
Blacksmith is a code generation tool which automates the creation of common files that you'd typically create for each entity in your application.

Blacksmith is a code generation tool which automates the creation of common files that you'd typically create for each entity in your application.

Indatus 197 Dec 30, 2022
This package can use form request just as Laravel do.

Lumen Form Request This package can use form request just as Laravel do. Installation Install by composer $ composer require chhw/form-request In

null 2 Nov 17, 2021
Navigator is a package to create headless navigation menus for use in Laravel applications

Navigator Navigator is a package to create headless navigation menus for use in Laravel applications: // In a Service Provider Nav::define(fn ($user)

Sam Rowden 36 Oct 30, 2022
this package can help you to test race condition in Laravel Feature Test

Laravel Async Testing this package can help you to test race condition in Laravel Feature Test Requirements Laravel versions 5.7, 6.x, 7.x and 8.x PHP

Recca Tsai 61 Nov 5, 2022
This package enables you to create and run a fully functioning WebSocket server in your Laravel app.

This package enables you to create and run a fully functioning WebSocket server in your Laravel app. It can optionally receive messages broadcast over ZeroMQ.

Asked.io 181 Oct 6, 2022