Ever had one of those mornings when you woke up unmotivated, but read a quote and the energy returned? That is the power of positive and motivational quotes.
Motivational quotes have a way of making people feel inspired and energized. This phenomenon can be attributed to a combination of factors such as motivational psychology, wordsmithing, and self-selection.
In this tutorial, I am going to teach you how to create an app that automatically sends you motivational quotes every morning. Before we start, here is a motivational quote to uplift you as you follow along.
“Believe in yourself! Have faith in your abilities! Without humble but reasonable confidence in your own powers, you cannot be successful or happy.” – Norman Vincent Peale
Getting Started
To complete this tutorial, you will need the following:
Create a New Laravel Project
Let’s create a new Laravel project by running the following command:
$ composer create-project laravel/laravel quote-app
$ cd quote-app
Set up the Twilio SDK and SendGrid Mail Driver
First, we need to install the Twilio PHP SDK using Composer. In your terminal, run the command below:
$ composer require twilio/sdk
Next, we need to set up our Laravel application to use SendGrid as the mail driver. Here is a link to a quick guide on how to set up SendGrid as your SMTP relay in Laravel.
After you have completed the setup of your SMTP relay, we will install Guzzle to execute the HTTP API requests. If you are unfamiliar, Guzzle is a great alternative to writing your server-side requests in cURL. Run the command below to install the latest version:
$ composer require guzzlehttp/guzzle
Once these steps are complete, update the .env
file with the credentials from your Twilio and SendGrid dashboards as shown below:
MAIL_DRIVER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=25
MAIL_USERNAME=apikey
MAIL_PASSWORD="Your password"
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="Your email"
MAIL_FROM_NAME="Michael Jaroya"
TWILIO_SID="Your Twilio SID"
TWILIO_AUTH_TOKEN="Your Twilio Auth Token"
TWILIO_PHONE_NUMBER="Your Twilio SMS enable phone number"
Create the Quote App
Let's flesh out the Quote model. Under normal circumstances, our model would primarily be responsible for reading and writing data into the table. We will extend its functionality with custom methods to fetch quotes from the forismatic and favqs APIs and send quotes. Finally, we will create the Quote artisan command to exploit our methods and provide CLI access to them.
Let's jump right in and get motivated :)
Create the Quote Model
Run the command below to create the model:
$ php artisan make:model Quote
Create the Logic to Fetch and Send the Quotes
Because our goal is to generate diverse, random quotes, we will use a single function to fetch a quote from both the forismatic and favqs APIs. Open the app/Quote.php
file and add the following method.
<?php
use GuzzleHttp\Client as GuzClient;
/**
* Fetch quotes from the Forismatic and Favqs APIs
*/
public function fetchQuotes() : Array {
$client = new GuzClient();
$quotes=[];
// Get quote from forismatic
$request = $client->get('http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=en');
$data = json_decode($request->getBody()->getContents());
$quotes[] = $data->quoteText . "-" . $data->quoteAuthor;
// Get quote from Favqs
$client = new GuzClient();
$request = $client->get('https://favqs.com/api/qotd');
$data = json_decode($request->getBody()->getContents());
$quotes[] = $data->quote->body . "-" . $data->quote->author;
return $quotes;
}
In the code above, a GET
request is made to the two APIs. From the responses, the quote and author are extracted. The function then returns an array containing two quotes.
Next, we need to create a function to send the fetched quotes via SMS and email them using Twilio and SendGrid respectively.
Add the code below to the Quote model:
<?php
use Twilio\Rest\Client;
/**
* send Twilio SMS
*
* @param $to
* @param $sms_body
*/
function sendSMS( $to, $sms_body ) {
// Your Account SID and Auth Token from twilio.com/console
$sid = getenv( 'TWILIO_SID' );
$token = getenv( 'TWILIO_AUTH_TOKEN' );
$client = new Client( $sid, $token );
$client->messages->create(
$to,
[
// A Twilio phone number you purchased at twilio.com/console
'from' => getenv( 'TWILIO_PHONE_NUMBER' ),
// the body of the text message you'd like to send
'body' => $sms_body[0]." ".$sms_body[1]
]
);
}
The sendSMS()
function accepts two parameters; the number of the recipient and the quotes in the form of the SMS body. Those parameters are then used to send an SMS using your Twilio enabled phone number.
Next, let's create the function to send the quotes via email. In app/Quote.php
add the following code:
<?php
use App\Mail\EmailQuotes;
use Mail;
/**
* Send email using SendGrid
* @param $email_address
* @param $body
*/
public function sendEmail($email_address,$body){
Mail::to($email_address)->send(new EmailQuote($body));
}
The sendEmail()
function accepts two parameters; the email address of the recipient and the email body and then sends the email using a Mailable class. We’ll break down what a Mailable class is in the next section.
Creating a Mailable Class
In Laravel, each type of email sent by your application is represented as a "mailable" class. These classes are stored in the app/Mail
directory.
In your terminal, run the artisan command below:
$ php artisan make:mail EmailQuote
The command generates a new file app/Mail/EmailQuote.php
.
The Mailable class has a build function where we can define the configurations for our email, indicate the template view file to be used, and also pass any needed parameters to our view template.
Update the file as shown below:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class EmailQuote extends Mailable
{
use Queueable, SerializesModels;
protected $email_body;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($email_body)
{
$this->email_body=$email_body;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$data=implode("<br>",$this->email_body);
return $this->view('emails.quote')->with(['email_body'=>$data]);;
}
}
Next, create an emails
folder under resources/views
and add a file quote.blade.php
.
Update the file as shown below:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h3>Hello,</h3>
<br>
<p>Quotes of the day:</p>
<br>
<p>{{$email_body}}</p>
</body>
</html>
Consolidating the App
Our app is now taking shape. Since we have all of the components needed to build the app, let’s put everything together. Reopen the Quote
model in app/Quotes.php
and add this final method:
/**
* The Quote App
*/
public function quoteApp(){
// ideally this should come from a database
$recipients=
[
[
'to' => '07XXXXXXXX',
'email_address' => 'email@example.com'
]
];
$quote=$this->fetchQuotes();
foreach($recipients as $recipient){
// send sms
$this->sendSMS($recipient['to'],$quote);
// send email
$this->sendEmail($recipient['email_address'],$quote);
}
}
The Quote Artisan Command
Since the app needs to send quotes every day, we need to create a way to automate the process through task scheduling. In Laravel, we can achieve this through a number of ways notably through scheduling artisan commands, Queue jobs, shell commands e.t.c.
I have opted to create a custom artisan command due to its simplicity, but you can opt for any of the options available.
Laravel's command scheduler allows you to fluently and expressively define your command schedule within Laravel itself. When using the scheduler, only a single Cron entry is needed on your server. Your task schedule is defined in the app/Console/Kernel.php
file's schedule
method.
Run the artisan command below to generate the artisan command:
$ php artisan make:command sendQuotes
This command created a new command class in the app/Console/Commands
directory.
Open the file app/Console/Commands/sendQuote.php
and update the signature
variable and the handle
method as shown below:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Quote;
class sendQuotes extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'send:quote';
/**
* The console command description.
*
* @var string
*/
protected $description = 'send SMS and Email using Twilio and SendGrid respectively';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$quote=new Quote();
$quote->quoteApp();
$this->info('Success :)');
}
Next, update app/Console/Kernel.php
file's schedule
method with this single line of code.
protected function schedule(Schedule $schedule)
{
$schedule->command('send:quote')->dailyAt('6:00');
}
This command simply means, call php artisan send:quote
(the command we have just created) daily at 6.00 am in the morning.
Finally, add the following Cron entry to your server.
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This Cron will call the Laravel command scheduler every minute. When the schedule:run
command is executed, Laravel will evaluate your scheduled tasks and runs the tasks that are due.
Testing
To test the final app, navigate to your project directory and run the artisan command below:
$ php artisan send:quote
If all went well, you should get both an SMS and an email.
Conclusion
The aim of this tutorial is to keep things as simple as possible. To build upon this app, you can create an online portal where users can subscribe to get the quote of the day by providing either a phone number or email. The code is available on Github.
Have some ideas to better improve the app? Let me know. I can’t wait to see what you build.
Feel free to reach out to me:
- GitHub: mikelidbary
- Web: www.talwork.net