In this tutorial, learn how to build a realtime Public Anonymous Group Chat App using Laravel and Pusher.
This blog post was written under the Pusher Guest Writer program.
Socializing with other users has been a trend for past few years and it is not going to go away. Having an anonymous public chat application where we can communicate within a group, put forth our opinions without the fear of leaking our identity could be a great boon to many users.
Today, we will create a realtime Public Anonymous Group Chat App using Laravel and Pusher. With the release of Echo, Laravel has provided an out of the box solution for implementing a realtime chat application using event broadcasting. It is quite simple to get started in a matter of few minutes.
A basic understanding of Laravel and Vue is needed to understand this tutorial.
We need to sign up on Pusher and create a new app.
First, we will grab a fresh copy of Laravel:
laravel new public-anonymous-chat-laravel-pusher
This will install the latest version of the Laravel framework and download the necessary dependencies. Next, we will install the Pusher PHP SDK using Composer:
composer require pusher/pusher-php-server
Next, we will install the JavaScript dependencies:
npm install
Now, we need to install two JavaScript libraries necessary for realtime event broadcasting: Laravel Echo and Pusher JS
npm install --save laravel-echo pusher-js
First, we need to set the APP_ID
, APP_KEY
, APP_SECRET
and APP_CLUSTER
in the environment file. We can get these details in our Pusher app dashboard:
1# .env 2 3BROADCAST_DRIVER=pusher 4 5PUSHER_APP_ID=your-pusher-app-id 6PUSHER_APP_KEY=your-pusher-app-key 7PUSHER_APP_SECRET=your-pusher-app-secret 8PUSHER_APP_CLUSTER=your-pusher-app-cluster
Next, we need to create a fresh Echo instance in our applications’s JavaScript. We can do this at the bottom of our resources/assets/js/bootstrap.js
file:
1import Echo from "laravel-echo" 2 3window.Echo = new Echo({ 4 broadcaster: 'pusher', 5 key: 'your-pusher-app-key', 6 cluster: 'ap2', 7 encrypted: true 8});
We will implement a feature wherein a user can anonymously chat with other users. The core feature is to let the users chat without revealing their identity. It being a public chat room, any user visiting the page would be able to chat with other users without the need of any authentication. The code is available on a Github repository for cloning and understanding purposes.
Next, we need a conversations
table to record all the messages sent by a user. Let us create a model and migration:
php artisan make:model Conversation -m
The conversations
table would require the following fields:
Below is our migration file for the conversations
table:
1use Illuminate\Support\Facades\Schema; 2use Illuminate\Database\Schema\Blueprint; 3use Illuminate\Database\Migrations\Migration; 4 5class CreateConversationsTable extends Migration 6{ 7 8 public function up() 9 { 10 Schema::create('conversations', function (Blueprint $table) { 11 $table->increments('id'); 12 $table->text('message'); 13 $table->string('user'); 14 $table->timestamps(); 15 }); 16 } 17 18 public function down() 19 { 20 Schema::dropIfExists('conversations'); 21 } 22}
To record messages anonymously, we need to generate and store a random username for each message. First, we will create a ConversationController
:
php artisan make:controller ConversationController
Next, we will record each message entry into a database. A random username will be assigned to the message from an array of anonymous usernames.
1# routes/api.php 2 3Route::post('conversations/store', 'ConversationController@store'); 4 5 6# ConversationController.php 7 8public function store() 9{ 10 $random_usernames = [ 11 'Anonymous', 12 'Someone', 13 'Some Girl', 14 'Some Boy', 15 'Mr. X', 16 'Mr. Y', 17 'Mr. ABC', 18 'Ms. A', 19 'Ms. B', 20 'Ms. C', 21 ]; 22 23 $conversation = Conversation::create([ 24 'message' => request('message'), 25 'user' => $random_usernames[array_rand($random_usernames)], 26 ]); 27}
Now, a random username from the array will be assigned to each message. Let us create a conversation and check:
1>>> Conversation::all(); 2=> Illuminate\Database\Eloquent\Collection {#687 3 all: [ 4 App\Conversation {#688 5 id: 1, 6 message: "Some comment", 7 user: "Anonymous", 8 created_at: "2017-02-28 12:09:38", 9 updated_at: "2017-02-28 12:09:38", 10 }, 11 App\Conversation {#689 12 id: 2, 13 message: "Another Comment", 14 user: "Some Girl", 15 created_at: "2017-02-28 12:09:43", 16 updated_at: "2017-02-28 12:09:43", 17 }, 18 ], 19 }
As we can see, a random username is assigned to both the comments in the above results.
Whenever a new message is recorded, we need to fire an event which would be broadcast over Pusher. For broadcasting an event, it should implement the ShouldBroadcast
interface. Let us first create the NewMessage
event:
php artisan make:event NewMessage
The event should implement a broadcastOn
method. This method should return the channels to which the event will be broadcast.
Our application is publicly available to anyone. Anyone can join and chat anonymously. We will not have any authorization for users to listen or send messages. Hence, we will simply use the public Channel
:
1namespace App\Events; 2 3use App\Conversation; 4use Illuminate\Broadcasting\Channel; 5use Illuminate\Broadcasting\InteractsWithSockets; 6use Illuminate\Contracts\Broadcasting\ShouldBroadcast; 7use Illuminate\Foundation\Events\Dispatchable; 8use Illuminate\Queue\SerializesModels; 9 10class NewMessage implements ShouldBroadcast 11{ 12 use Dispatchable, InteractsWithSockets, SerializesModels; 13 14 public $conversation; 15 16 /** 17 * Create a new event instance. 18 * 19 * @return void 20 */ 21 public function __construct(Conversation $conversation) 22 { 23 $this->conversation = $conversation; 24 } 25 26 /** 27 * Get the channels the event should broadcast on. 28 * 29 * @return Channel|array 30 */ 31 public function broadcastOn() 32 { 33 return new Channel('public-chat'); 34 } 35}
Now, we need to start our queue to actually listen for jobs and broadcast any events that are recorded. We can use the database queue listener on our local environment:
php artisan queue:listen
Next, we need to broadcast this event to other users on the same channel. Let us use the broadcast
helper provided by Laravel to fire the event whenever a new message is recorded:
1# ConversationController.php 2 3public function store() 4{ 5 $random_usernames = [ 6 'Anonymous', 7 'Someone', 8 'Some Girl', 9 'Some Boy', 10 'Mr. X', 11 'Mr. Y', 12 'Mr. ABC', 13 'Ms. A', 14 'Ms. B', 15 'Ms. C', 16 ]; 17 18 $conversation = Conversation::create([ 19 'message' => request('message'), 20 'user' => $random_usernames[array_rand($random_usernames)], 21 ]); 22 23 broadcast(new NewMessage($conversation))->toOthers(); 24}
Installation and configuration of Laravel Echo is a must before we can start listening to new messages. We have covered the process in detail in the above section of this article. Please go through it if you might have skipped it.
Being a public anonymous app, we can listen to new messages on a public channel using Echo.channel(channel)
:
1listen() { 2 Echo.channel('public-chat') 3 .listen('NewMessage', (e) => { 4 this.conversations.push(e.conversation); 5 }); 6}
Now, whenever a new message is recorded, it is broadcast over Pusher. Next, we listen to that channel and push the new conversations to our conversations array in our Vue component.
Below is the JavaScript part of our Example component written using Vue.js
1<script> 2 export default { 3 data() { 4 return { 5 conversations: [], 6 message: '', 7 } 8 }, 9 mounted() { 10 this.getConversations(); 11 this.listen(); 12 }, 13 methods: { 14 store() { 15 axios.post('/api/conversations/store', { 16 message: this.message 17 }) 18 .then((response) => { 19 this.message = ''; 20 this.conversations.push(response.data); 21 }); 22 }, 23 getConversations() { 24 axios.get('/api/conversations', {}) 25 .then((response) => { 26 this.conversations = response.data; 27 }); 28 }, 29 listen() { 30 Echo.channel('public-chat') 31 .listen('NewMessage', (e) => { 32 this.conversations.push(e.conversation); 33 }); 34 } 35 } 36 } 37</script>
Below is the demonstration of our functionality:
In this article, we have demonstrated How to create a Public Anonymous Chat Application. We have covered the configuration options necessary to get started, and the examples above should help you fill in the gaps and give an overview of some of the other configuration options available to you.
The code is hosted on a public Github repository. You can download it for educational purposes. How do you use Laravel and Pusher for chat applications? Can you think of any advanced use cases for this library? What are they? Let us know in the comments!