Full Stack Web Developer (Q1-Q2 2021)

Estimating read time ...
Edited 7th November 2021

SendGrid - Working with APIs, PHP and Composer

We're going to continue the theme of working with APIs which we began from the last sections, however in this section we're going to advance further.

As a recap we dived into using the OpenWeather API to retrieve weather data for a predefined/input location, returning the information to the user (i.e. via our browser on our project site). We used the Postman tool for establishing an initial connection and ensuring we receive the data we expect, then we implemented the functionality into our site using Ajax via jQuery in JavaScript.

Now we're moving focus onto the SendGrid API which will enable us to send emails. Instead of performing the API call directly to SendGrid using JavaScript, we’ll be using a server-side programming language, in our case this will be PHP.

1. Utilising Composer

As mentioned previously, there are multiple ways in which we can perform API calls. We’ve explored Ajax via jQuery in JS and now we’ll be using GuzzleClient in PHP. (cURL is another popular, arguably the most popular option, but we won’t be covering this.)

GuzzleClient is a package which provides us with the ability to make advanced HTTP calls (i.e. API calls) and is developed in and for PHP. We’ll be installing this onto our site using Composer, which we installed onto our machines in one of the early sections of this course. By installing this into our project, for our site/app to function correctly as intended, Composer will recognise GuzzleClient as a dependency for our site/app.

Briefly, similar to NPM, Composer is a package manager. We use them to install additional/third-party libraries to enhance the functionality or capabilities of our project. Package managers can keep track of all the software/libraries we’ve installed into our project, update them or remove them efficiently. Packages are not installed on your machine, but installed on each individual project. NPM is a package manager for JavaScript (or more specifically Node.js) and Composer is a package manager for PHP. We previously used NPM to install the Sass library.

So without further ado, let’s begin with Composer. Again similar to NPM, we need to use the terminal for this (i.e. Git Bash for Windows).

  1. Open Git Bash and cd into your project site we’ve been working on.
  2. Now run the following two commands:
composer require guzzlehttp/guzzle:^7.0 composer require vlucas/phpdotenv

Here we’re telling composer to install two packages into our project, the first is GuzzleClient and the second is "PHP dotenv" (the latter which I’ll explain in the "Keeping our API Keys Confidential" section further down on this page).

Running the above commands should have installed both packages into our project successfully. If you’ve received errors running the command, your PHP or Composer may not be correctly configured.

2. Updating our .gitignore

After running the composer require commands, we will have two additional files (composer.json and composer.lock) and a new directory (vendor) in our project folder.

Similar to node_modules we want to add vendor to our .gitignore so that we do not commit our composer packages and dependencies to our Git repo, which would otherwise make our repo unnecessarily large in file size. We however want to keep the other two files composer generated for us in our repo, so please don’t add them into your .gitignore, just the vendor directory.

Whilst we’re editing our .gitignore, we may as well add an extra entry now. We also want to ignore a file named .env (which we’ll explain in the next section). All new git ignore exclusions are added on a new line, so the contents of your .gitignore file should now look like:

/node_modules /vendor .env

Once you’ve made the above changes, you can now commit your .gitignore and composer files (composer.json and composer.lock) to git.

3. Keeping our API Keys Confidential (Part 1 – Brief)

When we integrated with the OpenWeather API previously using Ajax in JavaScript (JS), you would have been required to place your unique API KEY which was provided by OpenWeather in your JS code. As JS is executed on the client-side (as is HTML and CSS), our code and ultimately any keys we use are exposed to anyone who inspects our source code. Additionally any API calls would have been performed by the visitor’s device, unknowingly sending their details (i.e. their browser’s "request header") to the API provider.

We can overcome these constraints by using a server-side programming language, instead of executing our API calls over Ajax. When using a server-side language such as PHP, as our code is processed by the server they are never exposed to the end-user’s device. (When developing locally, XAMPP on our machines currently acts as the server.)

Although using Ajax can leave keys exposed in our source code, we should avoid placing any confidential data initially in our JS code which is publicly available for inspection. We did use the Ajax method previously purely to get us started in a simple manner to API development, however this should not downplay Ajax’s role and capabilities. Ajax allows us to perform API calls and return data to the user without the need to reload the page, whereas any server-side code which requires execution needs the page to be visited. The need not to reload the page (or be redirected to another page for processing) is actually a better user experience (UX) for the end-user, so we can achieve this by processing our API calls using a server-side language such as PHP, then performing an Ajax call to the PHP page. This way we still have the benefits of Ajax and our confidential data is not exposed.

4. Keeping our API Keys Confidential (Part 2 – The .env File)

The .env file (dot env) is a file which defines environment variables for unix-based operating systems, however we have since adopted this standard for projects within the development industry. As they define variables for the environment only (i.e. our project), not shared and ignored by git (because we added it to our .gitignore), we can store API keys here.

By placing our environment data (and credentials/secret keys) in our .env file, we remove the need to store them in our programming code and ultimately our git repos (especially if we ever go onto make public repos).

So to get started, in your project folder create two files: .env and .env.example. If Windows does not allow you to create these files, you may need to do them using the terminal/Git Bash. You can do so by running the following command whilst in your project folder (i.e. once you’ve opened Git Bash and cd’d into your project):

touch .env .env.example

Now for best practices we want to ensure both files contain the same variables, however the .env.example values will always remain blank. This is so that when we collaborate with other developers, we know which variables we need to populate without sharing our secret/unique keys. Each new variable must be entered on a new line. Let’s start by adding our SendGrid API. In the contents of .env add:

SENDGRID_KEY=aybpawqBdT41FdHkmQOI9BVIAhNgdRzx

Replace the key (after the equals sign) with your own SendGrid key. You can obtain a SendGrid key by creating one (if one is not already generated for you). To generate your own SendGrid key, please see the "Creating an API key" section of the SendGrid documentation.

Next, in your .env.example file just add:

SENDGRID_KEY=

But leave the value blank (i.e. do not add your key in the `.env.example` file).

Now save both files and you may commit your .env.example file. You cannot (and should not) commit your .env file as it holds confidential data, but you can commit your .env.example file as the variables should not be defined a value.

If we ever need to we can always add additional variables to the .env file, from secret keys, database connection details or to something as simple as environment type (e.g. APP_ENV=local or APP_ENV=prod, both denoting local and production/live respectively).

5. Composer Autoload and Referencing ENV values in PHP

Now that we’ve defined our .env file which contains environment variables, we can now reference the variables in our PHP code and this is where our phpdotenv composer package we downloaded in the first section will come in handy.

To utilise any packages which we download via Composer, we must load them first and there are many standardised ways we can perform this. However Composer can handle this for us and when it does, it "autoloads" all packages for us (i.e. lazy loads). To initiate Composer’s autoloader, we need to add the following line of PHP code:

require __DIR__ . '/vendor/autoload.php';

The above code assumes that the PHP file in which you place the code is in your project’s root directory. (You can alter the directory if you require.)

Next the phpdotenv package requires us to run the following (according to its documentation):

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv->load();

The above code also assumes that your PHP file is in your root directory. The above code informs the phpdotenv package where our .env file is stored; within the parameter of the createImmutable() method the PHP global value __DIR__ is passed in, which is the current working directory.

Now that we’ve initiated Composer’s autoloader and also loaded phpdotenv, we can now use the stored variables in the .env file within our PHP code. We can retrieve our SENDGRID_KEY variable with the following line:

$_ENV['SENDGRID_KEY']

And that’s how we can access our secret keys and credentials without actually inserting them into our programming code, and ultimately avoid committing them to git repos. The full code for the above may look something like:

<?php require __DIR__ . '/vendor/autoload.php'; $dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv->load(); echo $_ENV['SENDGRID_KEY']; // Print the API key. ?>

Now moving on to the actual integration of the SendGrid API and building this into our PHP code.

6. Integrating with SendGrid using GuzzleClient (PHP) for our API calls

As you know SendGrid is capable of sending emails, therefore I’d like you to enhance your ‘ContactProcess.php’ file we created from an earlier chapter where we had the HTML contact form POST data to the PHP file for processing. Instead of using PHP’s mail() method, we’ll send the email using SendGrid. The email we send must contain the contact form’s contents, i.e. the inputs a user/visitor enters into our contact form.

6.1. Part 1 – Trialling SendGrid via Postman

Using Postman initially, I’d like you to establish a connection with the SendGrid API and be able to successfully send an email with a message (it can be any random message at this stage and to ensure the email sending functionality works, you’ll need to use a real email address, or if you would rather prefer you can use a disposable email). You will need to be familiar with the JSON format that we introduced previously (feel free to look over the Postman, APIs and Ajax chapter for a refresher).

To begin using the SendGrid API, please read their "Getting started with the SendGrid API" article and "Mail Send" documentation. You can ignore their provided libraries and the need to have cURL installed on your machine, as we’re using Postman for our testing and we’ll be using GuzzleClient for the API calls. You can also ignore the "Handlebars" and "Mail body compression" sections of the documentation.

The "Try it out" tab on the SendGrid documentation page provides an example JSON "Request Body" (i.e. the payload). To perform the API call, you’re going to need to define your own payload, but can use their provided example as a start.

You can add a payload into Postman by clicking the ‘Body’ tab under the address bar then select the ‘raw’ option. You can also optionally change this from ‘Text’ to ‘JSON’ in the far right drop-down which appears, it shouldn’t make a difference however.

6.2. Part 2 – Integrating into PHP via Guzzle

Once you’ve successfully managed to send an email using SendGrid via Postman, we can now move onto building the integration into our PHP code. For this please use the GuzzleClient. You can read the documentation on how to use their package on their Github Repo and their official documentation.

If calling the GuzzleClient, e.g. new GuzzleHttp and you get an exception error such as GuzzleHttp not found or defined, this would indicate that the package has not been autoloaded. Ensure that Composer’s autoloader is defined at the top of your PHP file. Ideally you should only define Composer’s autoloader once (to reduce code duplication), then include the file that requires the autoloader.

Both SendGrid and GuzzleClient are popular offerings, therefore if you do find yourself to become stuck you should be able to find helpful resources via a Google Search and numerous topics on Stackoverflow.

Author(s)

Arif Ullah

Developer & CEO