<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:og="http://ogp.me/ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:schema="http://schema.org/" xmlns:sioc="http://rdfs.org/sioc/ns#" xmlns:sioct="http://rdfs.org/sioc/types#" xmlns:skos="http://www.w3.org/2004/02/skos/core#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" version="2.0" xml:base="http://badzilla.co.uk/">
  <channel>
    <title>serverless</title>
    <link>http://badzilla.co.uk/</link>
    <description/>
    <language>en</language>
    
    <item>
  <title>Drupal 8 as a Static Site: AWS API Gateway, Lambda and SES Form Processing</title>
  <link>http://badzilla.co.uk/drupal-8-static-site-aws-api-gateway-lambda-and-ses-form-processing</link>
  <description>
&lt;span&gt;Drupal 8 as a Static Site: AWS API Gateway, Lambda and SES Form Processing&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Wed, 02/01/2019 - 10:38&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Serverless Installation&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The intention is to build our AWS ecosystem using the &lt;a href="https://serverless.com/"&gt;serverless&lt;/a&gt; product. This will enable us to configure our AWS provisioning in a YML file which is then translated into AWS CloudFormation orchestration. In the same codebase our PHP Lambda function can be built out. It isn't my intention to provide heavy documentation here since the Contact Form architecture was &lt;a href="http://badzilla.co.uk/drupal-8-static-site-contact-form-architecture"&gt;defined in an earlier blog&lt;/a&gt;, and I have previously written &lt;a href="http://badzilla.co.uk/real-world-php-lambda-app"&gt;many articles on the serverless / lambda / API Gateway&lt;/a&gt; combination of technologies to deliver HTTP content and handle form POSTs. &lt;/p&gt;
&lt;p&gt;Notwithstanding this, I will of course document points of interest along the way so it all makes sense! &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The first step is to install &lt;strong&gt;serverless&lt;/strong&gt; on your system. A dependency is node, so if you don't have that then please follow tutorials elsewhere on the Internet before executing the command below to install globally serverless.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;npm &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; serverless &lt;span style="color: #660033;"&gt;-g&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
We will be using Andy Raines' excellent PHP for AWS Lambda via Serverless Framework repo as our stating point. Issuing the following command will install our PHP serverless project into a directory called  d8-contact-form.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ serverless &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; &lt;span style="color: #660033;"&gt;--url&lt;/span&gt; https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;github.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;araines&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-php &lt;span style="color: #660033;"&gt;-n&lt;/span&gt; d8-contact-form
Serverless: Downloading and installing &lt;span style="color: #ff0000;"&gt;"serverless-php"&lt;/span&gt;...
Serverless: Successfully installed &lt;span style="color: #ff0000;"&gt;"d8-contact-form"&lt;/span&gt; &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
We then cd into the directory and list. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; d8-contact-form&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-las&lt;/span&gt;
total &lt;span style="color: #000000;"&gt;48&lt;/span&gt;
&lt;span style="color: #000000;"&gt;0&lt;/span&gt; drwxrwxr-x &lt;span style="color: #000000;"&gt;16&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;512&lt;/span&gt; Jan  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;14&lt;/span&gt; .
&lt;span style="color: #000000;"&gt;0&lt;/span&gt; drwxr-xr-x &lt;span style="color: #000000;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;448&lt;/span&gt; Jan  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;14&lt;/span&gt; ..
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rwxr-xr-x&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;660&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; buildphp.sh
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;569&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; CHANGELOG.md
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;430&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; composer.json
&lt;span style="color: #000000;"&gt;0&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;3&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout   &lt;span style="color: #000000;"&gt;96&lt;/span&gt; Jan  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;14&lt;/span&gt; config
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout &lt;span style="color: #000000;"&gt;1011&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; dockerfile.buildphp
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout   &lt;span style="color: #000000;"&gt;40&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; .gitattributes
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;120&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; .gitignore
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout &lt;span style="color: #000000;"&gt;1330&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; handler.js
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;829&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; handler.php
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout &lt;span style="color: #000000;"&gt;1103&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; LICENSE
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rwxr-xr-x&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;133&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; php
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout &lt;span style="color: #000000;"&gt;3705&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;14&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2018&lt;/span&gt; README.md
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout &lt;span style="color: #000000;"&gt;3008&lt;/span&gt; Jan  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;14&lt;/span&gt; serverless.yml
&lt;span style="color: #000000;"&gt;0&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;5&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  &lt;span style="color: #000000;"&gt;160&lt;/span&gt; Jan  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;14&lt;/span&gt; src&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Since I don't have Git LFS installed, the PHP executable hasn't been downloaded from the repo correctly. I will download this manually, and add it to the directory. Once completed, we can see it there with:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-lash&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;" php"&lt;/span&gt;
 27M &lt;span style="color: #660033;"&gt;-rwxr-xr-x&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;501&lt;/span&gt; dialout  27M Jan  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;22&lt;/span&gt; php&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now we need to install the PHP dependencies using composer. This does have a dependency on PHP 7.1. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ composer &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; &lt;span style="color: #660033;"&gt;-o&lt;/span&gt; &lt;span style="color: #660033;"&gt;--no-dev&lt;/span&gt;
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;getcomposer.org&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;xdebug
Loading composer repositories with package information
Updating dependencies
Package operations: &lt;span style="color: #000000;"&gt;9&lt;/span&gt; installs, &lt;span style="color: #000000;"&gt;0&lt;/span&gt; updates, &lt;span style="color: #000000;"&gt;0&lt;/span&gt; removals
  - Installing psr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;log &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;1.1.0&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
  - Installing monolog&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;monolog &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;1.24.0&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;polyfill-ctype &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v1.10.0&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Loading from cache
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;filesystem &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v4.2.1&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;config &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v4.2.1&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;contracts &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v1.0.2&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
  - Installing psr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;container &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;1.0.0&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Loading from cache
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dependency-injection &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v4.2.1&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;yaml &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v4.2.1&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: Downloading &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;         
Writing lock &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt;
Generating optimized autoload files&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Any Raines' code comes with a very basic Lambda function called &lt;strong&gt;hello&lt;/strong&gt;. To prove the environment is working correctly, we should invoke it locally (no need for deploying to AWS yet) and if everything is correct, it'll look like this:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ serverless invoke &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; hello
Got event &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"statusCode"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;200&lt;/span&gt;,
    &lt;span style="color: #ff0000;"&gt;"body"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Go Serverless v1.0! Your function executed successfully!"&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
In an &lt;a href="http://badzilla.co.uk/running-php-amazon-lambda-serverless"&gt;earlier blog&lt;/a&gt; I replaced the references of &lt;strong&gt;Hello&lt;/strong&gt; with &lt;strong&gt;demo&lt;/strong&gt;. I have changed it to &lt;strong&gt;D8ContactForm&lt;/strong&gt; for the contact form. By deploying the code to AWS, and submitting the contact form, you will see the same screenshot as shown at the end of the &lt;a href="http://badzilla.co.uk/drupal-8-static-site-drupal-8-contact-form"&gt;previous blog. &lt;/a&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;SES Validation of email address&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-03/Screenshot%202019-03-24%20at%2012.53.48.png?itok=VklpZIXH 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-03/Screenshot%202019-03-24%20at%2012.53.48.png?itok=w6rR8Bo2 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-03/Screenshot%202019-03-24%20at%2012.53.48.png?itok=Pt0JuZRW 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-03/Screenshot%202019-03-24%20at%2012.53.48.png?itok=wYgkoMN1 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-03/Screenshot%202019-03-24%20at%2012.53.48.png?itok=VklpZIXH" alt="Email address validation" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-03/Screenshot%202019-03-24%20at%2013.03.04-edited.png?itok=gDIdr5NA 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-03/Screenshot%202019-03-24%20at%2013.03.04-edited.png?itok=4U2cM8Hw 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-03/Screenshot%202019-03-24%20at%2013.03.04-edited.png?itok=Y1AhIOSK 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-03/Screenshot%202019-03-24%20at%2013.03.04-edited.png?itok=8YS9rsXw 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-03/Screenshot%202019-03-24%20at%2013.03.04-edited.png?itok=gDIdr5NA" alt="Verification completed" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;To use the AWS SES service, your email address will need to be verified. This is easy - navigate to Simple Email Service and click on email addresses, then "Verify a new email address". Add the email address and a verification email message will be sent for you to click back and confirm the verification process. Once verified, you'll see the second screenshot above. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Serverless configuration&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The next step is to add the SES configuration to the &lt;strong&gt;serverless.yml&lt;/strong&gt; file. Add a custom area for your own variables - in this case the email address.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;custom:
  SENDER_EMAIL: xxxx&lt;span style="color: #000000; font-weight: bold;"&gt;@&lt;/span&gt;xxxxxxxx
  RECIPIENT_EMAIL: xxxx&lt;span style="color: #000000; font-weight: bold;"&gt;@&lt;/span&gt;xxxxxxxx&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
And add the SES config to the provider area so it looks like this in its entirety:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
  environment:
    SENDER: &lt;span style="color: #800000;"&gt;${self:custom.SENDER_EMAIL}&lt;/span&gt;
    RECIPIENT: &lt;span style="color: #800000;"&gt;${self:custom.RECIPIENT_EMAIL}&lt;/span&gt;
    DOMAIN: &lt;span style="color: #ff0000;"&gt;"*"&lt;/span&gt;
  iamRoleStatements:
    - Effect: &lt;span style="color: #ff0000;"&gt;"Allow"&lt;/span&gt;
      Action:
        - &lt;span style="color: #ff0000;"&gt;"ses:SendEmail"&lt;/span&gt;
      Resource: &lt;span style="color: #ff0000;"&gt;"*"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Then deploy
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Add AWS SDK to the codebase using composer&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The SDK will make it much easier to build out the SES interface code and can be installed to the codebase in the usual composer way
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ composer require aws&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;aws-sdk-php
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;getcomposer.org&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;xdebug
Using version ^&lt;span style="color: #000000;"&gt;3.90&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; aws&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;aws-sdk-php
.&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;composer.json has been updated&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Add SDK PHP required libraries&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The AWS PHP SDK requires the &lt;strong&gt;filter and simplexml&lt;/strong&gt; libraries that aren't in the PHP executable we deploy to AWS by default. Thankfully there is a way of recompiling the PHP executable and I covered this in &lt;a href="http://badzilla.co.uk/recompiling-php-serverless-php-and-lambda"&gt;an earlier blog.&lt;/a&gt; So the tl;dr is &lt;ul&gt;
&lt;li&gt;Add the filter and simplexml libraries to dockerfile.buildphp&lt;/li&gt;
&lt;li&gt;Make a note of the php creation date and filesize.
&lt;/li&gt;&lt;li&gt;Make sure buildphp.sh is executable on the command line and run it.&lt;/li&gt;
&lt;ul&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Add the Serverless and SDK handler code&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now the AWS SDK is in the code base we can build out the functionality to integrate the SDK. Our first work is to ensure that the recipient and sender email addresses are available to the code. To achieve this, they were defined in the &lt;strong&gt;serverless.yml&lt;/strong&gt; in the environment section which can be picked up in &lt;strong&gt;handler.php&lt;/strong&gt; and assigned to the &lt;strong&gt;$event&lt;/strong&gt; array which is made available to the handler class. Add the following lines before the call to handle
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'sender_email'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #0000BB"&gt;getenv&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'SENDER'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'recipient_email'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #0000BB"&gt;getenv&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'RECIPIENT'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
Now the handler itself. A few things to note. &lt;ul&gt;&lt;li&gt;I have added the necessary &lt;strong&gt;use&lt;/strong&gt; clauses to the AWS SDK client and the exception class&lt;/li&gt;&lt;li&gt;The protected &lt;strong&gt;$client_config&lt;/strong&gt; holds the configuration we have - but note that further down I am getting the credentials from the &lt;strong&gt;CredentialProvider&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;The recipients are an array and so it is possible if required to add multiples here.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;strong&gt;D8ContactFormHandler.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Raines&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Serverless&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;require &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Ses&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;SesClient&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;AwsException&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;D8ContactFormHandler &lt;/span&gt;&lt;span style="color: #007700"&gt;implements &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Handler&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;    protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$client_config &lt;/span&gt;&lt;span style="color: #007700"&gt;= [&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'region' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'eu-west-1'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'version' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'2010-12-01'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'credentials.cache' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;TRUE&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'validation' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;FALSE&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;    ];&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * {@inheritdoc}&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;handle&lt;/span&gt;&lt;span style="color: #007700"&gt;(array &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Context $context&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$context&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getLogger&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Comment out for debugging&lt;br /&gt;        //$logger-&gt;notice('Got event', $event);&lt;br /&gt;&lt;br /&gt;        // Set up AWS SDK&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'credentials'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Credentials&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;CredentialProvider&lt;/span&gt;&lt;span style="color: #007700"&gt;::&lt;/span&gt;&lt;span style="color: #0000BB"&gt;env&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$SesClient &lt;/span&gt;&lt;span style="color: #007700"&gt;= new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;SesClient&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$sender_email &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'sender_email'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$recipient_emails&lt;/span&gt;&lt;span style="color: #007700"&gt;[] = &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'recipient_email'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;&lt;br /&gt;        return [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;200&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'body' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Go Serverless v1.0! Your function executed successfully!'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        ];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Email generation&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now we can insert the code to actually generate the email. All of this is self evident and really doesn't need further commentary from me. It should be inserted just before the return statement. &lt;br /&gt;
&lt;strong&gt;D8ContactFormHandler.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Process the submitted form.&lt;br /&gt;        // *TODO* This could do with more validation.&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields &lt;/span&gt;&lt;span style="color: #007700"&gt;= [];&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;parse_str&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'body'&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        if (!isset(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'name'&lt;/span&gt;&lt;span style="color: #007700"&gt;])) &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'name'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'{unknown name}'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        if (!isset(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'mail'&lt;/span&gt;&lt;span style="color: #007700"&gt;])) &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'mail'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'{unknown email address}'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        if (!isset(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'subject'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;])) &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'subject'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'{unknown subject}'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        if (!isset(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'message'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;])) &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'message'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'{unknown message}'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$subject &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'[badzilla.co.uk website feedback] '&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'subject'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$plaintext_body &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'From: '&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'name'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'  '&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'mail'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Subject: '&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'subject'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;' Message: '&lt;/span&gt;&lt;span style="color: #007700"&gt;. &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'message'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$html_body &lt;/span&gt;&lt;span style="color: #007700"&gt;=  &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;h1&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'subject'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;/h1&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;h2&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'From: '&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'name'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'  &lt;a href="mailto:"'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'mail'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'"&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'mail'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;/a&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;/h2&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;p&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fields&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'message'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'value'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'&lt;/p&gt;'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$char_set &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'UTF-8'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$result &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$SesClient&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;sendEmail&lt;/span&gt;&lt;span style="color: #007700"&gt;([&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Destination' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ToAddresses' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$recipient_emails&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                ],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ReplyToAddresses' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$sender_email&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Source' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$sender_email&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Message' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Body' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Html' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Charset' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$char_set&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Data' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$html_body&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                        ],&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Text' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Charset' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$char_set&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Data' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$plaintext_body&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                        ],&lt;br /&gt;                    ],&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Subject' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Charset' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$char_set&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Data' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$subject&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                    ],&lt;br /&gt;                ],&lt;br /&gt;            ]);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$messageId &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$result&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'MessageId'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        } catch (&lt;/span&gt;&lt;span style="color: #0000BB"&gt;AwsException $e&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// output error message if fails&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;notice&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Message'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getMessage&lt;/span&gt;&lt;span style="color: #007700"&gt;());&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;notice&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'AWS Message'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getAwsErrorMessage&lt;/span&gt;&lt;span style="color: #007700"&gt;());&lt;br /&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Redirect to thank you page&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Once we've sent the email we want to redirect back to our thank you page. This is done with a 307 code which preserves the original POSTed values so they can be used on the forwarded page. Our use will be to make the message personalised. I have decided that I would like my redirect back to my originating page, but of course you could customise it as you see fit. For my case, I use the Referer header. The code below replaces the existing return functionality.&lt;br /&gt;
&lt;strong&gt;D8 ContactFormHandler.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;return [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Location' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Referer'&lt;/span&gt;&lt;span style="color: #007700"&gt;]],&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;307&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        ];&lt;br /&gt;&lt;/&lt;/span&gt;&lt;span style="color: #0000BB"&gt;codE&lt;/span&gt;&lt;span style="color: #007700"&gt;&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Debugging&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-03/Screenshot%202019-03-24%20at%2018.22.11.png?itok=LTjE38Bn 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2019-03/Screenshot%202019-03-24%20at%2018.22.11.png?itok=uyEGnya5 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2019-03/Screenshot%202019-03-24%20at%2018.22.11.png?itok=KbaNuSz5 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2019-03/Screenshot%202019-03-24%20at%2018.22.11.png?itok=BRx1-OBf 2552w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2019-03/Screenshot%202019-03-24%20at%2018.22.11.png?itok=LTjE38Bn" alt="CloudWatch" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;During the development process you will have to do multiple deploys and doubtless you will get numerous error responses from AWS. The best way of working these issues is to use CloudWatch, and a sample screenshot is shown above. The codebase has an excellent logging facility to check variables and these are written out to CloudWatch. Have a look at:&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;notice&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Got event'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
This can be amended for whatever you need to interrogate, but remember the second parameter must be an array.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Git Repository&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The entire codebase discussed here is at &lt;a href="https://github.com/sanddevil/serverless-php-contact-form"&gt;https://github.com/sanddevil/serverless-php-contact-form&lt;/a&gt; - if you wish to extend its functionality, please send me a pull request. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/static-site" hreflang="en"&gt;Static Site&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/drupal" hreflang="en"&gt;Drupal&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/drupal8" hreflang="en"&gt;Drupal 8&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/development" hreflang="en"&gt;Development&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Wed, 02 Jan 2019 10:38:46 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">164 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 7: Load Testing with serverless-artillery</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-7-load-testing-serverless-artillery</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 7: Load Testing with serverless-artillery&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Thu, 12/04/2018 - 09:05&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Load testing is an important aspect of delivering an enterprise solution. Load testing can monitor the system's response times for each of the transactions during a set period of time. Load testing can also raise attention to any problems in the application software and fix these bottlenecks before they become more problematic. &lt;/p&gt;
&lt;p&gt;So we've established that load testing is necessary. Tools for load testing Lambda functions are scarce, but there is serverless-artillery, which is of course based on the artillery nodejs application. So this is our choice for load testing our voting app. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Installing serverless-artillery&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;First step is to install globally the parent &lt;strong&gt;artillery&lt;/strong&gt; app
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;npm &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; &lt;span style="color: #660033;"&gt;-g&lt;/span&gt; artillery&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now lets install &lt;strong&gt;serverless-artillery&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;npm &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; &lt;span style="color: #660033;"&gt;-g&lt;/span&gt; serverless-artillery&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
And let's see what we've got on our system after that
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-als&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;local&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;node_modules&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
total &lt;span style="color: #000000;"&gt;48&lt;/span&gt;
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxr-xr-x &lt;span style="color: #000000;"&gt;12&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;11&lt;/span&gt; .
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxr-xr-x  &lt;span style="color: #000000;"&gt;6&lt;/span&gt; root  root     &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;17&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; ..
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;7&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;10&lt;/span&gt;:07 artillery
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;17&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; casper-chai
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;9&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;17&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; casperjs
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;6&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;30&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; localtunnel
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;6&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;17&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; mocha
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;17&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; mocha-casperjs
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Nov &lt;span style="color: #000000;"&gt;26&lt;/span&gt; &lt;span style="color: #000000;"&gt;19&lt;/span&gt;:&lt;span style="color: #000000;"&gt;30&lt;/span&gt; n
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x &lt;span style="color: #000000;"&gt;11&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Nov &lt;span style="color: #000000;"&gt;26&lt;/span&gt; &lt;span style="color: #000000;"&gt;19&lt;/span&gt;:&lt;span style="color: #000000;"&gt;26&lt;/span&gt; npm
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;6&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Dec &lt;span style="color: #000000;"&gt;23&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;15&lt;/span&gt; serverless
&lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;6&lt;/span&gt; nigel www-data &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;10&lt;/span&gt; serverless-artillery&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Your directory listing of the available packages will obviously be different - but it looks like we are good to go.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Configuring serverless-artillery&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We now need a home for our serverless-artillery configuration. I opted (perhaps confusingly) to create a directory called serverless-artillery in the usual place for my projects - /var/www/html. Once that is created, we can run the configure command.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; serverless-artillery
$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; serverless-artillery
$ slsart configure&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now if we look at the directory we can see the normal artefacts we would expect in a severless project.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-las&lt;/span&gt;
total &lt;span style="color: #000000;"&gt;112&lt;/span&gt;
 &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x   &lt;span style="color: #000000;"&gt;3&lt;/span&gt; nigel    www-data  &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;27&lt;/span&gt; .
 &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x  &lt;span style="color: #000000;"&gt;17&lt;/span&gt; www-data www-data  &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;16&lt;/span&gt; ..
&lt;span style="color: #000000;"&gt;48&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-rw-r--&lt;/span&gt;   &lt;span style="color: #000000;"&gt;1&lt;/span&gt; nigel    www-data &lt;span style="color: #000000;"&gt;46843&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;27&lt;/span&gt; handler.js
 &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxrwxr-x &lt;span style="color: #000000;"&gt;152&lt;/span&gt; nigel    www-data  &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;27&lt;/span&gt; node_modules
 &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-rw-r--&lt;/span&gt;   &lt;span style="color: #000000;"&gt;1&lt;/span&gt; nigel    www-data   &lt;span style="color: #000000;"&gt;222&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;27&lt;/span&gt; package.json
&lt;span style="color: #000000;"&gt;44&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-rw-r--&lt;/span&gt;   &lt;span style="color: #000000;"&gt;1&lt;/span&gt; nigel    www-data &lt;span style="color: #000000;"&gt;41915&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;27&lt;/span&gt; package-lock.json
 &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-rw-r--&lt;/span&gt;   &lt;span style="color: #000000;"&gt;1&lt;/span&gt; nigel    www-data  &lt;span style="color: #000000;"&gt;1329&lt;/span&gt; Apr &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;11&lt;/span&gt;:&lt;span style="color: #000000;"&gt;27&lt;/span&gt; serverless.yml&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
The &lt;strong&gt;serverless.yml&lt;/strong&gt; needs editing because the AWS region is completely missing so it will default to us-east-1 unless we change it.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;head&lt;/span&gt; &lt;span style="color: #660033;"&gt;-20&lt;/span&gt; serverless.yml &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;tail&lt;/span&gt; &lt;span style="color: #660033;"&gt;-6&lt;/span&gt;
provider: &lt;span style="color: #666666; font-style: italic;"&gt;# Using Node JS v4.3 on AWS&lt;/span&gt;
  name: aws
  region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
  runtime: nodejs6.10
  iamRoleStatements:
    - Effect: &lt;span style="color: #ff0000;"&gt;"Allow"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Above you can see I have now added a region of eu-west-1 which reflects the region I am operating out of.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Deploying the serverless-artillery Lambda Function&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2014.43.47.png?itok=5rjsrGig 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2014.43.47.png?itok=XVzdTCUo 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2014.43.47.png?itok=uHSJNnfW 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2014.43.47.png?itok=0wEQWQKB 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2014.43.47.png?itok=5rjsrGig" alt="Deployed function" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Something I hadn't appreciated when I first installed and configured serverless-artillery is that it is a standalone Lambda function in its own right. I assumed incorrectly it somehow was attached to a pre-existing Lambda function as a plugin. The documentation for serverless-artillery didn't make this clear so I added a GitHub issue and the problem will be addressed by the project's maintainer. So now we know it's a standalone function, it needs deploying. The deployment is a little different - see below. The screenshot above shows the function listed on the AWS console. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ slsart deploy
 
	Deploying Lambda to AWS...
 
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3 &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;5.45&lt;/span&gt; MB&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...............
Serverless: Stack update finished...
Service Information
service: serverless-artillery-Bk1YNhhsM
stage: dev
region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
stack: serverless-artillery-Bk1YNhhsM-dev
api keys:
  None
endpoints:
  None
functions:
  loadGenerator: serverless-artillery-Bk1YNhhsM-dev-loadGenerator
 
	Deploy complete.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Create New 'test' Stage&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.31.26.png?itok=x0hhfPuD 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.31.26.png?itok=gWxQueMM 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.31.26.png?itok=dxobLqxm 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.31.26.png?itok=8ZA1Wo1d 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.31.26.png?itok=x0hhfPuD" alt="Test Lambda Functions" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now would be a really good time to create a new stage called &lt;strong&gt;test&lt;/strong&gt; to keep my testing environment separate from my development stage. To enable us to take advantage of the ability to flip between different stages on the command line, we have to make a minor change to the &lt;strong&gt;serverless.yml&lt;/strong&gt; file. Change the stage to the output from the cat / grep combination below. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-vote
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; serverless.yml &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; stage &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; dev
  stage: &lt;span style="color: #800000;"&gt;${opt:stage, 'dev'}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
This effectively means take the stage from the command line option &lt;strong&gt;stage&lt;/strong&gt; but if that doesn't exist, use &lt;strong&gt;dev&lt;/strong&gt; as the default. Now we can do a regular deploy with a switch for the stage. Don't forget we will also need to sync assets for our new test stage. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls deploy &lt;span style="color: #660033;"&gt;--stage&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt; &lt;span style="color: #660033;"&gt;--no-color&lt;/span&gt;
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3 &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;12.53&lt;/span&gt; MB&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...........................................................................
Serverless: Stack update finished...
Service Information
service: vote
stage: &lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt;
region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
stack: vote-test
api keys:
  None
endpoints:
  GET - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;bnz9qsvtm1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
  POST - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;bnz9qsvtm1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
  POST - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;bnz9qsvtm1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;test&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;thank_you
functions:
  vote_get: vote-test-vote_get
  vote_post: vote-test-vote_post
  thank_you: vote-test-thank_you
$ sls syncToS3 &lt;span style="color: #660033;"&gt;--stage&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt;
Serverless: s3,&lt;span style="color: #c20cb9; font-weight: bold;"&gt;sync&lt;/span&gt;,dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;,s3:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;vote-test-webapps3bucket-ncaevy1jcsry&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
upload: dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;favicon.ico to s3:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;vote-test-webapps3bucket-ncaevy1jcsry&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;favicon.ico
upload: dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;css&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;default.css to s3:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;vote-test-webapps3bucket-ncaevy1jcsry&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;css&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;default.css
upload: dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;badzilla-logo32x32.png to s3:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;vote-test-webapps3bucket-ncaevy1jcsry&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;badzilla-logo32x32.png
 
Serverless: stderr undefined
Serverless: Successfully synced to the S3 bucket&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
It should now be possible to point a web browser at the url provided by AWS, and by navigating to the Lambda function list on the AWS console, the test stage functions can be seen (see screenshot above).&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Auto Scale DynamoDB&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.34.46.png?itok=TEM5avYq 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.34.46.png?itok=clhPByvy 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.34.46.png?itok=7BGwI9RJ 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.34.46.png?itok=3KaIG6PB 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2016.34.46.png?itok=TEM5avYq" alt="DynamoDB Auto Scaling" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;We are going to load test the vote_post function, so we should ensure that the DynamoDB Auto Scaling feature is enabled, along with minimum and maximum read and write capacity parameters. Navigate to Services-&gt;DynamoDB-&gt;Tables-&gt;{vote_test}-&gt;Capacity and you can see in the screenshot above I've elected to put the minimum capacity for read and writes to by 10 per second. I am not intending to really stretch DynamoDB too far for my load testing since this is a hobby project and DynamoDB costs can escalate out of hand quickly without prudence. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Create the Artillery Script&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;serverless-artillery uses Artillery scripts to run load tests. They are easy to create and are constructed in yml format. Below is the script for our vote_post function load test. We are going to simulate the submission of our POSTed vote form multiple time. Note that despite the test will be run from our &lt;strong&gt;serverless-artillery&lt;/strong&gt; directory, I have created the script in the &lt;strong&gt;serverless-vote&lt;/strong&gt; directory so it is included in our vote project's git repo. 
&lt;strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;pwd&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-vote
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; artillery
$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; artillery
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; vote_post.yml
config:
  &lt;span style="color: #666666; font-style: italic;"&gt;# this hostname will be used as a prefix for each URI in the flow unless a complete URI is specified&lt;/span&gt;
  target: &lt;span style="color: #ff0000;"&gt;"https://bnz9qsvtm1.execute-api.eu-west-1.amazonaws.com"&lt;/span&gt;
  phases:
    - duration: &lt;span style="color: #000000;"&gt;300&lt;/span&gt;
      arrivalRate: &lt;span style="color: #000000;"&gt;1&lt;/span&gt;
      rampTo: &lt;span style="color: #000000;"&gt;10&lt;/span&gt;
scenarios:
  - name: &lt;span style="color: #ff0000;"&gt;"Post form"&lt;/span&gt;
    flow:
      - post:
          url: &lt;span style="color: #ff0000;"&gt;"/test"&lt;/span&gt;
          form:
            first_name: &lt;span style="color: #ff0000;"&gt;"Fred"&lt;/span&gt;
            last_name: &lt;span style="color: #ff0000;"&gt;"Blogs"&lt;/span&gt;
            optradio: &lt;span style="color: #ff0000;"&gt;"phpstorm"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/strong&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Running the Load Test&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now the time has come to execute our test. We navigate back to the &lt;strong&gt;serverless-artillery&lt;/strong&gt; directory and invoke the Lambda function with a path back to our yml script.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; ..&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-artillery&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
$ slsart invoke &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; ..&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-vote&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;artillery&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;vote_post.yml 
 
	Invoking &lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt; Lambda
 
 
	Your &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; has been invoked. The load is scheduled to be completed &lt;span style="color: #000000; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #000000;"&gt;300&lt;/span&gt; seconds.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Ok so now our test will run for five minutes.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Analysing the Load Test Results&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.15.36.png?itok=Of160Z4y 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.15.36.png?itok=CGT3U-Mp 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.15.36.png?itok=mVodArBD 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.15.36.png?itok=sQY5Ym40 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.15.36.png?itok=Of160Z4y" alt="DynamoDB Overview" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.04.png?itok=KeIUD6mv 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.04.png?itok=2P9ADS9K 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.04.png?itok=vEwZtKTP 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.04.png?itok=K2OhAYWt 1828w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.04.png?itok=KeIUD6mv" alt="DynamoDB Detail" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.18.png?itok=KJIzs_xT 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.18.png?itok=g8IwHrm9 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.18.png?itok=nEykWnxf 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.18.png?itok=v3dqyTiX 2462w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.16.18.png?itok=KJIzs_xT" alt="DynamoDB List Items" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.17.20.png?itok=xEHtqK_v 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.17.20.png?itok=cPuEHtfy 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.17.20.png?itok=0_Q8Vugy 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.17.20.png?itok=-JOsjmM2 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-13%20at%2017.17.20.png?itok=xEHtqK_v" alt="Lambda Metrics" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Once the load test completes there are monitoring screens that can be examined to determine the results. By navigating to the &lt;em&gt;Metrics&lt;/em&gt; tab on the AWS Console DynamoDB vote_test, we can see the topmost screenshot above. The red line on the graph indicates where I have set the minimum provisioning thresholds. If we look at the Write Capacity metric we can also see a small blue line of the number of writes per second during the test. We didn't quite achieve ten per second. It's also useful to look at the rightmost metric - Throttled Write Requests. Thankfully the count is zero and this is important. I have noticed empirically that with throttling, there comes a nasty side effect - the AWS SDK &lt;em&gt;putItem&lt;/em&gt; can timeout thus causing an exception to be thrown in the model code. &lt;/p&gt;
&lt;p&gt;The second screenshot shows a zoomed view of the Write Capacity with five minute intervals. The most writes per second reached 8 diring our test. &lt;/p&gt;
&lt;p&gt;By navigating to the &lt;em&gt;Items&lt;/em&gt; tab (screenshot 3) we can see that we have a whole swathe of records that have been created in the DynamoDB database - this is exactly what we would expect. &lt;/p&gt;
&lt;p&gt;Next we navigate to Services-&gt;Lambda-&gt;Functions-&gt;{vote_test_vote_post}-&gt;Monitoring and we can see three metrics - all of which are important. We achieved over 1500 invocations of the function in the five minutes (leftmost graphic). The Invocation Duration is interesting - we averaged a completion time of 67 milliseconds which is very fast. There was a maximum of 343 milliseconds - still very acceptable, and clearly juding where the maximum peak is in comparison to the average, there can't have been too many functions that were near the top end of that maximum. The rightmost metric - Invocation Errors - is crucial. If we got time outs caused by DynamoDB write throttling, we would see some activity on this metric. Thankfully there is nothing so we know all is good. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;br /&gt;We can also use the command line - for instance to get the number of records created during the run we can issue:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws dynamodb scan &lt;span style="color: #660033;"&gt;--table-name&lt;/span&gt;=vote_test
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;snipped output&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
            &lt;span style="color: #ff0000;"&gt;"optradio"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"phpstorm"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"datetime"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"2018-04-13T16:10:18"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"surname"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Blogs"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"id"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"6949cf80-336f-4536-a86d-4be164861597"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"forename"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Fred"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;, 
    &lt;span style="color: #ff0000;"&gt;"ScannedCount"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;1596&lt;/span&gt;, 
    &lt;span style="color: #ff0000;"&gt;"ConsumedCapacity"&lt;/span&gt;: null
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Hopefully this has given you a good taster for using artillery and serverless-artillery. As you can see, it really is quite easy.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Thu, 12 Apr 2018 08:05:09 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">143 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 6: Local Development</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-6-local-development</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 6: Local Development&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Tue, 10/04/2018 - 09:31&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;One of the drawbacks of developing AWS Lambda apps is the time it takes to deploy any changes to code. In addition there are financial costs to repeatedly uploading the lambda executable to an AWS S3 bucket, exacerbated by the need in our case to upload a PHP image. The upload triggers GET Lambda costs and storage costs so it is a double whammy. &lt;/p&gt;
&lt;p&gt;Ideally a development regime should be implemented whereby most development is undertaken locally and only deployed to AWS when the developer has a high degree of confidence there are no outstanding bugs. &lt;/p&gt;
&lt;p&gt;In an earlier &lt;a href="http://badzilla.co.uk/real-world-php-lambda-app-part-4-setting-dynamodb-locally"&gt;blog&lt;/a&gt; we discussed how to set up a local copy of DynamoDB - so now we have the ammunition to perform our development locally. Up until now I have been spoon-feeding all my code - but in reality development is an iterative process of building out functionality and fixing bugs. Let's see how we can do this. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Persist Local DynamoDB Data&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;For us to do anything meaningful we are really going to have to persist our DynamoDB data. The earlier blog started the local instance of DynamoDB with the -inMemory flag. Let's check it isn't still running before we do anything:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ps&lt;/span&gt; &lt;span style="color: #660033;"&gt;-ef&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;
nigel     &lt;span style="color: #000000;"&gt;1142&lt;/span&gt;     &lt;span style="color: #000000;"&gt;1&lt;/span&gt;  &lt;span style="color: #000000;"&gt;0&lt;/span&gt; Apr09 ?        00:00:00 &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;daemon &lt;span style="color: #660033;"&gt;--name&lt;/span&gt;=jenkins &lt;span style="color: #660033;"&gt;--inherit&lt;/span&gt; &lt;span style="color: #660033;"&gt;--env&lt;/span&gt;=&lt;span style="color: #007800;"&gt;JENKINS_HOME&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins &lt;span style="color: #660033;"&gt;--output&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;log&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins.log &lt;span style="color: #660033;"&gt;--pidfile&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;run&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins.pid &lt;span style="color: #660033;"&gt;--&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt; -Djava.awt.headless=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;true&lt;/span&gt; &lt;span style="color: #660033;"&gt;-jar&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;share&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins.war &lt;span style="color: #660033;"&gt;--webroot&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;cache&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;war &lt;span style="color: #660033;"&gt;--httpPort&lt;/span&gt;=&lt;span style="color: #000000;"&gt;8080&lt;/span&gt;
nigel     &lt;span style="color: #000000;"&gt;1143&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1142&lt;/span&gt;  &lt;span style="color: #000000;"&gt;0&lt;/span&gt; Apr09 ?        00:07:&lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt; -Djava.awt.headless=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;true&lt;/span&gt; &lt;span style="color: #660033;"&gt;-jar&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;share&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins.war &lt;span style="color: #660033;"&gt;--webroot&lt;/span&gt;=&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;cache&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jenkins&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;war &lt;span style="color: #660033;"&gt;--httpPort&lt;/span&gt;=&lt;span style="color: #000000;"&gt;8080&lt;/span&gt;
nigel     &lt;span style="color: #000000;"&gt;8748&lt;/span&gt;  &lt;span style="color: #000000;"&gt;8694&lt;/span&gt;  &lt;span style="color: #000000;"&gt;0&lt;/span&gt; &lt;span style="color: #000000;"&gt;10&lt;/span&gt;:&lt;span style="color: #000000;"&gt;13&lt;/span&gt; pts&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;1&lt;/span&gt;    00:00:00 &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #660033;"&gt;--color&lt;/span&gt;=auto &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Ok so whilst the Java runtime is there - it actually corresponds to my Jenkins server and not DynamoDB.  So lets start DynamoDB with a path to a directory where we want the database file to be. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dynamodb&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt; -Djava.library.path=.&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;DynamoDBLocal_lib &lt;span style="color: #660033;"&gt;-jar&lt;/span&gt; DynamoDBLocal.jar &lt;span style="color: #660033;"&gt;-sharedDb&lt;/span&gt; &lt;span style="color: #660033;"&gt;-dbPath&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;home&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;nigel
Initializing DynamoDB Local with the following configuration:
Port:	&lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
InMemory:	&lt;span style="color: #c20cb9; font-weight: bold;"&gt;false&lt;/span&gt;
DbPath:	&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;home&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;nigel
SharedDb:	&lt;span style="color: #c20cb9; font-weight: bold;"&gt;true&lt;/span&gt;
shouldDelayTransientStatuses:	&lt;span style="color: #c20cb9; font-weight: bold;"&gt;false&lt;/span&gt;
CorsParams:	&lt;span style="color: #000000; font-weight: bold;"&gt;*&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now let's create our database.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws dynamodb create-table &lt;span style="color: #660033;"&gt;--table-name&lt;/span&gt;=vote_dev &lt;span style="color: #660033;"&gt;--attribute-definitions&lt;/span&gt; &lt;span style="color: #007800;"&gt;AttributeName&lt;/span&gt;=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;id&lt;/span&gt;,&lt;span style="color: #007800;"&gt;AttributeType&lt;/span&gt;=S &lt;span style="color: #660033;"&gt;--key-schema&lt;/span&gt; &lt;span style="color: #007800;"&gt;AttributeName&lt;/span&gt;=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;id&lt;/span&gt;,&lt;span style="color: #007800;"&gt;KeyType&lt;/span&gt;=HASH &lt;span style="color: #660033;"&gt;--provisioned-throughput&lt;/span&gt; &lt;span style="color: #007800;"&gt;ReadCapacityUnits&lt;/span&gt;=&lt;span style="color: #000000;"&gt;5&lt;/span&gt;,&lt;span style="color: #007800;"&gt;WriteCapacityUnits&lt;/span&gt;=&lt;span style="color: #000000;"&gt;5&lt;/span&gt;  &lt;span style="color: #660033;"&gt;--endpoint-url&lt;/span&gt; http:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;localhost:&lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"TableDescription"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
        &lt;span style="color: #ff0000;"&gt;"TableArn"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"arn:aws:dynamodb:ddblocal:000000000000:table/vote_dev"&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"AttributeDefinitions"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"AttributeName"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"id"&lt;/span&gt;, 
                &lt;span style="color: #ff0000;"&gt;"AttributeType"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"ProvisionedThroughput"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
            &lt;span style="color: #ff0000;"&gt;"NumberOfDecreasesToday"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"WriteCapacityUnits"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;5&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"LastIncreaseDateTime"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0.0&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"ReadCapacityUnits"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;5&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"LastDecreaseDateTime"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0.0&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"TableSizeBytes"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"TableName"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"vote_dev"&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"TableStatus"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"ACTIVE"&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"KeySchema"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"KeyType"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"HASH"&lt;/span&gt;, 
                &lt;span style="color: #ff0000;"&gt;"AttributeName"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"id"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"ItemCount"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"CreationDateTime"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;1523353381.749&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Check the database is there ok
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws dynamodb list-tables &lt;span style="color: #660033;"&gt;--endpoint-url&lt;/span&gt; http:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;localhost:&lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"TableNames"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
        &lt;span style="color: #ff0000;"&gt;"vote_dev"&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Setting the DynamoDB Endpoint in AWS PHP SDK&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Under normal circumstances (i.e. when doing regular deploys to AWS) the DynamoDB endpoint doesn't need to be specified in the AWS PHP SDK. However when we are developing locally, the SDK does need to know where we have our local instance running. To achieve that we need to set the endpoint in the client configuration. The line of code would look like:
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'endpoint' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'http://localhost:8000'&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
This needs to be added to the existing client configuration but must be set conditionally, i.e. only when we are running locally. So that means we can't do &lt;br /&gt;
&lt;strong&gt;VoteModel.php **WRONG**&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$client_config &lt;/span&gt;&lt;span style="color: #007700"&gt;= [&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'region' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'eu-west-1'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'version' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'2012-08-10'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'credentials.cache' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;TRUE&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'validation' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;FALSE&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'endpoint' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'http://localhost:8000'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'scheme' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'http'&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
We could create a new custom environment variable and surface it at the DynamoDB client creation step. But we already have a candidate - the &lt;strong&gt;stage&lt;/strong&gt; variable can be used - and we could create a fictitious new stage of &lt;strong&gt;local&lt;/strong&gt; to be used in a conditional. &lt;br /&gt;
&lt;strong&gt;VoteModel.php **CORRECT**&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;loadClient&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'credentials'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Credentials&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;CredentialProvider&lt;/span&gt;&lt;span style="color: #007700"&gt;::&lt;/span&gt;&lt;span style="color: #0000BB"&gt;env&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;        if (&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;] == &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'local'&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'endpoint'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'http://localhost:8000'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        }&lt;br /&gt;        return(new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDbClient&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Creating the Lambda Data&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.30.09-processed.png?itok=6gnrNTPn 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.30.09-processed.png?itok=lJROK1vY 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.30.09-processed.png?itok=YaYYkGdH 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.30.09-processed.png?itok=MZe-79Fe 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.30.09-processed.png?itok=6gnrNTPn" alt="Cloudwatch List" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.42.37.png?itok=7fjtjW0_ 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.42.37.png?itok=NlM8xpCY 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.42.37.png?itok=suALv1VS 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.42.37.png?itok=sjDeG5RO 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.42.37.png?itok=7fjtjW0_" alt="Cloudwatch Log list" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.46.20.png?itok=0TxqfRe6 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.46.20.png?itok=uvalY-GA 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.46.20.png?itok=auA9hTXm 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.46.20.png?itok=VTS1CQGX 2008w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2010.46.20.png?itok=0TxqfRe6" alt="JSON dump" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;When we invoke a Lambda function locally, we need to ensure the environment is set up correctly for it. This includes the routing information (since we don't have a local copy of API Gateway) and the run time data that the Lambda function will be asked to process. In our case that would be the submitted POSTed form data. So how do we build this? We can handcraft some JSON which includes all this information, but it's time consuming. A much easier approach is to copy the data directly from a previous AWS invocation in the CloudWatch logs - this is where our &lt;em&gt;Got event&lt;/em&gt; debug trace pays dividends! &lt;/p&gt;
&lt;p&gt;Navigate to the Cloudwatch logs and you'll see a list of all the Lambda functions (see first screenshot above). Select the form POST function which in my case is /aws/lambda/vote-dev-vote_post. This takes us to the list of previous invocations (second screenshot) - I've done quite a lot which is a side effect of blogging! Select the top one and open up a &lt;em&gt;Got event&lt;/em&gt; log entry (third screenshot). Select the dumped JSON object and copy it to your clipboard. &lt;/p&gt;
&lt;p&gt;This can then be saved in a file. I created a new subdirectory under the project's top directory called &lt;em&gt;data&lt;/em&gt; and I named this file &lt;em&gt;post.json&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Set the Stage&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now edit the &lt;strong&gt;post.json&lt;/strong&gt; file so that the stage is set to local - see below &lt;br /&gt;
&lt;strong&gt;data/post.json&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #ff0000;"&gt;"stage"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"local"&lt;/span&gt;,&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Local Invocation&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We are now ready to run our code locally. The syntax for this is below:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;sls invoke &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; vote_post &lt;span style="color: #660033;"&gt;--no-color&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; data&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;post.json &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
The &lt;strong&gt;-f&lt;/strong&gt; flag value sets the Lambda function name which in our case is vote_post. We use the &lt;strong&gt;--no-color&lt;/strong&gt; switch for readability, and the &lt;strong&gt;-p&lt;/strong&gt; flag value is a path to our data file. Running it gives us the following output (for brevity some output removed)
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;Got event &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"resource"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"/"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"path"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"/"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"httpMethod"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"POST"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"headers"&lt;/span&gt;:&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"Accept"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"Accept-Encoding"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"gzip, deflate, br"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"Accept-Language"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"en-GB,en-US;q=0.9,en;q=0.8"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"cache-control"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"no-cache"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"CloudFront-Forwarded-Proto"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"https"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"CloudFront-Is-Desktop-Viewer"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"true"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"CloudFront-Is-Mobile-Viewer"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"false"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"CloudFront-Is-SmartTV-Viewer"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"false"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"CloudFront-Is-Tablet-Viewer"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"false"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"CloudFront-Viewer-Country"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"GB"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"content-type"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"Cookie"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"_ga=GA1.2.1152355093.1509819171; mousestats_vi=d4e8e34af07e2372c27c"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"Host"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"n4kofna4l1.execute-api.eu-west-1.amazonaws.com"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"origin"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"https://n4kofna4l1.execute-api.eu-west-1.amazonaws.com"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"pragma"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"no-cache"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"Referer"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"https://n4kofna4l1.execute-api.eu-west-1.amazonaws.com/dev/"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"upgrade-insecure-requests"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"1"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"User-Agent"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"Via"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"2.0 bd161094d4b1a9657f26409a791c36ef.cloudfront.net (CloudFront)"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"X-Amz-Cf-Id"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"qbxtM7siu0PhYiY58aPKYVXrhG5RO8S4r8XfXOUG-u-IwuTjL_2Vpw=="&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"X-Amzn-Trace-Id"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"Root=1-5acbbc81-1c0ce7281e876d1c307f0d98"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"X-Forwarded-For"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"94.3.136.181, 216.137.62.46"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"X-Forwarded-Port"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"443"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"X-Forwarded-Proto"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"https"&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"queryStringParameters"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"pathParameters"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"stageVariables"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"requestContext"&lt;/span&gt;:&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"resourceId"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"lp67djpm80"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"resourcePath"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"/"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"httpMethod"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"POST"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"extendedRequestId"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"FFpkSGhmjoEFlug="&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"requestTime"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"09/Apr/2018:19:18:25 +0000"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"path"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"/dev/"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"protocol"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"HTTP/1.1"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"stage"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"local"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"requestTimeEpoch"&lt;/span&gt;:&lt;span style="color: #000000;"&gt;1523301505841&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"requestId"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"c6eb6aa6-3c2a-11e8-8346-13d846b589a2"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"identity"&lt;/span&gt;:&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"cognitoIdentityPoolId"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"accountId"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"cognitoIdentityId"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"caller"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"accessKey"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"cognitoAuthenticationType"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"cognitoAuthenticationProvider"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"userArn"&lt;/span&gt;:null,&lt;span style="color: #ff0000;"&gt;"userAgent"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"user"&lt;/span&gt;:null&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"apiId"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"n4kofna4l1"&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"body"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"first_name=Joe&amp;last_name=Soap&amp;optradio=phpstorm"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"isBase64Encoded"&lt;/span&gt;:false,&lt;span style="color: #ff0000;"&gt;"static_url"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"https://s3-eu-west-1.amazonaws.com/vote-dev-webapps3bucket-1htbi30lx4nii"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"dynamodb_table"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"vote_dev"&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"headers"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
        &lt;span style="color: #ff0000;"&gt;"Location"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"https://n4kofna4l1.execute-api.eu-west-1.amazonaws.com/local/thank_you"&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,
    &lt;span style="color: #ff0000;"&gt;"statusCode"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;307&lt;/span&gt;,
    &lt;span style="color: #ff0000;"&gt;"body"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;""&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Note that the &lt;strong&gt;body&lt;/strong&gt; contains the submitted data and we should now have a record in our local DynamoDB containing that informations. Also note that we got a HTTP response of 307 - this is a redirect which would, with API Gateway being present, redirect us to the thank_you page. Obviously running locally terminates the Lambda function once its job has been completed. There are two methods for determining whether the write to DynamoDB worked - the cli and the local console shell.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;DynamoDB Scan Results - CLI Method&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The easiest method to ensure your records are being created correctly is to use the AWS CLI. The command below doesn't really require further explanation. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws dynamodb scan &lt;span style="color: #660033;"&gt;--table-name&lt;/span&gt;=vote_dev &lt;span style="color: #660033;"&gt;--endpoint-url&lt;/span&gt; http:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;localhost:&lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"Count"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;1&lt;/span&gt;, 
    &lt;span style="color: #ff0000;"&gt;"Items"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
            &lt;span style="color: #ff0000;"&gt;"optradio"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"phpstorm"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"forename"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Joe"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"surname"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Soap"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"id"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"4679de4d-1726-436e-b24b-755415b6298a"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"datetime"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"2018-04-11T09:45:54"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;, 
    &lt;span style="color: #ff0000;"&gt;"ScannedCount"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;1&lt;/span&gt;, 
    &lt;span style="color: #ff0000;"&gt;"ConsumedCapacity"&lt;/span&gt;: null
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;DynamoDB Scan Results - Console Shell Method&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.36.30-shell1.png?itok=52-NqHMp 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.36.30-shell1.png?itok=FSR2iTw6 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.36.30-shell1.png?itok=qLGshOxZ 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.36.30-shell1.png?itok=4C34Rw5P 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.36.30-shell1.png?itok=52-NqHMp" alt="Shell Button" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.41.51.png?itok=uExuPe15 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.41.51.png?itok=avkVbkhZ 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.41.51.png?itok=G_QtIYSu 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.41.51.png?itok=rGblFBxd 1930w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.41.51.png?itok=uExuPe15" alt="Expanded Scan" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.43.35.png?itok=tXe9mCmm 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.43.35.png?itok=5fB92aeH 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.43.35.png?itok=e0kZXlmI 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.43.35.png?itok=TSjEIbFx 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.43.35.png?itok=tXe9mCmm" alt="Scan Console. " typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;This is more complicated than the command line, but is more powerful and would be ideally suited to someone with a good understanding of JavaScript. Go to your console shell at http://{your_ip_address}:8000/shell/ and click the &lt;/&gt; button as shown in the first screenshot. This will provide a list of JavaScript templates. Click the &lt;strong&gt;Scan&lt;/strong&gt; template and it will expand to show the sample JavaScript as per the second screenshot. Click the thick left arrow and the console will appear for you to edit code and run it (the third screenshot). &lt;/p&gt;
&lt;p&gt;Now here's the (slightly) fiddly bit. The code has a great many parameters which can be supplied, but we don't need that. We just want to dump all records in their entireity. So cut all the parameters we don't need. For convenience I have pasted below what you need to leave in. It's quite obvious, but copy this over the entire code in the console. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="javascript geshifilter-javascript" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #000066; font-weight: bold;"&gt;var&lt;/span&gt; params &lt;span style="color: #339933;"&gt;=&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
    TableName&lt;span style="color: #339933;"&gt;:&lt;/span&gt; &lt;span style="color: #3366CC;"&gt;'vote_dev'&lt;/span&gt;&lt;span style="color: #339933;"&gt;,&lt;/span&gt;
    Limit&lt;span style="color: #339933;"&gt;:&lt;/span&gt; &lt;span style="color: #CC0000;"&gt;10&lt;/span&gt;&lt;span style="color: #339933;"&gt;,&lt;/span&gt; &lt;span style="color: #006600; font-style: italic;"&gt;// optional (limit the number of items to evaluate)&lt;/span&gt;
    Select&lt;span style="color: #339933;"&gt;:&lt;/span&gt; &lt;span style="color: #3366CC;"&gt;'ALL_ATTRIBUTES'&lt;/span&gt;&lt;span style="color: #339933;"&gt;,&lt;/span&gt; &lt;span style="color: #006600; font-style: italic;"&gt;// optional (ALL_ATTRIBUTES | ALL_PROJECTED_ATTRIBUTES | &lt;/span&gt;
                              &lt;span style="color: #006600; font-style: italic;"&gt;//           SPECIFIC_ATTRIBUTES | COUNT)&lt;/span&gt;
    ConsistentRead&lt;span style="color: #339933;"&gt;:&lt;/span&gt; &lt;span style="color: #003366; font-weight: bold;"&gt;false&lt;/span&gt;&lt;span style="color: #339933;"&gt;,&lt;/span&gt; &lt;span style="color: #006600; font-style: italic;"&gt;// optional (true | false)&lt;/span&gt;
    ReturnConsumedCapacity&lt;span style="color: #339933;"&gt;:&lt;/span&gt; &lt;span style="color: #3366CC;"&gt;'NONE'&lt;/span&gt;&lt;span style="color: #339933;"&gt;,&lt;/span&gt; &lt;span style="color: #006600; font-style: italic;"&gt;// optional (NONE | TOTAL | INDEXES)&lt;/span&gt;
&lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;
dynamodb.&lt;span style="color: #660066;"&gt;scan&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;params&lt;span style="color: #339933;"&gt;,&lt;/span&gt; &lt;span style="color: #000066; font-weight: bold;"&gt;function&lt;/span&gt;&lt;span style="color: #009900;"&gt;(&lt;/span&gt;err&lt;span style="color: #339933;"&gt;,&lt;/span&gt; data&lt;span style="color: #009900;"&gt;)&lt;/span&gt; &lt;span style="color: #009900;"&gt;{&lt;/span&gt;
    &lt;span style="color: #000066; font-weight: bold;"&gt;if&lt;/span&gt; &lt;span style="color: #009900;"&gt;(&lt;/span&gt;err&lt;span style="color: #009900;"&gt;)&lt;/span&gt; ppJson&lt;span style="color: #009900;"&gt;(&lt;/span&gt;err&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; &lt;span style="color: #006600; font-style: italic;"&gt;// an error occurred&lt;/span&gt;
    &lt;span style="color: #000066; font-weight: bold;"&gt;else&lt;/span&gt; ppJson&lt;span style="color: #009900;"&gt;(&lt;/span&gt;data&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt; &lt;span style="color: #006600; font-style: italic;"&gt;// successful response&lt;/span&gt;
&lt;span style="color: #009900;"&gt;}&lt;/span&gt;&lt;span style="color: #009900;"&gt;)&lt;/span&gt;&lt;span style="color: #339933;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now click on the play shaped button.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.51.49.png?itok=DTg_abmf 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.51.49.png?itok=NcUpdG6w 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.51.49.png?itok=ijtEDL9g 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.51.49.png?itok=tBOsYkio 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.51.49.png?itok=DTg_abmf" alt="Console successful run" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.54.53.png?itok=8K__woNS 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.54.53.png?itok=o57MFYti 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.54.53.png?itok=JoSE5r4e 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.54.53.png?itok=Ok75Q5sl 1488w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-11%20at%2012.54.53.png?itok=8K__woNS" alt="Zoomed successful run" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The first screenshot above shows the console after it has completed the playback of the JavaScript code. The second screenshot shows a zoomed view of the results. The results are exactly what we put into the local invocation so it is fine. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Further Functions&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The example I have shown above relates to the form's POSTed submission. To develop the original form GET and the redirect to the thank_you page, simply change the function names in the local invocation. The POST is the most complex since it performs the database write. The others shouldn't be too onerous in comparison!&lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Tue, 10 Apr 2018 08:31:50 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">142 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 5: Models</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-5-models</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 5: Models&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Mon, 09/04/2018 - 10:31&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now it's time to create our model. This will be easy at this stage since we are only going to be writing a record to our DynamoDB table. However since the scope of the project could increase over time, it would make sense to create an abstract class which will deal with the AWS SDK Client configuration and creation. So to start we should create a directory and two PHP files - one for the abstract class and one to write the record. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;pwd&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-vote
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Models
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Models&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;VoteModel.php
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Models&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;PutVote.php&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Installing AWS PHP SDK&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We are going to use the AWS PHP SDK for writing our records out to DynamoDB since it contains a very convenient DynamoDB Client. To install it, use composer:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ composer require aws&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;aws-sdk-php
Using version ^&lt;span style="color: #000000;"&gt;3.54&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;for&lt;/span&gt; aws&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;aws-sdk-php&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;The PHP Abstract Class&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;strong&gt;VoteModel.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Vote&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Models&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDb&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDbClient&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;abstract class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;VoteModel &lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;    protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$client_config &lt;/span&gt;&lt;span style="color: #007700"&gt;= [&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'region' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'eu-west-1'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'version' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'2012-08-10'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'credentials.cache' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;TRUE&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'validation' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;FALSE&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'scheme' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'http'&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__construct&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;logger &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__set&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$value&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$value&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Get an aws sdk client for extended classes&lt;br /&gt;     *&lt;br /&gt;     * @return \Aws\DynamoDb\DynamoDbClient&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;loadClient&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'credentials'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Credentials&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;CredentialProvider&lt;/span&gt;&lt;span style="color: #007700"&gt;::&lt;/span&gt;&lt;span style="color: #0000BB"&gt;env&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;        return(new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDbClient&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;client_config&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
This shouldn't hold too many surprises. The constructor requires the data and logger which is made available to any class that extends from it - we will need both since the logger object is used to notify our status through CloudWatch, and the data will contain the submitted form data. There are setters and getters as you would expect to provide a consistent way of dealing with the class's properties. &lt;br /&gt;&lt;br /&gt;
The &lt;strong&gt;loadClient&lt;/strong&gt; method instantiates the DynamoDB client, and note that we are getting the necessary credentials from the environment which will be passed to the client.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;PHP DynamoDB PutVote Class&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;strong&gt;PutModel.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Vote&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Models&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Aws&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDb&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDbException&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;PutVote &lt;/span&gt;&lt;span style="color: #007700"&gt;extends &lt;/span&gt;&lt;span style="color: #0000BB"&gt;VoteModel &lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    private &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$id &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;''&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Put request to AWS DynamoDB API&lt;br /&gt;     *&lt;br /&gt;     *&lt;br /&gt;     * @param array $payload&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;put&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$payload&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$client &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;loadClient&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;id &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;generateUUID&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$current_datetime &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;date&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Y-m-d\TH:i:s'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$item &lt;/span&gt;&lt;span style="color: #007700"&gt;= [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'id'               &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'S' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;id&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Primary Key&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'forename'        &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'S' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$payload&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'first_name'&lt;/span&gt;&lt;span style="color: #007700"&gt;]],&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'surname'        &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'S' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$payload&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'last_name'&lt;/span&gt;&lt;span style="color: #007700"&gt;]],&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'datetime'        &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'S' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$current_datetime&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'optradio'      &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'S' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$payload&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'optradio'&lt;/span&gt;&lt;span style="color: #007700"&gt;]],&lt;br /&gt;        ];&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$client&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;putItem&lt;/span&gt;&lt;span style="color: #007700"&gt;(array(&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'TableName' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'dynamodb_table'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Item' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$item&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;        } catch (&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DynamoDbException $e&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;logger&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;notice&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'DynamoDB Put Failed'&lt;/span&gt;&lt;span style="color: #007700"&gt;, array(&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'table'         &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'dynamodb_table'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'id'             &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;id&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'RequestID'     &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getAwsRequestId&lt;/span&gt;&lt;span style="color: #007700"&gt;(),&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ErrorType'     &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getAwsErrorType&lt;/span&gt;&lt;span style="color: #007700"&gt;(),&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ErrorCode'     &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getAwsErrorCode&lt;/span&gt;&lt;span style="color: #007700"&gt;(),&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'ErrorMessage'    &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getAwsErrorMessage&lt;/span&gt;&lt;span style="color: #007700"&gt;(),&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'StatusCode'     &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getStatusCode&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;            ));&lt;br /&gt;            return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;TRUE&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        }&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;FALSE&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Create a UUID - PHP doesn't have a good function for this, so hand-rolled&lt;br /&gt;     *&lt;br /&gt;     * @see https://rogerstringer.com/2013/11/14/generate-uuids-php/&lt;br /&gt;     *&lt;br /&gt;     * @return string generated UUID&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;generateUUID&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;sprintf&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'%04x%04x-%04x-%04x-%04x-%04x%04x%04x'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0xffff &lt;/span&gt;&lt;span style="color: #007700"&gt;), &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0xffff &lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0xffff &lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0x0fff &lt;/span&gt;&lt;span style="color: #007700"&gt;) | &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0x4000&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0x3fff &lt;/span&gt;&lt;span style="color: #007700"&gt;) | &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0x8000&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0xffff &lt;/span&gt;&lt;span style="color: #007700"&gt;), &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0xffff &lt;/span&gt;&lt;span style="color: #007700"&gt;), &lt;/span&gt;&lt;span style="color: #0000BB"&gt;mt_rand&lt;/span&gt;&lt;span style="color: #007700"&gt;( &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;0xffff &lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;        );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
The PutVote class is also very simple since the legwork is undertaken by the AWS PHP SDK. The primary key can be auto-increment but I elected to use a UUID which is created in the generateUUID method. The payload passed to the &lt;strong&gt;put&lt;/strong&gt; method is an array of the POSTed data of the form which is bundled into an record before being passed to the SDK &lt;strong&gt;putItem&lt;/strong&gt;.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;DynamoDB Configuration&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;There are a number of changes we need to inform to our codebase about DynamoDB. The first place is &lt;strong&gt;serverless.yml&lt;/strong&gt;- we need to set an environment variable with the name of the DynamoDB table, so we will stick with the convention of appending the stage to the end of it. Add it to the end of the environmental section as below: &lt;br /&gt;
&lt;strong&gt;serverless.yml&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;  environment:
    STATIC_URL: https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;s3-&lt;span style="color: #800000;"&gt;${self:provider.region}&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;${self:custom.s3StaticBucket}&lt;/span&gt;
    DYNAMODB_TABLE: vote_&lt;span style="color: #800000;"&gt;${self:provider.stage}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Further down in the &lt;strong&gt;Resources&lt;/strong&gt; section we need to define our DynamoDB resource. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;    &lt;span style="color: #666666; font-style: italic;"&gt;## Specify the DynamoDB Table&lt;/span&gt;
    DynamoDbTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: vote_&lt;span style="color: #800000;"&gt;${self:provider.stage}&lt;/span&gt;
        AttributeDefinitions:
          - AttributeName: &lt;span style="color: #c20cb9; font-weight: bold;"&gt;id&lt;/span&gt;
            AttributeType: S
        KeySchema:
          - AttributeName: &lt;span style="color: #c20cb9; font-weight: bold;"&gt;id&lt;/span&gt;
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: &lt;span style="color: #000000;"&gt;5&lt;/span&gt;
          WriteCapacityUnits: &lt;span style="color: #000000;"&gt;5&lt;/span&gt;
    DynamoDBIamPolicy:
      Type: AWS::IAM::Policy
      DependsOn: DynamoDbTable
      Properties:
        PolicyName: lambda-dynamodb
        PolicyDocument:
          Version: &lt;span style="color: #ff0000;"&gt;'2012-10-17'&lt;/span&gt;
          Statement:
            - Effect: Allow
              Action:
                - dynamodb:GetItem
                - dynamodb:PutItem
              Resource: arn:aws:dynamodb:&lt;span style="color: #000000; font-weight: bold;"&gt;*&lt;/span&gt;:&lt;span style="color: #000000; font-weight: bold;"&gt;*&lt;/span&gt;:table&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;vote_&lt;span style="color: #800000;"&gt;${self:provider.stage}&lt;/span&gt;
        Roles:
          - Ref: IamRoleLambdaExecution&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Finally, in the &lt;strong&gt;handler.php&lt;/strong&gt; file that interfaces with the JavaScript shim there is a section of the code that sets PHP variables from the environment - this will make sure our model has the table name surfaced to use when a record is written out to DynamoDB. Make sure this section looks like mine below:&lt;br /&gt;
&lt;strong&gt;handler.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Get the handler service and execute&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$handler &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$container&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getenv&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'HANDLER'&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #0000BB"&gt;getenv&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'STATIC_URL'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'dynamodb_table'&lt;/span&gt;&lt;span style="color: #007700"&gt;] = &lt;/span&gt;&lt;span style="color: #0000BB"&gt;getenv&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'DYNAMODB_TABLE'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;DynamoDB Deploy&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-09%20at%2015.46.36-processed.png?itok=s2AZT8VZ 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-09%20at%2015.46.36-processed.png?itok=oCvGJIVM 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-09%20at%2015.46.36-processed.png?itok=_OCoGSW9 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-09%20at%2015.46.36-processed.png?itok=TIrC_4Pd 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-09%20at%2015.46.36-processed.png?itok=s2AZT8VZ" alt="AWS Table Deploy" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Once the serverless.yml file has been updated it makes sense to do a deploy to make sure the table has been created correctly in AWS. The deply is below, and you should end up with the screenshot above. To get there, navigate to Services-&gt;DynamoDB-&gt;Tables and you should see &lt;strong&gt;vote_dev&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3 &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;12.53&lt;/span&gt; MB&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
................................
Serverless: Stack update finished...
Service Information
service: vote
stage: dev
region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
stack: vote-dev
api keys:
  None
endpoints:
  GET - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
  POST - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
  POST - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;thank_you
functions:
  vote_get: vote-dev-vote_get
  vote_post: vote-dev-vote_post
  thank_you: vote-dev-thank_you
Serverless: Removing old service versions...&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Controller Modifications&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Now the model exists, we need to made changes to our controllers so the models are instantiated and invoked. Firstly the &lt;strong&gt;save&lt;/strong&gt; method in the &lt;strong&gt;FormController&lt;/strong&gt; needs to be rewritten - see below. Once we get the submitted POSTed data, it is parsed into an array ready for the model to use. The model is called, and if it returns TRUE then we reload the index page with an error message. &lt;br /&gt;
&lt;strong&gt;FormController.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;save&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Get the data ready for for the model and the redirect&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'data'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;parse_str&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'body'&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$params&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$model &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;createModel&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'PutVote'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Bail on Error&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;if (&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$model&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;put&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$params&lt;/span&gt;&lt;span style="color: #007700"&gt;)) {&lt;br /&gt;            return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_index&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'vote.html'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                [&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'title' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Badzilla\'s Lambda Vote Form'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'error' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Something has gone wrong with your submission. Please try later.'&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #007700"&gt;]);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Construct the url using the Lambda data we have&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'X-Forwarded-Proto'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'://'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;.= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Host'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        if (isset(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;]) &amp;&amp; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;] != &lt;/span&gt;&lt;span style="color: #DD0000"&gt;''&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;.= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;.= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/thank_you'&lt;/span&gt;&lt;span style="color: #007700"&gt;;        &lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Set the required http settings for a redirect resubmit POST&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__set&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;307&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__set&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;, array(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Location' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// No body text to return &lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;return &lt;/span&gt;&lt;span style="color: #DD0000"&gt;''&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt; 
The &lt;strong&gt;ThankYouController&lt;/strong&gt; requires a small modification - we need to parse the submitted data from the form and then pass the first name and last name to the Twig template. This occurs in the &lt;strong&gt;index&lt;/strong&gt; method. &lt;br /&gt;
&lt;strong&gt;ThankYouController.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;index&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;parse_str&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'body'&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$params&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_index&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'thank-you.html'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            [&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'title' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Badzilla\'s Big Thank You'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'first_name' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;htmlspecialchars&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$params&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'first_name'&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;ENT_QUOTES&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'UTF-8'&lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'last_name' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;htmlspecialchars&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$params&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'last_name'&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;ENT_QUOTES&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'UTF-8'&lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;            ]&lt;br /&gt;        );&lt;br /&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Composer Autoloader&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We will need to inform composer of our new autoloader requirements for the model. So make sure your composer has the following entries under psr-4 in &lt;strong&gt;composer.json&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;  &lt;span style="color: #ff0000;"&gt;"autoload"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"psr-4"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
      &lt;span style="color: #ff0000;"&gt;"Raines\\Serverless\&lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;: "&lt;/span&gt;src&lt;span style="color: #ff0000;"&gt;",
      "&lt;/span&gt;Vote\\Controllers\&lt;span style="color: #000000; font-weight: bold;"&gt;\"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"src/Controllers/"&lt;/span&gt;,
      &lt;span style="color: #ff0000;"&gt;"Vote\\Models\&lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;: "&lt;/span&gt;src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Models&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;",
      "&lt;/span&gt;Twig\&lt;span style="color: #000000; font-weight: bold;"&gt;\"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"vendor/twig/twig/lib"&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
  &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Then update with:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ composer dump-autoload
Generating autoload files&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Deploy and Add Records&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-09%20at%2020.24.20-processed.png?itok=gQcTd37A 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-04/Screen%20Shot%202018-04-09%20at%2020.24.20-processed.png?itok=9W1ako5O 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-04/Screen%20Shot%202018-04-09%20at%2020.24.20-processed.png?itok=RpS2_Z4V 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-04/Screen%20Shot%202018-04-09%20at%2020.24.20-processed.png?itok=Q5FJpqZj 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-04/Screen%20Shot%202018-04-09%20at%2020.24.20-processed.png?itok=gQcTd37A" alt="Vote records" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The code can now be deployed (as per the instructions earlier) and by pointing a browser to the dev instance of the site, records can be successfully added to the DynamoDB database. By navigating in the AWS Console to Services-&gt;DynamoDV-&gt;Tables-&gt;{select vote_dev}-&gt;Items we can see that the records are being created successfully. &lt;/p&gt;
&lt;p&gt;The solution is now functionally ok but there is a long way to go before we are production ready. Also I have spoon fed the code, but in the real world there would have been plenty of trial and error, and problems to solve. To cut down the endless deploy to AWS/test cycle, it is better to develop and test as far as possible locally. We prepped for this in the earlier blog &lt;a href="http://badzilla.co.uk/real-world-php-lambda-app-part-4-setting-dynamodb-locally"&gt;A Real World PHP Lambda App Part 4: Setting up DynamoDb Locally&lt;/a&gt; and in the next blog I'll show you how to develop locally.&lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Mon, 09 Apr 2018 09:31:50 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">141 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 4: Setting up DynamoDb Locally</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-4-setting-dynamodb-locally</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 4: Setting up DynamoDb Locally&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sun, 04/02/2018 - 16:47&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We will be using DynamoDb to save our vote data, but since this adds additional complexity to the development process, it will also slow it down. There is a solution - DynamoDb can be installed locally so that there isn't the need for continuous deploys to AWS. In fact, the local version of DynamoDb is probably SQLite but it will do the job whilst we are testing our code. It also requires a working Java runtime so that needs to be installed first. This can be done on the command line. I am using Ubuntu 16.04 so for my system I do:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sudo&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;apt-get update&lt;/span&gt;
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sudo&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;apt-get install&lt;/span&gt; default-jre&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
The JAVA_HOME environment variable will need to be set for the local DynamoDb to work correctly. Firstly we must determine where Java has been installed. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sudo&lt;/span&gt; update-alternatives &lt;span style="color: #660033;"&gt;--config&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;
There is only one alternative &lt;span style="color: #000000; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;link&lt;/span&gt; group &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;providing &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;: &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jvm&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;java-&lt;span style="color: #000000;"&gt;7&lt;/span&gt;-openjdk-amd64&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;jre&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;
Nothing to configure.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
That's easy - Java is available at /usr/bin/java. Now edit &lt;strong&gt;/etc/environment&lt;/strong&gt; and add the following line at the bottom:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #007800;"&gt;JAVA_HOME&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"/usr/bin/java"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now we need to reload and check the variable is set
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;source&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;etc&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;environment 
$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;echo&lt;/span&gt; &lt;span style="color: #007800;"&gt;$JAVA_HOME&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;bin&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Install DynamoDb&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;I downloaded the DynamoDb tarball from the AWS site and moved it into my /tmp directory. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;usr&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;sudo&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dynamodb
$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;cd&lt;/span&gt; dynamodb
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;tar&lt;/span&gt; zxvf &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;tmp&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dynamodb_local_latest.tar.gz &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now list the directory and you'll see the jar file we will need to run. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-las&lt;/span&gt;
total &lt;span style="color: #000000;"&gt;3660&lt;/span&gt;
   &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxr-xr-x  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; root root    &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Feb  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;17&lt;/span&gt;:&lt;span style="color: #000000;"&gt;55&lt;/span&gt; .
   &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxr-xr-x &lt;span style="color: #000000;"&gt;69&lt;/span&gt; root root    &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Feb  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;17&lt;/span&gt;:&lt;span style="color: #000000;"&gt;54&lt;/span&gt; ..
&lt;span style="color: #000000;"&gt;3628&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; root root &lt;span style="color: #000000;"&gt;3713946&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;16&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; DynamoDBLocal.jar
   &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxr-xr-x  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; root root    &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Feb  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;17&lt;/span&gt;:&lt;span style="color: #000000;"&gt;55&lt;/span&gt; DynamoDBLocal_lib
  &lt;span style="color: #000000;"&gt;12&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; root root    &lt;span style="color: #000000;"&gt;8644&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;16&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; LICENSE.txt
   &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rw-r--r--&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; root root     &lt;span style="color: #000000;"&gt;795&lt;/span&gt; Feb &lt;span style="color: #000000;"&gt;16&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2017&lt;/span&gt; README.txt
   &lt;span style="color: #000000;"&gt;4&lt;/span&gt; drwxr-xr-x  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; root root    &lt;span style="color: #000000;"&gt;4096&lt;/span&gt; Feb  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;17&lt;/span&gt;:&lt;span style="color: #000000;"&gt;55&lt;/span&gt; third_party_licenses&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Start DynamoDB &lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_183156.png?itok=ccY-dfqC 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-02/Screenshot_20180204_183156.png?itok=Sl8aXsQQ 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-02/Screenshot_20180204_183156.png?itok=IgmtJjy_ 1045w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_183156.png?itok=ccY-dfqC" alt="Start Dynamo" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;To start DynamoDb, you need to be sure you are in the directory listed above, and then issue the following command
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;java&lt;/span&gt; -Djava.library.path=.&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;DynamoDBLocal_lib &lt;span style="color: #660033;"&gt;-jar&lt;/span&gt; DynamoDBLocal.jar &lt;span style="color: #660033;"&gt;-sharedDb&lt;/span&gt; &lt;span style="color: #660033;"&gt;-inMemory&lt;/span&gt;
Initializing DynamoDB Local with the following configuration:
Port:   &lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
InMemory:       &lt;span style="color: #c20cb9; font-weight: bold;"&gt;true&lt;/span&gt;
DbPath: null
SharedDb:       &lt;span style="color: #c20cb9; font-weight: bold;"&gt;true&lt;/span&gt;
shouldDelayTransientStatuses:   &lt;span style="color: #c20cb9; font-weight: bold;"&gt;false&lt;/span&gt;
CorsParams:     &lt;span style="color: #000000; font-weight: bold;"&gt;*&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Note I have set the flag &lt;strong&gt;inMemory&lt;/strong&gt; so I am not writing to a database held on disk - all data is stored in volatile RAM. This is useful for quickly testing a solution, but obviously the data won't persist. The &lt;strong&gt;sharedDb&lt;strong&gt; flag tells DynamoDB to use one database across all regions and credentials - it makes it much easier to manage on a local test installation. To check it is running ok, point a browser at &lt;strong&gt;{your IP address}:8000/shell/&lt;/strong&gt; and you should see the shell as shown above. &lt;/strong&gt;&lt;/strong&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Create a Local DynamoDb Database&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Once DynamoDb is up and running, you could write some code to create a database. However it is much easier to use the aws command line. All the options I list below are mandatory. I decided to define an attribute named id which I will generate when I write records. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws dynamodb create-table &lt;span style="color: #660033;"&gt;--table-name&lt;/span&gt;=vote_dev &lt;span style="color: #660033;"&gt;--attribute-definitions&lt;/span&gt; &lt;span style="color: #007800;"&gt;AttributeName&lt;/span&gt;=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;id&lt;/span&gt;,&lt;span style="color: #007800;"&gt;AttributeType&lt;/span&gt;=S &lt;span style="color: #660033;"&gt;--key-schema&lt;/span&gt; &lt;span style="color: #007800;"&gt;AttributeName&lt;/span&gt;=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;id&lt;/span&gt;,&lt;span style="color: #007800;"&gt;KeyType&lt;/span&gt;=HASH &lt;span style="color: #660033;"&gt;--provisioned-throughput&lt;/span&gt; &lt;span style="color: #007800;"&gt;ReadCapacityUnits&lt;/span&gt;=&lt;span style="color: #000000;"&gt;5&lt;/span&gt;,&lt;span style="color: #007800;"&gt;WriteCapacityUnits&lt;/span&gt;=&lt;span style="color: #000000;"&gt;5&lt;/span&gt;  &lt;span style="color: #660033;"&gt;--endpoint-url&lt;/span&gt; http:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;localhost:&lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"TableDescription"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
        &lt;span style="color: #ff0000;"&gt;"TableArn"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"arn:aws:dynamodb:ddblocal:000000000000:table/vote_dev"&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"AttributeDefinitions"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"AttributeName"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"id"&lt;/span&gt;, 
                &lt;span style="color: #ff0000;"&gt;"AttributeType"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"S"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"ProvisionedThroughput"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
            &lt;span style="color: #ff0000;"&gt;"NumberOfDecreasesToday"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"WriteCapacityUnits"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;5&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"LastIncreaseDateTime"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0.0&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"ReadCapacityUnits"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;5&lt;/span&gt;, 
            &lt;span style="color: #ff0000;"&gt;"LastDecreaseDateTime"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0.0&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"TableSizeBytes"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"TableName"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"vote_dev"&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"TableStatus"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"ACTIVE"&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"KeySchema"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
                &lt;span style="color: #ff0000;"&gt;"KeyType"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"HASH"&lt;/span&gt;, 
                &lt;span style="color: #ff0000;"&gt;"AttributeName"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"id"&lt;/span&gt;
            &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
        &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"ItemCount"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;0&lt;/span&gt;, 
        &lt;span style="color: #ff0000;"&gt;"CreationDateTime"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;1517770607.687&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Let's double check everything is ok
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ aws dynamodb list-tables &lt;span style="color: #660033;"&gt;--endpoint-url&lt;/span&gt; http:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;localhost:&lt;span style="color: #000000;"&gt;8000&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"TableNames"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
        &lt;span style="color: #ff0000;"&gt;"vote_dev"&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sun, 04 Feb 2018 16:47:33 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">137 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 3: Controllers</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-3-controllers</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 3: Controllers&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sun, 28/01/2018 - 10:36&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The next step in our odyssey to build a real world Lambda app is to create the controllers. We will need two - one for the form and one for the thankyou page. We should - and therefore will - create an interface for those two. In addition since we want to be able to test our controllers out, we will need to create some placeholder views. The views will be constructed using the Twig template engine so that will have to be added to our build too. &lt;/p&gt;

&lt;p&gt;First lets create our controllers. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Navigate to the root directory of the project and issue:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #7a0874; font-weight: bold;"&gt;pwd&lt;/span&gt;
&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;www&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;html&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;serverless-vote
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Controllers
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Controllers&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;FormController.php
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Controllers&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;ThankyouController.php
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Controllers&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;VoteInterfaceController.php&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Twig Installation&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Twig installation is by composer and thus simplicity itself. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ composer require &lt;span style="color: #ff0000;"&gt;"twig/twig:^2.0"&lt;/span&gt;
.&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;composer.json has been updated
Loading composer repositories with package information
Updating dependencies &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;including require-dev&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
Package operations: &lt;span style="color: #000000;"&gt;2&lt;/span&gt; installs, &lt;span style="color: #000000;"&gt;0&lt;/span&gt; updates, &lt;span style="color: #000000;"&gt;0&lt;/span&gt; removals
  - Installing symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;polyfill-mbstring &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v1.7.0&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; Downloading: &lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;         
  - Installing twig&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;twig &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v2.4.4&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; Downloading: &lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;         
Writing lock &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt;
Generating autoload files
$ &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Interface&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The interface is listed below. Note that we construct with the two properties we are going to need to do our work - the data array structure, and the logger object we can use to report to stderr which will be picked up by CloudWatch. We are setting the default HTTP status code to 200 and the headers will always return HTML by default. We have two protected methods in there - the &lt;em&gt;createModel&lt;/em&gt; uses the &lt;strong&gt;new&lt;/strong&gt; operator which dooms unit testing so it has been placed outside of the main code, and the &lt;em&gt;_index&lt;/em&gt; method which also performs instantiation thus making unit testing difficult.&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Vote&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Controllers&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;abstract class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;VoteInterfaceController&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Lambda context&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    public &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// http protocol stuff - set default values&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$statusCode &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;200&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$headers &lt;/span&gt;&lt;span style="color: #007700"&gt;= [&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Content-Type' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'text/html'&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__construct&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;logger &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__set&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$value&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$value&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$key&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Instantiate a model.&lt;br /&gt;     * Performing this in it's own function makes unit testing easier&lt;br /&gt;     *&lt;br /&gt;     * @link https://stackoverflow.com/questions/7760635/unit-test-for-mocking-a-method-called-by-new-class-object&lt;br /&gt;     *&lt;br /&gt;     * @param string model&lt;br /&gt;     * @return object&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;createModel&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$model&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$model &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;"\\Vote\\Models\\"&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$model&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        return new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$model&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Wrapper for index controller&lt;br /&gt;     *&lt;br /&gt;     * @param string filename of the template&lt;br /&gt;     * @param array key/values to populate the template&lt;br /&gt;     *&lt;br /&gt;     * @return string rendered template&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;_index&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$filename&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$values&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$loader &lt;/span&gt;&lt;span style="color: #007700"&gt;= new \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Twig_Loader_Filesystem&lt;/span&gt;&lt;span style="color: #007700"&gt;(array(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;dirname&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__DIR__&lt;/span&gt;&lt;span style="color: #007700"&gt;).&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/Views'&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$twig &lt;/span&gt;&lt;span style="color: #007700"&gt;= new \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Twig_Environment&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$loader&lt;/span&gt;&lt;span style="color: #007700"&gt;, array(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'cache' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/tmp/cache'&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$content &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$twig&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;load&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$filename&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$content&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;render&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$values&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Composer Autoloader&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We will need to inform composer of our new autoloader requirements - both Twig and our controllers. So add the following entries under psr-4 in &lt;strong&gt;composer.json&lt;/strong&gt;
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;  &lt;span style="color: #ff0000;"&gt;"autoload"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"psr-4"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
      &lt;span style="color: #ff0000;"&gt;"Raines\\Serverless\&lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;: "&lt;/span&gt;src&lt;span style="color: #ff0000;"&gt;",
      "&lt;/span&gt;Vote\\Controllers\&lt;span style="color: #000000; font-weight: bold;"&gt;\"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"src/Controllers/"&lt;/span&gt;,
      &lt;span style="color: #ff0000;"&gt;"Twig\&lt;span style="color: #000099; font-weight: bold;"&gt;\"&lt;/span&gt;: "&lt;/span&gt;vendor&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;twig&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;twig&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib&lt;span style="color: #ff0000;"&gt;"
    }
  },&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Then update
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ composer update
Loading composer repositories with package information
Updating dependencies &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;including require-dev&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;
Package operations: &lt;span style="color: #000000;"&gt;0&lt;/span&gt; installs, &lt;span style="color: #000000;"&gt;4&lt;/span&gt; updates, &lt;span style="color: #000000;"&gt;0&lt;/span&gt; removals
  - Updating symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;filesystem &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v3.3.13 =&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt; v4.0.4&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; Downloading: &lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;         
  - Updating symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;config &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v3.3.13 =&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt; v3.4.4&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; Downloading: &lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;         
  - Updating symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dependency-injection &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v3.3.13 =&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt; v3.4.4&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; Downloading: &lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;         
  - Updating symfony&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;yaml &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;v3.3.13 =&lt;span style="color: #000000; font-weight: bold;"&gt;&gt;&lt;/span&gt; v3.4.4&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; Downloading: &lt;span style="color: #000000;"&gt;100&lt;/span&gt;&lt;span style="color: #000000; font-weight: bold;"&gt;%&lt;/span&gt;         
Writing lock &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt;
Generating autoload files&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Controller Code&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Here is the code for our controllers. The action &lt;em&gt;index&lt;/em&gt; in the &lt;em&gt;FormController&lt;/em&gt; merely presents the form to the end user. The &lt;em&gt;save&lt;/em&gt; method doesn't actually save the POSTed date yet since we haven't created our models yet. That will be covered in a later tutorial. However it constructs the URL for the redirect to the thank you page using the environmental data which is provided by Lambda. It returns an HTTP status code of 307 - which is the code that says&lt;em&gt; redirect and don't change the original HTTP method&lt;/em&gt;, which in our case was POST. Therefore the thank you page will have the POSTed data we want. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;strong&gt;FormController.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Vote&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Controllers&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;FormController &lt;/span&gt;&lt;span style="color: #007700"&gt;extends &lt;/span&gt;&lt;span style="color: #0000BB"&gt;VoteInterfaceController &lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Load the form&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;index&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_index&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'vote.html'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            [&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'title' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Badzilla\'s Lambda Vote Form'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url'&lt;/span&gt;&lt;span style="color: #007700"&gt;]&lt;br /&gt;            ]&lt;br /&gt;        );&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Save the captured form and send to DynamoDB then redirect to thank_you&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;save&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Get the data ready for for the model and the redirect&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'data'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Construct the url using the Lambda data we have&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'X-Forwarded-Proto'&lt;/span&gt;&lt;span style="color: #007700"&gt;].&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'://'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;.= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Host'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        if (isset(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;]) &amp;&amp; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;] != &lt;/span&gt;&lt;span style="color: #DD0000"&gt;''&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;.= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/'&lt;/span&gt;&lt;span style="color: #007700"&gt;.&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'requestContext'&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'stage'&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url &lt;/span&gt;&lt;span style="color: #007700"&gt;.= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/thank_you'&lt;/span&gt;&lt;span style="color: #007700"&gt;;        &lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Set the required http settings for a redirect resubmit POST&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__set&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;307&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__set&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;, array(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Location' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$url&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// No body text to return &lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;return &lt;/span&gt;&lt;span style="color: #DD0000"&gt;''&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
&lt;strong&gt;ThankyouController.php&lt;/strong&gt;
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Vote&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Controllers&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;ThankyouController &lt;/span&gt;&lt;span style="color: #007700"&gt;extends &lt;/span&gt;&lt;span style="color: #0000BB"&gt;VoteInterfaceController&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;    public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;index&lt;/span&gt;&lt;span style="color: #007700"&gt;()&lt;br /&gt;    {&lt;br /&gt;        return &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;_index&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'thank-you.html'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            [&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'title' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Badzilla\'s Big Thank You'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;data&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'static_url'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;            ]&lt;br /&gt;        );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Custom Serverless Parameter static_url&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_155649-processed.png?itok=qSSjDqyc 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-02/Screenshot_20180204_155649-processed.png?itok=NkxHbI3R 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-02/Screenshot_20180204_155649-processed.png?itok=t-e1FS0w 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2018-02/Screenshot_20180204_155649-processed.png?itok=4LxRV7TB 1374w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_155649-processed.png?itok=qSSjDqyc" alt="serverless.yml" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_160801.png?itok=JlmOR8yX 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-02/Screenshot_20180204_160801.png?itok=avUmv3y2 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-02/Screenshot_20180204_160801.png?itok=a1HOktDW 938w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_160801.png?itok=JlmOR8yX" alt="handler.php" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;You'll notice in the code above that I am passing the parameter &lt;strong&gt;$this-&gt;data['static_url'] &lt;/strong&gt;to the Twig templates. The static URL contains the base path to the S3 bucket that uses CloudFront to serve our assets from the S3 bucket (via CloudFront) we set up in a previous tutorial. So we need to make sure the URL is set correctly from the configuration. &lt;/p&gt;

&lt;p&gt;Firstly open up the file &lt;strong&gt;serverless.yml &lt;/strong&gt;in your favourite editor. Under &lt;strong&gt;custom&lt;/strong&gt;, add the key/value pair where the key is &lt;strong&gt;s3StaticBucket&lt;/strong&gt; and the value is the identifier of your s3 asset bucket (and not the s3 bucket for your deploys. Then under environment, add the full path of that bucket using &lt;strong&gt;STATIC_URL&lt;/strong&gt; as the key. It's best explained by referring to the first image above. This will populate the value of STATIC_URL in the environment which can be picked up in the PHP when it runs. &lt;/p&gt;

&lt;p&gt;Now edit&lt;strong&gt; handler.php&lt;/strong&gt; and set the array key $event['static_url'] as shown in the second image.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Views&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The views need to be created. These will hold the raw HTML for sending back to the browser. There will be three in total - an overarching layout.html which holds the main HTML structure such as the html head and body tags, and then vote.html and thank-you.html which hold specific body content for the two pages in our app. The actual 
HTML is beyond the scope of these tutorials, but they are created with:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Views
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;layout.html
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;thank-you.html
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;touch&lt;/span&gt; src&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Views&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;vote.html&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
You obviously now need to put the HTML code in those empty files, and if you are using Twig, then the placeholders for the variables you pass to the templates. You should also be adding your images and JavaScript and css to directories underneath /dist. The entire project should look like this right now. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;tree&lt;/span&gt; &lt;span style="color: #660033;"&gt;-I&lt;/span&gt; vendor
.
├── buildphp.sh
├── CHANGELOG.md
├── composer.json
├── composer.lock
├── config
│   └── services.yml
├── dist
│   ├── css
│   │   └── default.css
│   └── images
│       ├── badzilla-logo32x32.png
│       └── favicon.ico
├── dockerfile.buildphp
├── docroot
│   └── layout.html
├── handler.js
├── handler.php
├── LICENSE
├── node_modules
│   └── serverless-single-page-app-plugin
│       ├── index.js
│       ├── package.json
│       └── README.md
├── package-lock.json
├── php
├── README.md
├── serverless.yml
└── src
    ├── Context.php
    ├── Controllers
    │   ├── FormController.php
    │   ├── ThankyouController.php
    │   └── VoteInterfaceController.php
    ├── Handler.php
    ├── Views
    │   ├── layout.html
    │   ├── thank-you.html
    │   └── vote.html
    └── VoteHandler.php
 
&lt;span style="color: #000000;"&gt;10&lt;/span&gt; directories, &lt;span style="color: #000000;"&gt;29&lt;/span&gt; files&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
I've used the Bootstrap theme Cosmo which is hotlinked in the &lt;strong&gt;layout.html&lt;/strong&gt; so I don't need too many assets. But what I do have still needs syncing up to the S3 bucket which, as per my earlier tutorial, is achieved with what is below, followed by my final deploy because we are now ready to test our app.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls syncToS3 
$ sls deploy&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Run&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_162850.png?itok=O7SP68Ur 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-02/Screenshot_20180204_162850.png?itok=-wScMmiv 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-02/Screenshot_20180204_162850.png?itok=4CAVq1yM 1098w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_162850.png?itok=O7SP68Ur" alt="Form" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_163001.png?itok=8FJyLZUj 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-02/Screenshot_20180204_163001.png?itok=QovEmFBQ 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-02/Screenshot_20180204_163001.png?itok=zr3mcUK3 1079w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-02/Screenshot_20180204_163001.png?itok=8FJyLZUj" alt="Thank You" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Ok so time to check out our app. Yes we still have a long way to go because we aren't saving the data as yet. But steady progress is being made. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sun, 28 Jan 2018 10:36:46 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">136 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 2: Routing and a Front Controller</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-2-routing-and-front-controller</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 2: Routing and a Front Controller&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sat, 27/01/2018 - 14:06&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Since we are making a PHP application we really should stick to the recognised right way of doing this; the MVC pattern is the established best practice. Sitting in front of this pattern is the Front Controller which will act as a controller to determine which C of the MVC will actually be called, and to do a bit of the routing job, and to act as the layer between our actual code and the &lt;strong&gt;hander,js&lt;/strong&gt; / &lt;strong&gt;handler.php&lt;/strong&gt; shim that comes with serverless-php.&lt;/p&gt;
&lt;p&gt;In fact we get a starter Front Controller in the serverless-php repo already although it is very basic and will need a little extending to serve a purpose in a MVC web app. &lt;/p&gt;
&lt;p&gt;The name of the game is to keep whatever we develop to be very lightweight. Whilst it would be good to get Symfony / Zend / Laravel running under serverless-php, that will come at a cost of execution time and development time. &lt;/p&gt;
&lt;p&gt;So the 'Front Controller' is called &lt;strong&gt;HelloHandler.php&lt;/strong&gt; in the &lt;strong&gt;src/&lt;/strong&gt; directory but you should've renamed it &lt;strong&gt;VoteHandler.php&lt;/strong&gt; already and changed the name of the class it contains.&lt;/p&gt;
&lt;p&gt;The second consideration is the AWS API Gateway - that too needs to know which routes we are defining. We can accomplish that by configuration in the &lt;em&gt;serverless.yml&lt;/em&gt; file.&lt;/p&gt;
&lt;p&gt;As previously mentioned our voting app is going to present a form (HTTP GET), then when submitted (HTTP POST) it will cache the name of the voter and that person's choice in a NoSQL data store, then redirect to a thank you page (HTTP POST). Note that the redirect must be a POST since Google don't take kindly to URL parameters containing personal data, and we want to display the voter's name on the thank you page. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;serverless.yml &lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;We need to define the functions - one for each of the transactions. Present the form; Submit the form; Redirect to thank_you. Note that since we are always going to channel the code through our Front Controller and therefore we are going to use the same service. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;functions:
  vote_get:
    handler: handler.handle
    environment:
      HANDLER: handler.vote  &lt;span style="color: #666666; font-style: italic;"&gt;# This is the service name which will be used (from services.yml)&lt;/span&gt;
    events:
      - http:
          path: &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
          method: get
  vote_post:
    handler: handler.handle
    environment:
      HANDLER: handler.vote  &lt;span style="color: #666666; font-style: italic;"&gt;# This is the service name which will be used (from services.yml)&lt;/span&gt;
    events:
      - http:
          path: &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
          method: post
  thank_you:
    handler: handler.handle
    environment:
      HANDLER: handler.vote  &lt;span style="color: #666666; font-style: italic;"&gt;# This is the service name which will be used (from services.yml)&lt;/span&gt;
    events:
      - http:
          path: &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;thank_you
          method: post&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now lets deploy to AWS
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3 &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;9.96&lt;/span&gt; MB&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
.....................................................................
Serverless: Stack update finished...
Service Information
service: vote
stage: dev
region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
stack: vote-dev
api keys:
  None
endpoints:
  GET - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
  POST - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
  POST - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;thank_you
functions:
  vote_get: vote-dev-vote_get
  vote_post: vote-dev-vote_post
  thank_you: vote-dev-thank_you&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-01/Screenshot_20180127_145609-processed.png?itok=l_ENs4wD 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2018-01/Screenshot_20180127_145609-processed.png?itok=fHlh-Aub 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2018-01/Screenshot_20180127_145609-processed.png?itok=v0n-8qy0 1296w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2018-01/Screenshot_20180127_145609-processed.png?itok=l_ENs4wD" alt="API Gateway" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;If we log into the AWS Console and navigate to the API Gateway we can see our functions are declared correctly. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Front Controller&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;Below is the front controller &lt;strong&gt;src/VoteHandler.php&lt;/strong&gt;. Most of it is quite self-explanatory but a few points are worthy of commentary. The $routing is hard-coded since we need to match a path / method against a controller. The $event is populated with the serverless runtime such as command line data, HTTP method and the route. In the main handle function we are returning whatever the controller passes back to us in terms of HTTP status code, headers and body. It is up to the controllers to determine this. Finally the function createController is used to avoid having a &lt;strong&gt;new&lt;/strong&gt; operator in the handle function which would make it impossible to be unit tested, 
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;namespace &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Raines&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Serverless&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Psr&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Log&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;LoggerInterface&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;class &lt;/span&gt;&lt;span style="color: #0000BB"&gt;VoteHandler &lt;/span&gt;&lt;span style="color: #007700"&gt;implements &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Handler&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Routing table&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;protected &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$routing &lt;/span&gt;&lt;span style="color: #007700"&gt;= [&lt;br /&gt;        [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'path' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'method' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'GET'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'controller' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Form'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'action' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'index'&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;        [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'path' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'method' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'POST'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'controller' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Form'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'action' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'save'&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;        [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'path' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/thank_you'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'method' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'POST'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'controller' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Thankyou'&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'action' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'index'&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;    ];&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * {@inheritdoc}&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;public function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;handle&lt;/span&gt;&lt;span style="color: #007700"&gt;(array &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Context $context&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$context&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getLogger&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;notice&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Got event'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// get the controller and action based on the path and method&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$route &lt;/span&gt;&lt;span style="color: #007700"&gt;= [];&lt;br /&gt;        foreach(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;routing &lt;/span&gt;&lt;span style="color: #007700"&gt;as &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$k &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$r&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            if (&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$r&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'path'&lt;/span&gt;&lt;span style="color: #007700"&gt;] == &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'path'&lt;/span&gt;&lt;span style="color: #007700"&gt;] &amp;&amp; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$r&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'method'&lt;/span&gt;&lt;span style="color: #007700"&gt;] == &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'httpMethod'&lt;/span&gt;&lt;span style="color: #007700"&gt;]) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$route&lt;/span&gt;&lt;span style="color: #007700"&gt;[] = &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;routing&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$k&lt;/span&gt;&lt;span style="color: #007700"&gt;];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            if (&lt;/span&gt;&lt;span style="color: #0000BB"&gt;count&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$route&lt;/span&gt;&lt;span style="color: #007700"&gt;) != &lt;/span&gt;&lt;span style="color: #0000BB"&gt;1&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;                throw new \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Inconsistent routing provided'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Construct the controller name&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$classname &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #DD0000"&gt;"Vote\Controllers\\&lt;/span&gt;&lt;span style="color: #007700"&gt;{&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$route&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'controller'&lt;/span&gt;&lt;span style="color: #007700"&gt;]}&lt;/span&gt;&lt;span style="color: #DD0000"&gt;Controller"&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// See if classname and action both exist&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #007700"&gt;if (!&lt;/span&gt;&lt;span style="color: #0000BB"&gt;class_exists&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$classname&lt;/span&gt;&lt;span style="color: #007700"&gt;) || !&lt;/span&gt;&lt;span style="color: #0000BB"&gt;method_exists&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$classname&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$route&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'action'&lt;/span&gt;&lt;span style="color: #007700"&gt;])) {&lt;br /&gt;                throw new \&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Unknown classname or action provided'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        } catch (\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Exception $e&lt;/span&gt;&lt;span style="color: #007700"&gt;) {&lt;br /&gt;            return [&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; [&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'Content-Type' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'application/json'&lt;/span&gt;&lt;span style="color: #007700"&gt;],&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;500&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'body' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;json_encode&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$e&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getMessage&lt;/span&gt;&lt;span style="color: #007700"&gt;(), &lt;/span&gt;&lt;span style="color: #0000BB"&gt;JSON_HEX_QUOT&lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;            ];&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Create the controller&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$controller &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$this&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;createController&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$classname&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Execute the action&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$output &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$controller&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;{&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$route&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;0&lt;/span&gt;&lt;span style="color: #007700"&gt;][&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'action'&lt;/span&gt;&lt;span style="color: #007700"&gt;]}();&lt;br /&gt;&lt;br /&gt;        return [&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$controller&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'headers'&lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$controller&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'statusCode'&lt;/span&gt;&lt;span style="color: #007700"&gt;),&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'body' &lt;/span&gt;&lt;span style="color: #007700"&gt;=&gt; &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$output&lt;/span&gt;&lt;span style="color: #007700"&gt;,&lt;br /&gt;        ];&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #FF8000"&gt;/**&lt;br /&gt;     * Instantiate the controller&lt;br /&gt;     *&lt;br /&gt;     * @param string $classname&lt;br /&gt;     * @param LoggerInterface $logger&lt;br /&gt;     * @param array $event&lt;br /&gt;     *&lt;br /&gt;     * @return object&lt;br /&gt;     */&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #007700"&gt;private function &lt;/span&gt;&lt;span style="color: #0000BB"&gt;createController&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;string $classname&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;LoggerInterface $logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, array &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;)&lt;br /&gt;    {&lt;br /&gt;        return new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$classname&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;
We also need to make a small change to &lt;strong&gt;handler.php&lt;/strong&gt;, In the final line we need to make sure the json_encode() call is passed the JSON_HEX_QUOT parameter to ensure correct escaping. 
&lt;div class="codeblock geshifilter"&gt;&lt;code&gt;&lt;span style="color: #000000"&gt;&lt;br /&gt;&lt;span style="color: #0000BB"&gt;&lt;?php&lt;br /&gt;&lt;br /&gt;$loader &lt;/span&gt;&lt;span style="color: #007700"&gt;= require &lt;/span&gt;&lt;span style="color: #0000BB"&gt;__DIR__ &lt;/span&gt;&lt;span style="color: #007700"&gt;. &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/vendor/autoload.php'&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Raines&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Serverless&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Context&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Symfony&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Component&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Config&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;FileLocator&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Symfony&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Component&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DependencyInjection&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;ContainerBuilder&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;use &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Symfony&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Component&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;DependencyInjection&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;Loader&lt;/span&gt;&lt;span style="color: #007700"&gt;\&lt;/span&gt;&lt;span style="color: #0000BB"&gt;YamlFileLoader&lt;/span&gt;&lt;span style="color: #007700"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Set up service container&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$container &lt;/span&gt;&lt;span style="color: #007700"&gt;= new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;ContainerBuilder&lt;/span&gt;&lt;span style="color: #007700"&gt;();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$loader &lt;/span&gt;&lt;span style="color: #007700"&gt;= new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;YamlFileLoader&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$container&lt;/span&gt;&lt;span style="color: #007700"&gt;, new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;FileLocator&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;__DIR__ &lt;/span&gt;&lt;span style="color: #007700"&gt;. &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'/config'&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$loader&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;load&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'services.yml'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Get event data and context object&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;json_decode&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$argv&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;1&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;true&lt;/span&gt;&lt;span style="color: #007700"&gt;) ?: [];&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$container&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'logger'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fd &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;fopen&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'php://fd/3'&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #DD0000"&gt;'r+'&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$context &lt;/span&gt;&lt;span style="color: #007700"&gt;= new &lt;/span&gt;&lt;span style="color: #0000BB"&gt;Context&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$logger&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$argv&lt;/span&gt;&lt;span style="color: #007700"&gt;[&lt;/span&gt;&lt;span style="color: #0000BB"&gt;2&lt;/span&gt;&lt;span style="color: #007700"&gt;], &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$fd&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Get the handler service and execute&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$handler &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$container&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;get&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;getenv&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #DD0000"&gt;'HANDLER'&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$response &lt;/span&gt;&lt;span style="color: #007700"&gt;= &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$handler&lt;/span&gt;&lt;span style="color: #007700"&gt;-&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;handle&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$event&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;$context&lt;/span&gt;&lt;span style="color: #007700"&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #FF8000"&gt;// Send data back to shim&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;printf&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;json_encode&lt;/span&gt;&lt;span style="color: #007700"&gt;(&lt;/span&gt;&lt;span style="color: #0000BB"&gt;$response&lt;/span&gt;&lt;span style="color: #007700"&gt;, &lt;/span&gt;&lt;span style="color: #0000BB"&gt;JSON_HEX_QUOT&lt;/span&gt;&lt;span style="color: #007700"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000BB"&gt;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Runtime Invocation&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;We are now ready to run our code from the command line locally. Of course it isn't going to do too much since we've not added the MVC part of the code yet! However I would expect it to get to the point it tries to instantiate a controller before throwing an exception. &lt;/p&gt;
&lt;p&gt;The syntax for local invocation is below. Note the JSON structure passed using the flag --data - this will be interpreted by our Front Controller in the populated $event array. The -f flag denotes the Lambda function we are running. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls invoke &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; vote_get &lt;span style="color: #660033;"&gt;--data&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;'{"path":"/","httpMethod":"POST"}'&lt;/span&gt;
Got event &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"path"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"/"&lt;/span&gt;,&lt;span style="color: #ff0000;"&gt;"httpMethod"&lt;/span&gt;:&lt;span style="color: #ff0000;"&gt;"POST"&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"headers"&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
        &lt;span style="color: #ff0000;"&gt;"Content-Type"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"application/json"&lt;/span&gt;
    &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,
    &lt;span style="color: #ff0000;"&gt;"statusCode"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;500&lt;/span&gt;,
    &lt;span style="color: #ff0000;"&gt;"body"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Unknown classname or action provided"&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Ok - an error but totally expected. Progress is being made!&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sat, 27 Jan 2018 14:06:02 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">135 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App Part 1: Extend to CloudFront + S3</title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app-part-1-extend-cloudfront-s3</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App Part 1: Extend to CloudFront + S3&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sat, 23/12/2017 - 17:02&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;We are going to create a voting app to collect information from our users. This will require a HTML form to be initially rendered to the user using the HTTP GET method and then POSTed to the PHP backend for processing and the data saved into AWS DynamoDB. The page should then be redirected to a thank you page. &lt;/p&gt;
&lt;p&gt;We shall call this app &lt;em&gt;vote&lt;/em&gt;. So our first activity will be to refer back to my &lt;a href="http://badzilla.co.uk/running-php-amazon-lambda-serverless"&gt;initial blog&lt;/a&gt; but instead of create a project &lt;em&gt;demo&lt;/em&gt;, call it &lt;em&gt;vote&lt;/em&gt;. Once you are ready check your function has been created correctly with the command below. &lt;/p&gt;
&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ serverless invoke &lt;span style="color: #7a0874; font-weight: bold;"&gt;local&lt;/span&gt; &lt;span style="color: #660033;"&gt;-f&lt;/span&gt; vote
&lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt;
    &lt;span style="color: #ff0000;"&gt;"statusCode"&lt;/span&gt;: &lt;span style="color: #000000;"&gt;200&lt;/span&gt;,
    &lt;span style="color: #ff0000;"&gt;"body"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"Go Serverless v1.0! Your function executed successfully!"&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;
$&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Note how I am changing my regime. I now want to do all my development locally and only rarely deploy to S3. This will cut down S3 costs (although they won't be exorbitant) and speed up development .As we go through the blogs I will point out techniques to aid the local development process.&lt;br /&gt;&lt;br /&gt;Ok - so we've reached base camp and we will now build on our sample function.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Prerequisites&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;We will need the &lt;strong&gt;aws cli &lt;/strong&gt;console&lt;strong&gt; &lt;/strong&gt;to be able to upload our app's static assets (css, js, images) to S3 for them to be served by CloudFront. The console has a requirement for Python so that will need to be installed first if you don't already have it. If you already have Python installed, execute the command below. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;# &lt;/span&gt;pip &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; awscli &lt;span style="color: #660033;"&gt;--ignore-installed&lt;/span&gt; six&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Next we will need to install our first Serverless plugin - this will provide us with the facility to sync our local assets with the S3 bucket we are going to create for our app. The plugin we need to achieve this is serverless-single-page-app-plugin. Let's install it. Navigate to the root directory of our app and issue the following. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;npm &lt;span style="color: #c20cb9; font-weight: bold;"&gt;install&lt;/span&gt; &lt;span style="color: #660033;"&gt;--save&lt;/span&gt; serverless-single-page-app-plugin&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
This will place the serverless-single-page-app-plugin in the parent directory node_modules. We need to let serverless know about our plugin by adding the following to our &lt;strong&gt;serverless.yml&lt;/strong&gt; file just after the &lt;strong&gt;service:&lt;/strong&gt; section.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;plugins:
  - serverless-single-page-app-plugin&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
We now need to include into the serverless.yml file the CloudFormation configuration for the S3 assets bucket and for it to serve pages through CloudFront. Thankfully this is provided in the serverless-single-page-app-plugin README.md file so simply copy and paste the following. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;resources:
  Resources:
    &lt;span style="color: #666666; font-style: italic;"&gt;## Specifying the S3 Bucket&lt;/span&gt;
    WebAppS3Bucket:
      Type: AWS::S3::Bucket
      Properties:
        AccessControl: PublicRead
        WebsiteConfiguration:
          IndexDocument: index.html
          ErrorDocument: index.html
    &lt;span style="color: #666666; font-style: italic;"&gt;## Specifying the policies to make sure all files inside the Bucket are avaialble to CloudFront&lt;/span&gt;
    WebAppS3BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        Bucket:
          Ref: WebAppS3Bucket
        PolicyDocument:
          Statement:
            - Sid: PublicReadGetObject
              Effect: Allow
              Principal: &lt;span style="color: #ff0000;"&gt;"*"&lt;/span&gt;
              Action:
              - s3:GetObject
              Resource:
                Fn::Join: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
                  &lt;span style="color: #ff0000;"&gt;""&lt;/span&gt;, &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
                    &lt;span style="color: #ff0000;"&gt;"arn:aws:s3:::"&lt;/span&gt;,
                    &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Ref"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"WebAppS3Bucket"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,
                    &lt;span style="color: #ff0000;"&gt;"/*"&lt;/span&gt;
                  &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
                &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
    &lt;span style="color: #666666; font-style: italic;"&gt;## Specifying the CloudFront Distribution to server your Web Application&lt;/span&gt;
    WebAppCloudFrontDistribution:
      Type: AWS::CloudFront::Distribution
      Properties:
        DistributionConfig:
          Origins:
            - DomainName:
                Fn::Join: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
                  &lt;span style="color: #ff0000;"&gt;""&lt;/span&gt;, &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt;
                    &lt;span style="color: #7a0874; font-weight: bold;"&gt;{&lt;/span&gt; &lt;span style="color: #ff0000;"&gt;"Ref"&lt;/span&gt;: &lt;span style="color: #ff0000;"&gt;"WebAppS3Bucket"&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;}&lt;/span&gt;,
                    &lt;span style="color: #ff0000;"&gt;".s3.amazonaws.com"&lt;/span&gt;
                  &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
                &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;
              &lt;span style="color: #666666; font-style: italic;"&gt;## An identifier for the origin which must be unique within the distribution&lt;/span&gt;
              Id: WebApp
              CustomOriginConfig:
                HTTPPort: &lt;span style="color: #000000;"&gt;80&lt;/span&gt;
                HTTPSPort: &lt;span style="color: #000000;"&gt;443&lt;/span&gt;
                OriginProtocolPolicy: https-only
              &lt;span style="color: #666666; font-style: italic;"&gt;## In case you want to restrict the bucket access use S3OriginConfig and remove CustomOriginConfig&lt;/span&gt;
              &lt;span style="color: #666666; font-style: italic;"&gt;# S3OriginConfig:&lt;/span&gt;
              &lt;span style="color: #666666; font-style: italic;"&gt;#   OriginAccessIdentity: origin-access-identity/cloudfront/E127EXAMPLE51Z&lt;/span&gt;
          Enabled: &lt;span style="color: #ff0000;"&gt;'true'&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;## Uncomment the following section in case you are using a custom domain&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;# Aliases:&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;# - mysite.example.com&lt;/span&gt;
          DefaultRootObject: index.html
          &lt;span style="color: #666666; font-style: italic;"&gt;## Since the Single Page App is taking care of the routing we need to make sure ever path is served with index.html&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;## The only exception are files that actually exist e.h. app.js, reset.css&lt;/span&gt;
          CustomErrorResponses:
            - ErrorCode: &lt;span style="color: #000000;"&gt;404&lt;/span&gt;
              ResponseCode: &lt;span style="color: #000000;"&gt;200&lt;/span&gt;
              ResponsePagePath: &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;index.html
          DefaultCacheBehavior:
            AllowedMethods:
              - DELETE
              - GET
              - HEAD
              - OPTIONS
              - PATCH
              - POST
              - PUT
            &lt;span style="color: #666666; font-style: italic;"&gt;## The origin id defined above&lt;/span&gt;
            TargetOriginId: WebApp
            &lt;span style="color: #666666; font-style: italic;"&gt;## Defining if and how the QueryString and Cookies are forwarded to the origin which in this case is S3&lt;/span&gt;
            ForwardedValues:
              QueryString: &lt;span style="color: #ff0000;"&gt;'false'&lt;/span&gt;
              Cookies:
                Forward: none
            &lt;span style="color: #666666; font-style: italic;"&gt;## The protocol that users can use to access the files in the origin. To allow HTTP use `allow-all`&lt;/span&gt;
            ViewerProtocolPolicy: redirect-to-https
          &lt;span style="color: #666666; font-style: italic;"&gt;## The certificate to use when viewers use HTTPS to request objects.&lt;/span&gt;
          ViewerCertificate:
            CloudFrontDefaultCertificate: &lt;span style="color: #ff0000;"&gt;'true'&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;## Uncomment the following section in case you want to enable logging for CloudFront requests&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;# Logging:&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;#   IncludeCookies: 'false'&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;#   Bucket: mylogs.s3.amazonaws.com&lt;/span&gt;
          &lt;span style="color: #666666; font-style: italic;"&gt;#   Prefix: myprefix&lt;/span&gt;
  &lt;span style="color: #666666; font-style: italic;"&gt;## In order to print out the hosted domain via `serverless info` we need to define the DomainName output for CloudFormation&lt;/span&gt;
  Outputs:
    WebAppS3BucketOutput:
      Value:
        &lt;span style="color: #ff0000;"&gt;'Ref'&lt;/span&gt;: WebAppS3Bucket
    WebAppCloudFrontDistributionOutput:
      Value:
        &lt;span style="color: #ff0000;"&gt;'Fn::GetAtt'&lt;/span&gt;: &lt;span style="color: #7a0874; font-weight: bold;"&gt;[&lt;/span&gt; WebAppCloudFrontDistribution, DomainName &lt;span style="color: #7a0874; font-weight: bold;"&gt;]&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
It's time to deploy to AWS but before you do, check your credentials are loaded, and if not then fix. In my case I added them to the bottom of my &lt;strong&gt;~/.bashrc&lt;/strong&gt; file then logged out and in for them to take effect. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;env&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; AWS
&lt;span style="color: #007800;"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;=XXXXXXXXXXXXXXXXXXXXXXX
&lt;span style="color: #007800;"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;=XXXXXXXXXXXXXX
$ &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now deploy with 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip &lt;span style="color: #c20cb9; font-weight: bold;"&gt;file&lt;/span&gt; to S3 &lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #000000;"&gt;9.96&lt;/span&gt; MB&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt;...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...........................
Serverless: Stack update finished...
Service Information
service: vote
stage: dev
region: eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;
stack: vote-dev
api keys:
  None
endpoints:
  GET - https:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;n4kofna4l1.execute-api.eu-west-&lt;span style="color: #000000;"&gt;1&lt;/span&gt;.amazonaws.com&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;dev&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;vote
functions:
  vote: vote-dev-vote
$&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
This took an eternity first time through! I went and made a cup of tea!&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;AWS Console - S3&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.10.57-processed.png?itok=r6atxxMM 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.10.57-processed.png?itok=zZ1lgMMF 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.10.57-processed.png?itok=vRAwYaTR 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.10.57-processed.png?itok=Mp8yg_ZC 2234w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.10.57-processed.png?itok=r6atxxMM" alt="AWS S3" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;If we now navigate to S3 in the AWS console we should be able to see our two buckets for this project; one for the assets and one for our deployed serverless code. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;AWS Console - CloudFront&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.12.06-processed.png?itok=W7jvhCnT 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.12.06-processed.png?itok=zpvAkIZd 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.12.06-processed.png?itok=d0zHyzlK 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.12.06-processed.png?itok=FYCwC6Da 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2015.12.06-processed.png?itok=W7jvhCnT" alt="AWS CloudFront" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Now if we navigate to CloudFront we can see the service we have just created which will serve our S3 assets.&lt;/p&gt;

&lt;p&gt;The plugin provides the serverless &lt;strong&gt;syncToS3&lt;/strong&gt; command which is run to perform the sync, but it requires configuration before we can use it. We need to set a custom variable &lt;strong&gt;s3LocalPath&lt;/strong&gt; in the &lt;strong&gt;serverless.yml&lt;/strong&gt; file.&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cat&lt;/span&gt; serverless.yml &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #660033;"&gt;-A1&lt;/span&gt; custom:
custom:
  s3LocalPath: dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
$&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
I have decided to put my assets in a subdirectory under my root called &lt;strong&gt;dist/&lt;/strong&gt;. I now need to create that local directory and whilst I am at it I'll create an image subdirectory with a sample Badzilla logo image I can test the sync with.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;mkdir&lt;/span&gt; &lt;span style="color: #660033;"&gt;-p&lt;/span&gt; dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;cp&lt;/span&gt; ..&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;meedjum&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;docroot&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;themes&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;custom&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;beezee8&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;badzilla-logo32x32.png dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;.&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now let's be adventurous and see if the sync works. 
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ sls syncToS3
Serverless: s3,&lt;span style="color: #c20cb9; font-weight: bold;"&gt;sync&lt;/span&gt;,dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;,s3:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;vote-dev-webapps3bucket-1htbi30lx4nii&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;
upload: dist&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;badzilla-logo32x32.png to s3:&lt;span style="color: #000000; font-weight: bold;"&gt;//&lt;/span&gt;vote-dev-webapps3bucket-1htbi30lx4nii&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;images&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;badzilla-logo32x32.png
 
Serverless: stderr undefined
Serverless: Successfully synced to the S3 bucket
$&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Yey! Looking good but let's check it properly!&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;S3 Sync&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2016.51.10.png?itok=kDNSIWPX 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2017-12/Screen%20Shot%202017-12-23%20at%2016.51.10.png?itok=Ccm1T2eF 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2017-12/Screen%20Shot%202017-12-23%20at%2016.51.10.png?itok=9EhIpCjT 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2017-12/Screen%20Shot%202017-12-23%20at%2016.51.10.png?itok=EJy2x8Dg 1812w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2016.51.10.png?itok=kDNSIWPX" alt="S3 Sync" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Navigate on the console to the S3 bucket, then through the filesystem and the &lt;strong&gt;images&lt;/strong&gt; directory then click on &lt;strong&gt;badzilla-logo32x32.png&lt;/strong&gt;. Looks Good. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;CloudFront Browser Access&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2017.04.57.png?itok=bn5BvMkt 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2017-12/Screen%20Shot%202017-12-23%20at%2017.04.57.png?itok=L4uABGA2 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2017-12/Screen%20Shot%202017-12-23%20at%2017.04.57.png?itok=TglJiLt4 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2017-12/Screen%20Shot%202017-12-23%20at%2017.04.57.png?itok=FnCWTbyM 2038w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-12/Screen%20Shot%202017-12-23%20at%2017.04.57.png?itok=bn5BvMkt" alt="CloudFront Browser Access" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Now if we point a web browser at your Bazilla logo asset we see that it is rendered correctly (look closely!). Yippee! We now have a working S3 / CloudFront configuration for our industrial strength Lambda function. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sat, 23 Dec 2017 17:02:11 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">130 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>A Real World PHP Lambda App </title>
  <link>http://badzilla.co.uk/real-world-php-lambda-app</link>
  <description>
&lt;span&gt;A Real World PHP Lambda App &lt;/span&gt;

            &lt;div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"&gt;&lt;p&gt;My previous blogs on AWS Lambda, PHP, Serverless and Serverless-PHP should have given you enough of a basic understanding of the mix of technologies to attempt to build something much more useful - a fully fledged PHP app. &lt;/p&gt;
&lt;p&gt;What would be the motivation for doing this? What type of sites lend themselves to be built with Serverless? &lt;/p&gt;
&lt;p&gt;Well certainly nothing on a grand scale - it would be foolhardy to attempt to host the BBC website on Lambda!! However Lambda lends itself to websites that may be immensely popular over a relatively short period of time. These could include (but are not limited to)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;News announcements for significant events (e.g. Oscar results for instance)&lt;/li&gt;
&lt;li&gt;Promotional websites for new products&lt;/li&gt;
&lt;li&gt;Registration / statement of interest sites&lt;/li&gt;
&lt;li&gt;Advocacy / campaigns&lt;/li&gt;
&lt;li&gt;Questionnaires / surveys / voting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any small site that has the possibility of incurring scaling problems, significant orchestration and deployment costs is a candidate. Furthermore once the promotion has served its purpose, the site could be re-skinned for re-use at a later date. &lt;/p&gt;
&lt;p&gt;Why PHP? If you already have PHP skills, or your work department does, then it frequently makes sense to standardise skills when building out products. &lt;/p&gt;
&lt;p&gt;The tutorials will show how to create a PHP site using a basic MVC with Twig templates, saving and retrieving data in DynamoDB, use the POST and GET HTTP methods, the correct way to redirect using PHP on top of a JavaScript shim, store your assets on S3 and CloudFront amongst other neat tricks. Let the fun begin - pick your tutorial from the list below! &lt;/p&gt;
&lt;/div&gt;
      
&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sun, 26/11/2017 - 18:26&lt;/span&gt;

  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sun, 26 Nov 2017 18:26:58 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">129 at http://badzilla.co.uk</guid>
    </item>
<item>
  <title>Recompiling PHP for serverless-php and Lambda</title>
  <link>http://badzilla.co.uk/recompiling-php-serverless-php-and-lambda</link>
  <description>
&lt;span&gt;Recompiling PHP for serverless-php and Lambda&lt;/span&gt;

&lt;span&gt;&lt;span lang="" about="http://badzilla.co.uk/user/1" typeof="schema:Person" property="schema:name" datatype="" xml:lang=""&gt;nigel&lt;/span&gt;&lt;/span&gt;

&lt;span&gt;Sun, 05/11/2017 - 15:54&lt;/span&gt;

      &lt;div class="field field--name-field-heading-image-text field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;The serverless-php git repo contains a pre-compiled PHP executable which is uploaded to AWS Lambda as part of the FaaS deploy. However, and deliberately to keep it lightweight, many PHP extensions are not included in this PHP image. I thought I may get through my development without having to rebuild this image, but alas not! I decided to use the Twig template engine and that has a dependency on the &lt;em&gt;hash() &lt;/em&gt;function. I realised something was afoot when my execution failed.&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Cloudwatch error diagnostic&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-11/Screen%20Shot%202017-11-04%20at%2016.15.00.png?itok=U-oTFMYn 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2017-11/Screen%20Shot%202017-11-04%20at%2016.15.00.png?itok=CgtqsJbq 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2017-11/Screen%20Shot%202017-11-04%20at%2016.15.00.png?itok=9lFH1sA1 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2017-11/Screen%20Shot%202017-11-04%20at%2016.15.00.png?itok=1rPINsye 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-11/Screen%20Shot%202017-11-04%20at%2016.15.00.png?itok=U-oTFMYn" alt="Cloudwatch Error" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The error was discovered by inspecting my Lambda function run log - you may be able to see able there is a uncaught exception leading to a fatal error.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;Fatal error: Uncaught Error: Call to undefined &lt;span style="color: #000000; font-weight: bold;"&gt;function&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;hash&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;(&lt;/span&gt;&lt;span style="color: #7a0874; font-weight: bold;"&gt;)&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;in&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;var&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;task&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;vendor&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;twig&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;twig&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;lib&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Twig&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;Environment.php:&lt;span style="color: #000000;"&gt;272&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;"&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
I wasn't aware that hash() required a separate PHP extension, so I checked this on my local copy of PHP 7.1 on my Macbook with
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ php &lt;span style="color: #660033;"&gt;-m&lt;/span&gt; &lt;span style="color: #000000; font-weight: bold;"&gt;|&lt;/span&gt; &lt;span style="color: #c20cb9; font-weight: bold;"&gt;grep&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;hash&lt;/span&gt;
&lt;span style="color: #7a0874; font-weight: bold;"&gt;hash&lt;/span&gt;
$ &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Aha! So nothing else for it, we need to add this to the compiled PHP image.&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Recompilation of PHP image&lt;/div&gt;
      
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;Thankfully the serverless-php repo contains two files to aid the recompilation of the PHP image - &lt;em&gt;buildphp.sh &lt;/em&gt;which is a shell script to run the process, and &lt;em&gt;dockerfile.buildphp &lt;/em&gt;which is the configuration for a docker container in which the actual recompilation will occur. &lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;The dockerfile contains the list of PHP extensions to include - so I added hash to the list
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;RUN .&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;configure \
    &lt;span style="color: #660033;"&gt;--enable-static&lt;/span&gt;=&lt;span style="color: #c20cb9; font-weight: bold;"&gt;yes&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-shared&lt;/span&gt;=no \
    &lt;span style="color: #660033;"&gt;--disable-all&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-json&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-libxml&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-mbstring&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-phar&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-soap&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-xml&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-hash&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--with-curl&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--with-gd&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--with-zlib&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--with-openssl&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--without-pear&lt;/span&gt; \
    &lt;span style="color: #660033;"&gt;--enable-ctype&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Now we need to check the PHP filesize and run the build script - most of the output of this has been cropped since it was copious.
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-las&lt;/span&gt; php
&lt;span style="color: #000000;"&gt;49144&lt;/span&gt; -rwxr-xr-x&lt;span style="color: #000000; font-weight: bold;"&gt;@&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; nigel  staff  &lt;span style="color: #000000;"&gt;25161497&lt;/span&gt;  &lt;span style="color: #000000;"&gt;2&lt;/span&gt; Nov &lt;span style="color: #000000;"&gt;14&lt;/span&gt;:03 php
$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;chmod&lt;/span&gt; +x buildphp.sh 
$ .&lt;span style="color: #000000; font-weight: bold;"&gt;/&lt;/span&gt;buildphp.sh 
Build complete.
Don&lt;span style="color: #ff0000;"&gt;'t forget to run '&lt;/span&gt;&lt;span style="color: #c20cb9; font-weight: bold;"&gt;make&lt;/span&gt; &lt;span style="color: #7a0874; font-weight: bold;"&gt;test&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;'.
 
 ---&gt; 7b602edcddb5
Removing intermediate container 6c3cd6936a6d
Successfully built 7b602edcddb5
Successfully tagged php-build:latest
2bdff18d52adad839b6cbdba9ee55e3263d5399326175827398f757cc9c74c44
$&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
Ok so let's check what we've got:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;$ &lt;span style="color: #c20cb9; font-weight: bold;"&gt;ls&lt;/span&gt; &lt;span style="color: #660033;"&gt;-las&lt;/span&gt; php
&lt;span style="color: #000000;"&gt;50736&lt;/span&gt; &lt;span style="color: #660033;"&gt;-rwxr-xr-x&lt;/span&gt;  &lt;span style="color: #000000;"&gt;1&lt;/span&gt; nigel  staff  &lt;span style="color: #000000;"&gt;25976432&lt;/span&gt;  &lt;span style="color: #000000;"&gt;4&lt;/span&gt; Nov &lt;span style="color: #000000;"&gt;16&lt;/span&gt;:&lt;span style="color: #000000;"&gt;34&lt;/span&gt; php&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
A different size which is encouraging! Now let's deploy and run:
&lt;div class="geshifilter"&gt;&lt;div class="bash geshifilter-bash" style="font-family:monospace;"&gt;&lt;pre style="font-family: monospace; font-weight: normal; font-style: normal"&gt;&lt;span style="color: #666666;"&gt;$ &lt;/span&gt;sls deploy&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-heading-picture-text paragraph--view-mode--default"&gt;
          
            &lt;div class="field field--name-field-heading field--type-string field--label-hidden field--item"&gt;Results&lt;/div&gt;
      
      &lt;div class="field field--name-field-blog-image field--type-image field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;    &lt;img srcset="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-11/APIGateway.png?itok=rLAiDdWm 325w, https://assets.badzilla.co.uk/s3fs-public/styles/max_650x650/public/2017-11/APIGateway.png?itok=GVCU_aLo 650w, https://assets.badzilla.co.uk/s3fs-public/styles/max_1300x1300/public/2017-11/APIGateway.png?itok=rAp7Ewbu 1300w, https://assets.badzilla.co.uk/s3fs-public/styles/max_2600x2600/public/2017-11/APIGateway.png?itok=T8fVQNnx 2600w" sizes="(min-width: 1290px) 1290px, 100vw" src="https://assets.badzilla.co.uk/s3fs-public/styles/max_325x325/public/2017-11/APIGateway.png?itok=rLAiDdWm" alt="API Gateway" typeof="foaf:Image" class="img-responsive" /&gt;


&lt;/div&gt;
          &lt;/div&gt;
  
            &lt;div class="field field--name-field-blog-text field--type-text-long field--label-hidden field--item"&gt;&lt;p&gt;If we now run our function from the API Gateway or point a web browser on our assigned URL we get a 200 success! Yey!&lt;/p&gt;&lt;/div&gt;
      
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
      &lt;div class="field field--name-field-blog-youtube field--type-entity-reference-revisions field--label-hidden field--items"&gt;
              &lt;div class="field--item"&gt;  &lt;div class="paragraph paragraph--type--blog-text-youtube paragraph--view-mode--default"&gt;
          
      &lt;/div&gt;
&lt;/div&gt;
          &lt;/div&gt;
  
  &lt;div class="field field--name-field-blog-terms field--type-entity-reference field--label-inline"&gt;
    &lt;div class="field--label"&gt;blog terms&lt;/div&gt;
          &lt;span class="field__items"&gt;
              &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/php" hreflang="en"&gt;PHP&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless-php" hreflang="en"&gt;serverless-php&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/serverless" hreflang="en"&gt;serverless&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/lambda" hreflang="en"&gt;lambda&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/docker" hreflang="en"&gt;Docker&lt;/a&gt;&lt;/span&gt;
          &lt;span class="field--item"&gt;&lt;a href="http://badzilla.co.uk/devops" hreflang="en"&gt;devops&lt;/a&gt;&lt;/span&gt;
              &lt;/span&gt;
      &lt;/div&gt;
</description>
  <pubDate>Sun, 05 Nov 2017 15:54:48 +0000</pubDate>
    <dc:creator>nigel</dc:creator>
    <guid isPermaLink="false">127 at http://badzilla.co.uk</guid>
    </item>

  </channel>
</rss>
