Pragmatism in the real world

Using Composer with Serverless & OpenWhisk

Every PHP project I write has dependencies on components from Packagist and my Serverless OpenWhisk PHP projects are no different. It turns out that adding Composer dependencies is trivial.

Let’s create a simple action that converts a number to it’s string form. e.g. 123 becomes one hundred and twenty three. We’ll start with our simple ow-php-hello project from my earlier article and add a new function to serverless.yml:

functions:
  n2w:
    handler: n2w.main

Our handler is n2w.main, so we need a n2w.php file with our main() function:

<?php
use NFNumberToWord\NumberToWords;

function main(array $args) : array
{
    if (!isset($args['number'])) {
        return ['error' => 'Please supply a number.'];
    }
    $number = (int)($args['number']);

    $words = (new NumberToWords)->toWords($number);

    return [
        'Result' => $words,
    ];
}

This action uses NFNumberToWord which is available from Packagist so we add it via composer:

$ composer require nineteenfeet/nf-number-to-word

This creates our vendor directory in the top level of our project and we can now deploy:

$ sls deploy

As you read the output, you’ll notice that it has created two actions: ow-php-hello-dev-hello and ow-php-hello-dev-n2w. We can now test our new n2w action:

$ sls invoke -f n2w -d '{"number": 123}'

This generates our expected output:

{
    "result": "one hundred and twenty-three"
}

It all works as you’d expect!

A note on packaging

If you look in the .serverless directory, you’ll discover that Serverless has created a single ow-php-hello.zip which contains all the code from the project. This is then uploaded to both actions.

I prefer to have the minimum amount of files in my action as it loads slightly faster and is just cleaner. To control this, we use the package configuration directive in serverless.yml.

package:
  individually: true

This will ensure that we create a separate .zip file for each action: hello.zip and n2w.zip.

To control which files are included in each zip file we can use the include and exclude directives. This is how I like to set it up in my serverless.yaml:

package:
  individually: true
  exclude:
     - "*"
  include:
     - "vendor/**"

functions:
  hello:
    handler: handler.hello
    annotations:
      web-export: true
    package:
      include:
        - handler.php
  n2w:
    handler: n2w.main
    annotations:
      web-export: true
    package:
      include:
        - n2w.php

At the global package level, I exclude all files and then include Composer’s vendor directory. Then, for each function, I include the specific PHP files required.

This results in the action zip files containing just the code required for running the action which is how I like it.

Fin

As you can see composer dependencies work just as you would expect when using Serverless with the OpenWhisk PHP plugin. Exactly how it should be!

One thought on “Using Composer with Serverless & OpenWhisk

Comments are closed.