BotMan is the most popular chatbot development framework for PHP. You can use BotMan in your existing codebase or with any PHP frameworks.
There are different chatbot development frameworks available for Node Js, Python. BotMan is the only PHP framework that truly helps the developers to build chatbot using PHP.
If you are a Laravel developer, BotMan Studio is the one thing you are looking for. BotMan Studio is a bundled version of BotMan and Laravel.
How to create a chatbot using BotMan?
Let's take a look at BotMan Studio and build a simple Salon booking chatbot for the website.
Install and set up the BotMan Studio
First, make sure you have composer installed on your system. Now download the BotMan installer using Composer.
composer global require "botman/installer"
This will install the BotMan Studio on your system.
Make sure to place the $HOME/.composer/vendor/bin directory (or the equivalent directory for your OS) in your $PATH so the botman executable can be located by your system.
Type "botman" on your command line to see if installation works correctly. If you can see the output similar to the below image then BotMan Studio installation is a success.
Create a new chatbot project
Now let's use the BotMan Studio to create new chatbot. You can use 'botman new' command which will create a fresh BotMan Studio installation.
botman new salon
The above command will create a new directory called "salon" with the BotMan Studio installation with all of BotMan's dependencies already installed.
Test the installation works
Now start the development server using the
cd salon
php artisan serve
That will start the development server at http://127.0.0.1:8000
If the installation is okay, you can see the welcome page from Botman.
Click the link "Tinker", there you can try a very simple chatbot. Say "Hi" to bot and the bot will reply with "Hello!".
Great job. Now you have everything ready to build your first chatbot.
Install the web driver
BotMan comes with many drivers for the developers. Drivers help us to connect the bot with messaging channels such as Facebook Messenger, Slack, Telegram, Twilio, Web etc.
As we are going to build a web-based chatbot, let's install the web driver.
php artisan botman:install-driver web
We can use WebDriver for adding the chatbot to our website or use the APIs. Web driver comes with APIs for sending and receiving messages. This helps us to build our own chat interfaces by leveraging the WebDriver APIs.
BotMan ships with a web widget that you can use out of the box. We can include the Javascript snippet to our welcome view (welcome.blade.php)
<script src='https://cdn.jsdelivr.net/npm/botman-web-widget@0/build/js/widget.js'></script>
Now, refresh your page and you can see the chat widget at the bottom right corner of the page. Say "Hi" to bot and the bot will reply with "Hello!". That's it.
There are 2 important core concepts you should learn before starting building chatbot using the BotMan Studio - Hearing the Messages and Sending the Messages.
Like any other web application, chatbot receives some request, process it and send the responses back to the channels (Web, Messenger, Slack etc).
Hearing the Messages
$botman = resolve('botman');
$botman->hears('Hi', function ($bot) {
$bot->reply('Hello!');
});
You can even use a regular expression like below. It listens for either "Hi" or "Hello" anywhere in the incoming message.
$botman = resolve('botman');
$botman->hears('._(Hi|Hello)._', function ($bot) {
$bot->reply('Hello!');
});
Instead of Closure, you can pass a class and method that will get called if the keyword matches. In the example below, startConversation method will get called if the user says "Hi".
$botman = resolve('botman');
$botman->hears('._(Hi|Hello)._', BotManController::class.'@startConversation');
Sending the Messages
You have already seen how to send a message using BotMan. BotMan can send messages in different ways - text, buttons, attachments, generic templates etc.
Let's see how to send a text message with two buttons.
$botman = resolve('botman');
$question = Question::create('Do you agree with me?')
->callbackId('agree')
->addButtons([
Button::create('Yes')->value('yes'),
Button::create('No')->value('no'),
]);
$botman->ask($question, function(Answer $answer) {
});
Chatbot conversation flows
We are going to build a simple salon booking chatbot which helps the website visitors to book the salon services through the chatbot from their website.
Every chatbot must have one or more conversation flows. Here is the expected conversation flow of chatbot we are going to build.
- Welcome the visitor
- Ask for the name, email, and mobile
- Prompt the visitor to choose one of the services
- Prompt the visitor to choose a date and time slot
- Show the booking information
Build the chatbot dialogs
Now open routes/botman.php and change it so that when someone says 'Hi' or 'Hello', startConversation method in BotManController will get called.
<?php
use App\Http\Controllers\BotManController;
$botman = resolve('botman');
$botman->hears('._(Hi|Hello)._', BotManController::class.'@startConversation');
Create a new conversation class OnboardingConversation
php artisan botman:make:conversation OnboardingConversation
The above command will create the OnboardingConversation class at app/Http/Conversations/
<?php
namespace App\Http\Conversations;
use BotMan\BotMan\Messages\Conversations\Conversation;
class OnboardingConversation extends Conversation
{
public function run()
{
//
}
}
Let's take a look at the BotManController class located at app/Http/Controllers/ and update the code so that it can use our new OnboardingConversation class.
<?php
namespace App\Http\Controllers;
use BotMan\BotMan\BotMan;
use Illuminate\Http\Request;
use App\Http\Conversations\OnboardingConversation;
class BotManController extends Controller
{
public function handle()
{
$botman = app('botman');
$botman->listen();
}
public function tinker()
{
return view('tinker');
}
public function startConversation(BotMan $bot)
{
$bot->startConversation(new OnboardingConversation());
}
}
Now open the conversation class OnboardingConversation. It extends an abstract class Conversation. The run method is the starting point of the conversation and get's executed immediately.
<?php
namespace App\Http\Conversations;
use BotMan\BotMan\Messages\Conversations\Conversation;
class OnboardingConversation extends Conversation
{
public function run()
{
//
}
}
Ask for the name, email, and mobile
Let's ask the visitor to enter his/her name. This is a very simple thing to do.
<?php
namespace App\Http\Conversations;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Conversations\Conversation;
class OnboardingConversation extends Conversation
{
public function askName()
{
$this->ask('What is your name?', function(Answer $answer) {
$this->say('Nice to meet you '. $answer->getText());
});
}
public function run()
{
$this->askName();
}
}
How does it work?
The run method will call the askName method when the conversation starts. Inside the askName it uses the 'ask' method which will output a question in the chatbot. The user response can be fetched using $answer->getText().
Now the bot wants to ask the 2nd and 3rd questions. So let's create two methods - askEmail()and askMobile().
public function askEmail()
{
$this->ask('What is your email?', function(Answer $answer) {
$validator = Validator::make(['email' => $answer->getText()], [
'email' => 'email',
]);
if ($validator->fails()) {
return $this->repeat('That doesn\'t look like a valid email. Please enter a valid email.');
}
$this->bot->userStorage()->save([
'email' => $answer->getText(),
]);
$this->askMobile();
});
}
There are a few interesting things to notice.
First, I have used Laravel validation to validate the email. If the validation fails, the chatbot prompts the users to enter a valid email address. The method 'repeat' will ask the last asked question again.
$this->repeat('That doesn\'t look like a valid email. Please enter a valid email.');
userStorage method as the name suggests saving the current chatbot user information. Hence we will use userStorage method to store the booking information.
$this->bot->userStorage()->save([
'name' => 'Your name here',
]);
The bot will ask the question one after another. Here is the complete code.
<?php
namespace App\Http\Conversations;
use Validator;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Conversations\Conversation;
class OnboardingConversation extends Conversation
{
public function askName()
{
$this->ask('What is your name?', function(Answer $answer) {
$this->bot->userStorage()->save([
'name' => $answer->getText(),
]);
$this->say('Nice to meet you '. $answer->getText());
$this->askEmail();
});
}
public function askEmail()
{
$this->ask('What is your email?', function(Answer $answer) {
$validator = Validator::make(['email' => $answer->getText()], [
'email' => 'email',
]);
if ($validator->fails()) {
return $this->repeat('That doesn\'t look like a valid email. Please enter a valid email.');
}
$this->bot->userStorage()->save([
'email' => $answer->getText(),
]);
$this->askMobile();
});
}
public function askMobile()
{
$this->ask('Great. What is your mobile?', function(Answer $answer) {
$this->bot->userStorage()->save([
'mobile' => $answer->getText(),
]);
$this->say('Great!');
});
}
public function run()
{
$this->askName();
}
}
Let's try our chatbot to see if that works. Go to http://127.0.0.1:8000, refresh the page and start the conversation by sending 'Hello'.
Prompt the visitor to choose one of the services
Now let's move to the next questions. This time the chatbot will ask the users to choose one of the services. Assume the salon offers 3 services - Hair, Spa, Beauty.
Create a new conversation class SelectServiceConversation
php artisan botman:make:conversation SelectServiceConversation
When we build more and more conversations, we want to connect conversations with one another. You can use the method $this->bot->startConversation(new AnotherConversation()) inside any conversation class to connect it with another conversation.
Open the OnboardingConversation conversation class and make the following changes.
public function askMobile()
{
$this->ask('Great. What is your mobile?', function(Answer $answer) {
$this->bot->userStorage()->save([
'mobile' => $answer->getText(),
]);
$this->say('Great!');
$this->bot->startConversation(new SelectServiceConversation()); // Trigger the next conversation
});
}
BotMan ships cool method to asking multiple choice questions - Question and Button classes.
<?php
namespace App\Http\Conversations;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Conversations\Conversation;
class SelectServiceConversation extends Conversation
{
public function askService()
{
$question = Question::create('What kind of Service you are looking for?')
->callbackId('select_service')
->addButtons([
Button::create('Hair')->value('Hair'),
Button::create('Spa')->value('Spa'),
Button::create('Beauty')->value('Beauty'),
]);
$this->ask($question, function(Answer $answer) {
if ($answer->isInteractiveMessageReply()) {
$this->bot->userStorage()->save([
'service' => $answer->getValue(),
]);
}
});
}
public function run()
{
$this->askService();
}
}
isInteractiveMessageReply method detects if the user interacted with the message and clicked on a button or simply entered text.
Let's try our chatbot to see if that works. Go to http://127.0.0.1:8000, refresh the page and start the conversation by sending 'Hello'.
Prompt the visitor to choose a date and time slot
Great!. As what we have done before let's create one more conversation class to ask the users to choose a date and timeslot for the booking.
php artisan botman:make:conversation DateTimeConversation
The below conversation class will first prompt the users to choose a date then a timeslot and save the responses in the current chatbot user storage.
Here is the complete code.
<?php
namespace App\Http\Conversations;
use Carbon\Carbon;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Conversations\Conversation;
class DateTimeConversation extends Conversation
{
public function askDate()
{
$availableDates = [
Carbon::today()->addDays(1),
Carbon::today()->addDays(2),
Carbon::today()->addDays(3) ];
$question = Question::create('Select the date')
->callbackId('select_date')
->addButtons([
Button::create($availableDates[0]->format('M d'))->value($availableDates[0]->format('Y-m-d')),
Button::create($availableDates[1]->format('M d'))->value($availableDates[1]->format('Y-m-d')),
Button::create($availableDates[2]->format('M d'))->value($availableDates[2]->format('Y-m-d')),
]);
$this->ask($question, function(Answer $answer) {
if ($answer->isInteractiveMessageReply()) {
$this->bot->userStorage()->save([
'date' => $answer->getValue(),
]);
$this->askTime();
}
});
}
public function askTime()
{
$question = Question::create('Select a time slot')
->callbackId('select_time')
->addButtons([
Button::create('9 AM')->value('9 AM'),
Button::create('1 PM')->value('1 PM'),
Button::create('3 PM')->value('3 PM'),
]);
$this->ask($question, function(Answer $answer) {
if ($answer->isInteractiveMessageReply()) {
$this->bot->userStorage()->save([
'timeSlot' => $answer->getValue(),
]);
}
});
}
public function run()
{
$this->askDate();
}
}
Don't forget to connect the DateTimeConversation conversation with SelectServiceConversation inside the askService method.
$this->bot->startConversation(new DateTimeConversation());
Finally, let's show the booking details back to the user using a new conversation class BookingConversation.
php artisan botman:make:conversation BookingConversation
Here is the BookingConversation class
<?php
namespace App\Http\Conversations;
use BotMan\BotMan\Messages\Incoming\Answer;
use BotMan\BotMan\Messages\Outgoing\Question;
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
use BotMan\BotMan\Messages\Conversations\Conversation;
class BookingConversation extends Conversation
{
public function confirmBooking()
{
$user = $this->bot->userStorage()->find();
$message = '-------------------------------------- <br>';
$message .= 'Name : ' . $user->get('name') . '<br>';
$message .= 'Email : ' . $user->get('email') . '<br>';
$message .= 'Mobile : ' . $user->get('mobile') . '<br>';
$message .= 'Service : ' . $user->get('service') . '<br>';
$message .= 'Date : ' . $user->get('date') . '<br>';
$message .= 'Time : ' . $user->get('timeSlot') . '<br>';
$message .= '---------------------------------------';
$this->say('Great. Your booking has been confirmed. Here is your booking details. <br><br>' . $message);
}
public function run()
{
$this->confirmBooking();
}
}
Conclusion
The source code for this tutorial can be found here on Github.
I hope you found this article insightful.
Let's connect 🌎
- My blog kirandev.com
- Follow me on Twitter
- Find me on Github
Top comments (25)
I get the following error
include(): Opis\Closure\ClosureStream::stream_set_option is not implemented!
When using the following code
Has anyone else gotten this
its due to php 7.4 that I have installed locally (arrow functions and all that fun stuff), my vagrant homestead setup is currently on 7.2~3 so I just served it from there and everything works great. Great tutorial thanks !
Glad you found it useful.
Hello Sir
Iam buiding my chatbot with laravel and integrating using carbon library.
Can you please help me how can I show date picker in textbox.I wanted to select dat from date picker and save that value.
I waiting for your reply .Please help me as soon as possible.
Thanks
Pooja
Hello Pooja,
Botman web widget doesn't support datepicker component by default. But you can customize the web widget according to your needs github.com/botman/web-widget
In the newest version of Botman, when creating a new conversation using the command 'php artisan botman:make:conversation OnboardingConversation' this create file in to the path 'App\Conversations'. I had to replace the "namespace App\Http\Controllers;" to "namespace App\Controllers;" and "use App\Http\Conversations\OnboardingConversation;" to "use App\Conversations\OnboardingConversation;".
Thanks for the great tutorial Kiran! Helped me introduce Botman for the team =)
Thank you.
Hello,
I want to conversation start from botman side.
Currently, firstly we have to enter the message after that Botman reply. But I want to when user open chatbot Botman start conversation.
Please help.
Excellent article Kiran, I had no idea about this package. thanks for sharing
Thank you!
Hi, I am student of MscIT, basically I like to learn about AI Driven chatbot, How to build a chatbot and importance of chatbot for various industries. I also like to refer technical blogs like this blog. I always curious to learn new things and about new technologies. I gained my knowledge from this content. It was amazing and helpful too. Thank you writer for sharing this knowledge with us. bit.ly/2N5yyRm
This was a great tutorial. The only thing that I saw different in my system is that the Classes were getting installed in /app/ and not in /app/Http/, but was able to edit a bit and made it work.
Thanks for great tutorial!!!
I'm using the web driver without BotmanStudio, and when a type Hi i don't get a response. What can i do?
Do you have any pointers/tips for using BotMan with Laravel Echo? I am using a custom Web driver
and web widget, just simple modifications of the originals.
Hi
How to add custom URL or custom parameter in response.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.