bisquare与lar_哈Lar 通过SMS与PHP进行通讯!

bisquare与lar

This article was peer reviewed by Wern Ancheta. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

本文由Wern Ancheta进行同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!



In this article, we will modify our Laravel-powered phone-capable weather forecast app so that it is accessible via SMS (text message) in addition to the voice telephone system. It is recommended you read the previous post if you haven’t done so yet – it’s a 10 minute read for an excellent outcome.

在本文中,我们将修改Laravel支持的具有电话功能的天气预报应用程序,以便除了语音电话系统之外,还可以通过SMS(文本消息)进行访问。 如果您尚未阅读上一篇文章,建议您阅读该文章 -读10分钟即可获得很好的结果。

Note: If you’re confused by the development environment we’re using, it’s Homestead Improved and you can learn more about it here, or go in detail by buying our book about PHP environments.

注意:如果您对我们正在使用的开发环境感到困惑,它是Homestead改进的 ,您可以在此处了解更多信息,或者通过购买有关PHP环境的书来进行详细了解

Vector icon of phone with weather icon overlaid

添加路线 (Adding Routes)

To allow for SMS communication, we need some more routes. Open up the routes/web.php file and append the following code to it:

为了允许SMS通讯,我们需要更多路线。 打开routes/web.php文件,并将以下代码附加到该文件:

Route::group(['prefix' => 'sms', 'middleware' => 'twilio'], function () {
    Route::post('weather', 'SmsController@showWeather')->name('weather');
});

The prefix for the route is sms, so that routes will have a path like /sms/weather, as the one in the example. This is the only route we need for SMS, as Twilio will call the same route over and over again. Twilio will access it via HTTP POST. We could also do this without the prefix, but it’s more flexible this way if we decide to add more functionality to the SMS side later.

路由的前缀是sms ,因此路由将具有/sms/weather类的路径,例如本示例中的路径。 这是我们SMS所需的唯一路线,因为Twilio会一遍又一遍地调用同一条路线。 Twilio将通过HTTP POST访问它。 我们也可以不使用前缀来执行此操作,但是如果我们以后决定在SMS端添加更多功能,则这样做会更加灵活。

服务层 (Service Layer)

Next, we’ll modify the service we wrote previously. Open up the app/Services/WeatherService.php file and remove the current getWeather method, then replace it with the one below:

接下来,我们将修改我们先前编写的服务。 打开app/Services/WeatherService.php文件并删除当前的getWeather方法,然后将其替换为以下一种方法:

public function getWeather($zip, $dayName, $forSms = false)
    {

        $point = $this->getPoint($zip);
        $tz = $this->getTimeZone($point);
        $forecast = $this->retrieveNwsData($zip);
        $ts = $this->getTimestamp($dayName, $zip);

        $tzObj = new \DateTimeZone($tz->timezoneId);

        $tsObj = new \DateTime(null, $tzObj);
        $tsObj->setTimestamp($ts);

        foreach ($forecast->properties->periods as $k => $period) {
            $startTs = strtotime($period->startTime);
            $endTs = strtotime($period->endTime);

            if ($ts > $startTs and $ts < $endTs) {
                $day = $period;
                break;
            }
        }

        $weather = $day->name;
        $weather .= ' the ' . $tsObj->format('jS') . ': ';

        $response = new Twiml();

        if ($forSms) {
            $remainingChars = 140 - strlen($weather);

            if (strlen($day->detailedForecast) > $remainingChars) {
                $weather .= $day->shortForecast;
                $weather .= '. High of ' . $day->temperature . '. ';
                $weather .= $day->windDirection;
                $weather .= ' winds of ' . $day->windSpeed;
            } else {
                $weather .= $day->detailedForecast;
            }

            $response->message($weather);
        } else {
            $weather .= $day->detailedForecast;

            $gather = $response->gather(
                [
                    'numDigits' => 1,
                    'action' => route('day-weather', [], false)
                ]
            );

            $menuText = ' ';
            $menuText .= "Press 1 for Sunday, 2 for Monday, 3 for Tuesday, ";
            $menuText .= "4 for Wednesday, 5 for Thursday, 6 for Friday, ";
            $menuText .= "7 for Saturday. Press 8 for the credits. ";
            $menuText .= "Press 9 to enter in a new zipcode. ";
            $menuText .= "Press 0 to hang up.";

            $gather->say($weather . $menuText);
        }

        return $response;
    }

This function is very similar to the old one. The only difference is that it takes into consideration that the weather request might be coming form a telephone device via SMS, so it makes sure that the weather forecast isn’t too long and tries to limit it to less than 140 characters. The response for SMS is still TwiML, just formatted for SMS.

此功能与旧功能非常相似。 唯一的区别是考虑到天气请求可能是通过SMS通过电话设备发出的,因此可以确保天气预报不会太长,并尝试将其限制为少于140个字符。 SMS的响应仍然是TwiML,仅格式化为SMS

控制者 (Controller)

Create a file called SmsController.php in the app/Http/Controllers folder and put the following code into it:

app/Http/Controllers文件夹中创建一个名为SmsController.php的文件,并将以下代码放入其中:

<?php

namespace App\Http\Controllers;

use App\Services\WeatherService;
use Illuminate\Http\Request;
use Twilio\Twiml;

class SmsController extends Controller
{
    protected $weather;

    public function __construct(WeatherService $weatherService)
    {
        $this->weather = $weatherService;
    }

    public function showWeather(Request $request)
    {
        $parts = $this->parseBody($request);

        switch ($parts['command']) {
            case 'zipcode':
                $zip = $parts['data'];

                $request->session()->put('zipcode', $zip);

                $response = $this->weather->getWeather($zip, 'Today', true);

                break;
            case 'day':
                $zip = $request->session()->get('zipcode');

                $response = $this->weather->getWeather($zip, $parts['data'], true);

                break;
            case 'credits':
                $response = new Twiml();

                $response->message($this->weather->getCredits());

                break;
            default:
                $response = new Twiml();

                $text = 'Type in a zipcode to get the current weather. ';
                $text .= 'After that, you can type the day of the week to get that weather.';

                $response->message($text);

                break;
        }

        return $response;
    }

    private function parseBody($request)
    {
        $ret = ['command' => ''];
        $body = trim($request->input('Body'));

        if (is_numeric($body) and strlen($body) == 5) {
            $ret['command'] = 'zipcode';
            $ret['data'] = $body;
        }

        if (in_array(ucfirst(strtolower($body)), $this->weather->daysOfWeek) !== false) {
            $ret['command'] = 'day';
            $ret['data'] = ucfirst(strtolower($body));
        }

        if (strtolower($body) == 'credits') {
            $ret['command'] = 'credits';
        }

        return $ret;
    }
}

When an SMS message comes in from a user, Twilio will always hit the same route. This app does not have any redirects. That is why we only defined one route meaning all the requests will be going through the showWeather method. There are different things a user can text the app, so we will parse the request body to figure out what they want using the parseBody method.

当用户收到SMS消息时,Twilio将始终按相同的路线。 这个应用程式没有任何重新导向。 这就是为什么我们仅定义一条路线的原因,这意味着所有请求都将通过showWeather方法进行。 用户可以通过不同方式向应用发送文本,因此我们将使用parseBody方法解析请求正文以找出他们想要的parseBody

The parseBody method first creates a default return value. Then, it strips whitespace. This is so that if a user inputs “90210 ” (note the space), the program will still work as intended. Once the whitespace has been stripped, the body of the text is evaluated against three if statements. The first if statement checks to see if the user entered a zipcode. The second if statement checks to see if the user entered in a day of the week. It normalizes the input by making sure that only the first letter is capitalized, and compares it to the contents of the $daysOfWeek array property in the WeatherService class to determine if a day of the week was mentioned. The last if statement checks if a user requested the credits. If none of the three if statements evaluate to true then the program cannot figure out what the user wants and will return the default value. This default value will make the weather method send the user a help message that explains how to use the app.

parseBody方法首先创建一个默认返回值。 然后,它去除空格。 这样,如果用户输入“ 90210”(注意空格),程序仍将按预期运行。 除去空格后,将针对三个if语句评估文本的正文。 第一个if语句检查用户是否输入了邮政编码。 第二条if语句检查用户是否在一周中的某一天输入。 通过确保仅将第一个字母大写来对输入进行标准化,并将其与WeatherService类中$daysOfWeek数组属性的内容进行比较,以确定是否提到了星期几。 最后的if语句检查用户是否请求了积分。 如果三个if语句中的任何一个都不为true则程序无法确定用户想要什么,并将返回默认值。 此默认值将使weather方法向用户发送一条帮助消息,以说明如何使用该应用程序。

The parseBody method returns an array with two keys in it. The command key is what the user’s intention was determined to be. The data key is the data that goes with the command. Inside the showWeather method, after the parsebody is called, a switch statement is used to look at the value of the command array key.

parseBody方法返回一个包含两个键的数组。 command键是确定用户意图的键。 data键是命令附带的数据。 在showWeather方法内部,在调用parsebody之后,将使用switch语句查看command数组键的值。

If the parser determines a user texted a zipcode, then we store the zipcode in a session and return today’s forecast for that zipcode. A sample TwiML response looks like this:

如果解析器确定用户通过短信发送了邮政编码,则我们会将邮政编码存储在会话中,并返回该邮政编码的今日预测。 TwiML示例响应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Message>This Afternoon the 31st: Sunny, with a high near 72. South southwest wind around 8 mph.
  </Message>
</Response>

If it is determined a day of the week was entered, then that day’s forecast is returned. A sample TwiML response looks like this:

如果确定输入星期几,则返回该天的预测。 TwiML示例响应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Message>Monday the 3rd: Sunny, with a high near 70.
  </Message>
</Response>

If the parser determines the credits were asked for, then the app returns a TwiML response with the credits:

如果解析器确定要索要信用,则该应用将返回TwiML响应以及信用:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Message>Weather data provided by the National Weather Service. Zipcode data provided by GeoNames.
  </Message>
</Response>

If the parser cannot determine the user’s intent, then a help message is returned with this TwiML:

如果解析器无法确定用户的意图,则此TwiML将返回帮助消息:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Message>Type in a zipcode to get the current weather. After that, you can type the day of the week to get that weather.
  </Message>
</Response>

特威里奥 (Twilio)

Login to your Twilio account and navigate to the settings for your phone number. You can see your number by going to this page. In the SMS section, put in the URL in the following format: http://NGROK_HOST/sms/weather, where NGROK_HOST is the hostname in the URL you noted from the Ngrok program.

登录到您的Twilio帐户,然后导航到您的电话号码设置。 您可以转到此页面查看您的电话号码。 在“ SMS”部分中,以以下格式输入URL: http://NGROK_HOST/sms/weather ,其中NGROK_HOST是您从Ngrok程序记下的URL中的主机名。

Image of webhook page on Twilio

使用应用程式 (Using the App)

Open up the text messaging app on your phone and send a zipcode like 92010 to your Twilio phone number. In a couple of seconds, you should get a response with today’s forecast.

打开手机上的短信应用程序,然后将92010这样的邮政编码发送到Twilio电话号码。 在几秒钟之内,您应该得到对今天的预报的回应。

Image of iPhone SMS app with weather of entered zipcode

Next, you can send a day of the week to the number and it will respond with that day’s forecast.

接下来,您可以将星期几发送给该号码,它将以当天的预测作为响应。

Image of iPhone SMS app with weather of entered day

You can also send the word credits and it will return the credits.

您也可以发送credits一词,它将返回积分。

Image of iPhone SMS app with the credits for the app

If you enter in a command the weather app does not understand, it returns some help text.

如果您输入天气应用无法理解的命令,它将返回一些帮助文本。

Image of iPhone SMS app with weather help

结论 (Conclusion)

Over the course of two articles, we have seen how to build an application that is able to interact with users via the voice telephone system using voice menus and to interact with them using SMS. This was implemented using Laravel for the application backend and Twilio for the telephone / SMS integration. With writing a little bit more code, we have seen that it is possible to extend the voice app to have the same functionality exposed to users via SMS.

在两篇文章的过程中,我们已经了解了如何构建一个应用程序,该应用程序能够使用语音菜单通过语音电话系统与用户进行交互,并能够通过SMS与用户进行交互。 这是使用Laravel来实现应用程序后端,而使用Twilio来实现电话/ SMS集成。 通过编写更多代码,我们已经看到可以扩展语音应用程序,使其具有通过SMS向用户公开的相同功能。

You can find the example code for this article series on Github.

您可以在Github上找到本系列文章的示例代码。

There are lots of possibilities for apps that you can implement with Twilio and PHP, this is just a little glimpse into what can be done. Check out the documentation here for some inspiration.

您可以使用Twilio和PHP实现的应用程序有很多可能性,这只是可以做些什么。 在此处查看文档以获取一些启发。

翻译自: https://www.sitepoint.com/hello-laravel-communicating-php-sms/

bisquare与lar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值