How to Create a Vue.js Group Chat App in PHP with Symfony
Time to read: 7 minutes
If you have an app or products where users need to communicate with one another, adding a real-time means of communication will greatly increase customer satisfaction, and as a result, makes your business more credible.
In this tutorial, I will walk you through how you can easily add chat to your Symfony and Vue.js application using the Twilio Programmable Chat API. We'll build a group chat where every user can converse in the same channel.
Here is a preview of what we’ll be building:
Prerequisites
This tutorial uses the following:
- PHP version 7.1 or higher
- Symfony version 4.2
- Composer (You can get the latest version)
- Vue.js version 2.x
- Node.js version 8.9 or above
- Yarn version 1.7.0 or higher
To follow along with this tutorial, you should have a basic understanding of the PHP language. Knowledge of the Symfony framework is not entirely required.
I will assume you have some knowledge of Vue.js, otherwise, you can go through the basics on the docs to get you up to speed in a couple of minutes.
Create a Single Page Application
To get started, follow this tutorial to create the project structure or grab the complete file from GitHub. If you didn’t follow the tutorial, you may need to update your project directory name anywhere symfony-vue
appears.
Next, change your current directory to the root folder of the project:
Next, start up the backend server if it’s not already running:
Next, open a new terminal, then add the Twilio JavaScript library using:
Finally, start up the frontend server if it's not up already so that the changes we make to the Vue files will be automatically compiled:
Note: Make sure the two terminal windows are running while you follow along with this tutorial.
Generate a Chat Token
The first step to using the Twilio Programmable Chat API is to generate an access token. Twilio will generate the token using your API Keys and use it to make sure people accessing your app are authorized to do so.
First, generate the following API keys:
- Service Instance SID: A service instance where all the data for our application is stored and scoped. Generate one in the console here.
- Account SID: Your primary Twilio account identifier - find this in the console here.
- API Key and API Secret: Used to authenticate - generate one here.
Once you have the keys, update the values in the .env
file:
Then import the Twilio SDK we installed via Composer to the src/Controller/HomeController.php
file at the header section:
Now, create a route for generating a token by adding the function below to the HomeController.php
file:
To generate a token via the Chat API, we need a way to uniquely identify all users. In the code above, our route provides the support we need for generating these tokens.
First, we capture the email that will be sent along with the POST request. This will serve as the unique identifier for that user. Then we use the API keys we saved in the .env
file to generate a token.
Create the Vue Components for Our Chat Interface
First, let's divide our UI into components so we can build each component separately.
For brevity, we'll divide the components into:
Login.vue
that will render the login form.Channels.vue
which will list all channels created.Messages.vue
that will render all messages sent to channels.
The App.vue
file located in the /assets/js/components
folder exists by default and is the main component that will house every other component we'll create.
Now create these component files as Login.vue
, Channels.vue
, and Messages.vue
in the assets/js/components
folder.
Add the App.vue code
Using the single-file components approach of creating a Vue component, we’ll place our HTML markup in the <template>
section, our JavaScript code in the <script>
section, and our styles will be in the <styles>
section.
Now, update the template section of the assets/js/components/App.vue
file with the code below:
In the mark-up above, we imported the component's files we created earlier:
<Login …/>
. This will render the Login component. An important thing to note here is thev-if
directive we used. We are using thev-if
to check if theauthenticated
state is set to true or false. We'll render the login component if theauthenticated
state is set to false, else we’ll render the chat area. We use thev-on
directive to listen for an event namedauthenticated
that will be triggered once the user is successfully logged in so that we can call thesetAuthenticated
function to initialize the chat. We haven't created thesetAuthenticated
function yet. We'll create the function later.<Channels ../>
. This will render the channels component that we created. We’ll utilize the:channels="channels"
attribute to pass the channels array to the component so it can be rendered within the component.<Messages ../>
. This will render messages sent to a channel.
Next, update the script section of the assets/js/components/App.vue
file with the code below:
In the code above, we imported the components we created earlier and defined two global variables chatChannel
and Client
which will hold a value from the Twilio API when we initialize the SDK. Finally, we added a number of states in the data method, which will hold some states for the app.
Next, we registered the imported components, as seen in the components property components: {
so that Vue will know about them.
Finally, update the script section of the assets/js/components/App.vue
file with the code below:
Even though they’re empty, by importing the components now, Vue will allow us to observe the changes as we continue to develop them.
This is our entire chat UI. If you refresh the page, you will notice that the page is empty, except for our header and wrapper. This is because the contents of the components are still empty. Once we update the component files, you will see the page come to life.
The page should look like this:
Create the Login.vue component
Now, let's create our Login component. Add the code below to the assets/js/components/Login.vue
file:
Here, we created a form that will authenticate our users before proceeding to the chat room. For this demonstration, we are not actually doing any real authentication. We are just checking if the form inputs are populated before submitting.
If both fields are completed, we emit an event named authenticated
, passing along the user login data, which we'll act upon in the main component to show the chat area. If any of the inputs are empty, we show the user an error message.
NOTE: You should do your actual authentication within the login method before you make this application public.
If you check the page now, you will see something like below:
Create the Messages.vue component
Now add the messages component to the assets/js/components/Messages.vue
file:
Here, we have defined the messages props as an array. We will pass the messages in a channel so we can render the messages in the component using the v-for directive.
The v-bind:class...
directive allows us to check if a message was sent by the current logged in user so that we can format the message to the left. Else, we format it to the right.
Add the Channels.vue component
Finally, let's add the component for listing the channels. Add the code below to the assets/js/components/Channels.vue
file:
The code is similar to the code in Messages.vue. We pass in the channels as an array to the component, so that we can loop through the channels and list them on the page.
We also created a form for adding a new channel. When the user types a channel name and submits, we call the addChannel
function to trigger an event that we'll listen to in App.vue to create the new channel.
Finally, when a channel is clicked, we want to queue the messages in that channel. Using the v-on:click="showMessages(channel)" line, we listen to click events for a channel from a user. When the user clicks on a channel, we emit an event named show-message. Then from the App.vue, we listen to this event to display messages contained in that particular channel.
Initialize the Chat Window
To start communicating with Twilio using the JavaScript SDK, we need to generate a token. Now, add the function below to the methods:{}
block in assets/js/components/App.vue
file:
In this function, we are making a request to the /token
endpoint to generate a token using the email the user provided. Once we have the token, we save the token
and userData
to the state of the component.
Also, we change the authenticated
state to true so that the chat area will be visible and the login form will be hidden. Now try logging in, you will see the chat page show up if you fill in login details and submit (Remember, any information should work since we are not doing real authentication.):
Finally, we call the this.initializeChat();
function to initialize the chat. We'll be writing this function next.
Next, add the function that will initialize the chat to the methods:{}
block in assets/js/components/App.vue
file:
In the code above:
- We have the
Chat
object which is available to us from the Twilio JavaScript SDK we imported to this file usingconst Chat = require('twilio-chat');
- Then, using the Chat object, we initialize a chat using the token we generated -
this.token
. - If the token is valid, we'll now have access to the client object which is the starting point to accessing Twilio Chat functionality.
- Next, we use the
client
object to fetch all public channels that have been created. Once we have the channels, we save them to the state of the component and then pass them as props to theChannels.vue
component. Then finally, we set theclient
object globally.
Next, add a function to setup channels to the methods:{}
block in assets/js/components/App.vue
file:
We'll call this function once a user wants to view a channel by clicking on it. The function accepts a channel object as a parameter. Using the channel object, we, first of all, unsubscribe from the channel's events, then rejoin the channel. On successfully joining the channel, we get all the messages in the channel and also listen for new events on the channel.
Next, add a function to add a message to a channel. Once a user types a message and hits enter, we'll call the below function to add a new message to the channel:
Next, add a function for creating a new channel:
We'll call this function when a user submits a channel name they want to create.
Finally, when a user changes a channel, we want to fetch messages for the channel and display it to the user. Add a function to do that:
Test the App
Our chat is ready! To test it,
- Open two different tabs in your browser and load the application.
- In both tabs, enter a username and password and then log in. Any username and password should work.
- Create a channel, then start exchanging messages.
Conclusion
And that is it! In this tutorial, we have explored some of the Twilio Programmable Chat API. We have used the API to build a simple group chat app using Symfony and Vue. There are lots of the API features which we did not explore that would make the chat more lively. You can explore more of these features on the documentation page.
You can also get the complete code of the project on GitHub.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.