Building a booking chatbot using BotMan
Tags: botman, laravel, chatbot
Published: 2018-09-09 11:35:14

---
title: Building a booking chatbot using BotMan 
published: true
description: Building a salon booking chatbot with Laravel and BotMan
tags: BotMan, Laravel, Chatbot,
cover_image: https://preview.ibb.co/d5qoEp/02.png
---

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](https://botman.io/) 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.

```bash
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.

```bash
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

```bash
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!".

![BotMan chatbot development](https://preview.ibb.co/gq6g0U/qmrwa0sunw73g6upzx3s.png)

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.

```bash
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)

```javascript
<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.

![BotMan chat widget](https://preview.ibb.co/gOGQS9/yafe5vs55wpe1kzvbzts.png)

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

```php
$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.

```php
$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".

```php
$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.

```php
$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
<?php

use App\Http\Controllers\BotManController;

$botman = resolve('botman');

$botman->hears('._(Hi|Hello)._', BotManController::class.'@startConversation');
```

Create a new conversation class OnboardingConversation

```bash
php artisan botman:make:conversation OnboardingConversation
```

The above command will create the OnboardingConversation class at app/Http/Conversations/

```php
<?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
<?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
<?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
<?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().

```php
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.

```php
$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.

```php
$this->bot->userStorage()->save([
    'name' => 'Your name here',
]);
```

The bot will ask the question one after another. Here is the complete code.

```php
<?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'.

![Botman Booking Chatbot](https://image.ibb.co/j0zC79/jhxwnrhxl8lqdsbhypue.png)

## 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

```bash
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.

```php
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
<?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'.

![](https://image.ibb.co/mauen9/dfuktquf760gkx2phnhx.png)

## 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.

```bash
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
<?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.

```php
$this->bot->startConversation(new DateTimeConversation());
```

Finally, let's show the booking details back to the user using a new conversation class BookingConversation.

```bash
php artisan botman:make:conversation BookingConversation
```

Here is the BookingConversation class

```php
<?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();
    }
}

```

![](https://image.ibb.co/nM6TEp/Bot_Man_Studio.png)

# Conclusion
The source code for this tutorial can be found here on [Github](https://github.com/cedextech/botman-booking-chatbot). 

I hope you found this article insightful.

**Let's connect** 🌎
- My blog [kirandev.com](https://www.kirandev.com/)
- Follow me on [Twitter](https://twitter.com/tokirankrishnan)
- Find me on [Github](https://github.com/devkiran)