![Page 1: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/1.jpg)
![Page 2: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/2.jpg)
ServerlessA Serverless solution is one that costs you nothing to run ifnobody is using it … excluding data storage costs.
Paul D. Johnston
Rob Allen ~ @akrabat
![Page 3: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/3.jpg)
as a ServiceStorage as a ServiceDatabase as a ServiceCache as a ServiceAuth as a ServiceSearch as a ServiceFunction as a Service
Rob Allen ~ @akrabat
![Page 4: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/4.jpg)
Function as a Service• Your code• Deployed to the cloud• Runs when needed• Scaled automatically• Pay only for execution
Rob Allen ~ @akrabat
![Page 5: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/5.jpg)
Use-cases
Rob Allen ~ @akrabat
![Page 6: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/6.jpg)
Use-casesSynchronous
Service is invoked and provides immediate response(HTTP requests: APIs, chat bots)
Rob Allen ~ @akrabat
![Page 7: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/7.jpg)
Use-casesSynchronous
Service is invoked and provides immediate response(HTTP requests: APIs, chat bots)
AsynchronousPush a message which drives an action later(web hooks, timed events, database changes)
Rob Allen ~ @akrabat
![Page 8: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/8.jpg)
Challenges
Rob Allen ~ @akrabat
![Page 9: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/9.jpg)
Challenges• Start up latency
Rob Allen ~ @akrabat
![Page 10: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/10.jpg)
Challenges• Start up latency• Time limit
Rob Allen ~ @akrabat
![Page 11: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/11.jpg)
Challenges• Start up latency• Time limit• State is external
Rob Allen ~ @akrabat
![Page 12: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/12.jpg)
Challenges• Start up latency• Time limit• State is external• Different way of thinking
Rob Allen ~ @akrabat
![Page 13: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/13.jpg)
It's about value
Rob Allen ~ @akrabat
![Page 14: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/14.jpg)
When should you use serverless?• Responding to web hooks
Rob Allen ~ @akrabat
![Page 15: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/15.jpg)
When should you use serverless?• Responding to web hooks• PWA/Static site contact form, et al.
Rob Allen ~ @akrabat
![Page 16: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/16.jpg)
When should you use serverless?• Responding to web hooks• PWA/Static site contact form, et al.• Additional features without extending current platform
Rob Allen ~ @akrabat
![Page 17: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/17.jpg)
When should you use serverless?• Responding to web hooks• PWA/Static site contact form, et al.• Additional features without extending current platform• Variable traffic levels
Rob Allen ~ @akrabat
![Page 18: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/18.jpg)
When should you use serverless?• Responding to web hooks• PWA/Static site contact form, et al.• Additional features without extending current platform• Variable traffic levels• When you want your costs to scale with traffic
Rob Allen ~ @akrabat
![Page 19: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/19.jpg)
Serverless platforms
Rob Allen ~ @akrabat
![Page 20: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/20.jpg)
Serverless platforms with PHP support
Rob Allen ~ @akrabat
![Page 21: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/21.jpg)
![Page 22: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/22.jpg)
Concepts
Rob Allen ~ @akrabat
![Page 23: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/23.jpg)
Rob Allen ~ @akrabat
![Page 24: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/24.jpg)
Rob Allen ~ @akrabat
![Page 25: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/25.jpg)
Hello world in PHP
Rob Allen ~ @akrabat
![Page 26: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/26.jpg)
Hello world in PHP
Rob Allen ~ @akrabat
![Page 27: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/27.jpg)
Upload your action
$ wsk action update hello hello.phpok: updated action hello
Rob Allen ~ @akrabat
![Page 28: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/28.jpg)
Run your action
$ wsk action invoke hello --result{ "msg": "Hello World"}
Rob Allen ~ @akrabat
![Page 29: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/29.jpg)
Segue: How did it do this?
Rob Allen ~ @akrabat
![Page 30: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/30.jpg)
OpenWhisk's architecture
Rob Allen ~ @akrabat
![Page 31: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/31.jpg)
Create an action
Rob Allen ~ @akrabat
![Page 32: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/32.jpg)
Invoke an action
Rob Allen ~ @akrabat
![Page 33: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/33.jpg)
Action container lifecycle• Hosts the user-written code• Controlled via two end points: /init & /run
Rob Allen ~ @akrabat
![Page 34: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/34.jpg)
Action container lifecycle• Hosts the user-written code• Controlled via two end points: /init & /run
Rob Allen ~ @akrabat
![Page 35: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/35.jpg)
End Segue
Rob Allen ~ @akrabat
![Page 36: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/36.jpg)
Turn it into an APIAdd the --web flag:
$ wsk action update hello hello.php --web true
Rob Allen ~ @akrabat
![Page 37: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/37.jpg)
Turn it into an APIAdd the --web flag:
$ wsk action update hello hello.php --web true$ curl https://openwhisk.ng.bluemix.net/api/v1/web/ \ 19FT_demo/default/hello.json{ "msg": "Hello World"}
Rob Allen ~ @akrabat
![Page 38: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/38.jpg)
API GatewayWhen you want to do more with HTTP endpoints
• Route endpoint methods to actions• Custom domains• Rate limiting• Security (API keys, OAuth, CORS)• Analytics
Rob Allen ~ @akrabat
![Page 39: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/39.jpg)
API Gateway
$ wsk api create /demo /hello GET hellook: created API /demo/hello GET for action /_/hello
Rob Allen ~ @akrabat
![Page 40: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/40.jpg)
API Gateway
$ curl https://ow.akrabat.com/demo/hello?name=Rob{ "message": "Hello Rob!"}
Rob Allen ~ @akrabat
![Page 41: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/41.jpg)
A Serverless API
Rob Allen ~ @akrabat
![Page 42: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/42.jpg)
Todo-BackendAn OpenWhisk PHP implementation of a to-do list API
Rob Allen ~ @akrabat
![Page 43: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/43.jpg)
Serverless FrameworkDeployment tooling for serverless applications
serverless.yml:
service: ow-todo-backend
provider: name: openwhisk runtime: php
plugins: - serverless-openwhisk
Rob Allen ~ @akrabat
![Page 44: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/44.jpg)
Configure actionfunctions: edit-todo: handler: "src/actions/editTodo.main" name: "todo-backend/edit-todo"
Rob Allen ~ @akrabat
![Page 45: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/45.jpg)
Configure actionfunctions: edit-todo: handler: "src/actions/editTodo.main" name: "todo-backend/edit-todo"
Rob Allen ~ @akrabat
![Page 46: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/46.jpg)
Configure actionfunctions: edit-todo: handler: "src/actions/editTodo.main" name: "todo-backend/edit-todo"
Rob Allen ~ @akrabat
![Page 47: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/47.jpg)
Configure API Gatewayfunctions: edit-todo: handler: "src/actions/editTodo.main" name: "todo-backend/edit-todo" events: - http: path: /todos/{id} method: patch
Rob Allen ~ @akrabat
![Page 48: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/48.jpg)
Configure API Gatewayfunctions: edit-todo: handler: "src/actions/editTodo.main" name: "todo-backend/edit-todo" events: - http: path: /todos/{id} method: patch
Rob Allen ~ @akrabat
![Page 49: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/49.jpg)
Project files.├── src/├── vendor/├── composer.json├── composer.lock├── serverless.yml
Rob Allen ~ @akrabat
![Page 50: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/50.jpg)
Project files.├── src/├── vendor/├── composer.json├── composer.lock├── serverless.yml
src/├── Todo/│ ├── Todo.php│ ├── TodoMapper.php│ └── TodoTransformer.php├── actions/│ ├── addTodo.php│ ├── deleteTodo.php│ ├── editTodo.php│ ├── listTodos.php│ └── showTodo.php└── AppContainer.php
Rob Allen ~ @akrabat
![Page 51: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/51.jpg)
editTodo.phpfunction main(array $args) : array{ try { $parts = explode("/", $args['__ow_path']); $id = (int)array_pop($parts);
$data = json_decode(base64_decode($args['__ow_body']), true); if (!is_array($data)) { throw new InvalidArgumentException('Missing body', 400); }
$container = new AppContainer($args); $mapper = $container[TodoMapper::class];
$todo = $mapper->loadById($id); $mapper->update($todo, $data);
$transformer = $container[TodoTransformer::class]; $resource = new Item($todo, $transformer, 'todos'); $fractal = $container[Manager::class];
return [ 'statusCode' => 200, 'body' => $fractal->createData($resource)->toArray(), ]; } catch (Throwable $e) { var_dump((string)$e); $code = $e->getCode() < 400 ? $e->getCode(): 500; return [ 'statusCode' => $code, 'body' => ['error' => $e->getMessage()]]; }}
Rob Allen ~ @akrabat
![Page 52: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/52.jpg)
editTodo.php: Error handlingfunction main(array $args) : array{ try { // do stuff } catch (Throwable $e) { var_dump((string)$e); $code = $e->getCode() < 400 ? $e->getCode() : 500; return [ 'statusCode' => $code, 'body' => ['error' => $e->getMessage()]]; }}
Rob Allen ~ @akrabat
![Page 53: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/53.jpg)
editTodo.php: Error handlingfunction main(array $args) : array{ try { // do stuff } catch (Throwable $e) { var_dump((string)$e); $code = $e->getCode() < 400 ? $e->getCode() : 500; return [ 'statusCode' => $code, 'body' => ['error' => $e->getMessage()]]; }}
Rob Allen ~ @akrabat
![Page 54: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/54.jpg)
editTodo.php: Error handlingfunction main(array $args) : array{ try { // do stuff } catch (Throwable $e) { var_dump((string)$e); $code = $e->getCode() < 400 ? $e->getCode() : 500; return [ 'statusCode' => $code, 'body' => ['error' => $e->getMessage()]]; }}
Rob Allen ~ @akrabat
![Page 55: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/55.jpg)
editTodo.php: Error handlingfunction main(array $args) : array{ try { // do stuff } catch (Throwable $e) { var_dump((string)$e); $code = $e->getCode() < 400 ? $e->getCode() : 500; return [ 'statusCode' => $code, 'body' => ['error' => $e->getMessage()]]; }}
Rob Allen ~ @akrabat
![Page 56: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/56.jpg)
editTodo.php: Grab input $parts = explode("/", $args['__ow_path']); $id = (int)array_pop($parts);
Rob Allen ~ @akrabat
![Page 57: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/57.jpg)
editTodo.php: Grab input $parts = explode("/", $args['__ow_path']); $id = (int)array_pop($parts);
$body = base64_decode($args['__ow_body']; $data = json_decode($body), true); if (!is_array($data)) { throw new Exception('Missing body', 400); }
Rob Allen ~ @akrabat
![Page 58: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/58.jpg)
editTodo.php: Grab input $parts = explode("/", $args['__ow_path']); $id = (int)array_pop($parts);
$body = base64_decode($args['__ow_body']; $data = json_decode($body), true); if (!is_array($data)) { throw new Exception('Missing body', 400); }
Rob Allen ~ @akrabat
![Page 59: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/59.jpg)
editTodo.php: Do the work $container = new AppContainer($args); $mapper = $container[TodoMapper::class];
$todo = $mapper->loadById($id); $mapper->update($todo, $data);
Rob Allen ~ @akrabat
![Page 60: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/60.jpg)
editTodo.php: Do the work $container = new AppContainer($args); $mapper = $container[TodoMapper::class];
$todo = $mapper->loadById($id); $mapper->update($todo, $data);
Rob Allen ~ @akrabat
![Page 61: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/61.jpg)
editTodo.php: Do the work $container = new AppContainer($args); $mapper = $container[TodoMapper::class];
$todo = $mapper->loadById($id); $mapper->update($todo, $data);
Rob Allen ~ @akrabat
![Page 62: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/62.jpg)
editTodo.php: Present results $transformer = $container[TodoTransformer::class]; $resource = new Item($todo, $transformer, 'todos'); $fractal = $container[Manager::class];
$output = $fractal->createData($resource);
return [ 'statusCode' => 200, 'body' => $output->toArray(), ];
Rob Allen ~ @akrabat
![Page 63: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/63.jpg)
editTodo.php: Present results $transformer = $container[TodoTransformer::class]; $resource = new Item($todo, $transformer, 'todos'); $fractal = $container[Manager::class];
$output = $fractal->createData($resource);
return [ 'statusCode' => 200, 'body' => $output->toArray(), ];
Rob Allen ~ @akrabat
![Page 64: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/64.jpg)
editTodo.php: Present results $transformer = $container[TodoTransformer::class]; $resource = new Item($todo, $transformer, 'todos'); $fractal = $container[Manager::class];
$output = $fractal->createData($resource);
return [ 'statusCode' => 200, 'body' => $output->toArray(), ];
Rob Allen ~ @akrabat
![Page 65: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/65.jpg)
Deploy$ serverless deployServerless: Packaging service...Serverless: Compiling Functions...Serverless: Compiling Packages...Serverless: Compiling API Gateway definitions...Serverless: Compiling Rules...Serverless: Compiling Triggers & Feeds...Serverless: Compiling Service Bindings...Serverless: Deploying Packages...Serverless: Deploying Functions...Serverless: Deploying API Gateway definitions...[...]
Rob Allen ~ @akrabat
![Page 66: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/66.jpg)
A working API!
Rob Allen ~ @akrabat
![Page 67: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/67.jpg)
Rob Allen ~ @akrabat
![Page 68: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/68.jpg)
AWS Lambda with PHPOnly sensibly possible since November 2018 with the introductionof layers
Rob Allen ~ @akrabat
![Page 69: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/69.jpg)
AWS Lambda with PHPOnly sensibly possible since November 2018 with the introductionof layers
Process:1. Create a layer containing:
1. the PHP executable2. a bootstrap script
2. Write the PHP function!
Rob Allen ~ @akrabat
![Page 70: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/70.jpg)
.
![Page 71: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/71.jpg)
Bref• Maintained PHP runtimes for AWS Lambda• Deployment via Serverless Framework• Great documentation!
Rob Allen ~ @akrabat
![Page 72: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/72.jpg)
Bref PHP function<?php declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
return function($event) { return 'Hello ' . ($event['name'] ?? 'world');}
Rob Allen ~ @akrabat
![Page 73: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/73.jpg)
serverless.ymlservice: helloappprovider: name: aws runtime: provided
functions: hello: handler: index.php layers: - ${bref:layer.php-73}
Rob Allen ~ @akrabat
![Page 74: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/74.jpg)
serverless.ymlservice: helloappprovider: name: aws runtime: provided
functions: hello: handler: index.php layers: - ${bref:layer.php-73}
Rob Allen ~ @akrabat
![Page 75: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/75.jpg)
serverless.ymlservice: helloappprovider: name: aws runtime: provided
functions: hello: handler: index.php layers: - ${bref:layer.php-73}
Rob Allen ~ @akrabat
![Page 76: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/76.jpg)
Deploy$ serverless deployServerless: Packaging service......Serverless: Stack update finished...
Service Informationservice: helloappstage: devstack: helloapp-devfunctions: hello: helloapp-dev-hello
Rob Allen ~ @akrabat
![Page 77: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/77.jpg)
Run$ serverless invoke -f hello"Hello world"
Rob Allen ~ @akrabat
![Page 78: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/78.jpg)
Run$ serverless invoke -f hello"Hello world"
$ serverless invoke -f hello -d '{"name": "Rob"}'"Hello Rob"
Rob Allen ~ @akrabat
![Page 79: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/79.jpg)
Run locally in Docker$ serverless invoke local --docker -f helloServerless: Building Docker image......REPORT RequestId: 6a653a94-ee51-1f3e-65c7-1f1954842f29 Init Duration: 265.93 ms Duration: 145.37 ms Billed Duration: 200 ms Memory Size: 1024 MB Max Memory Used: 27 MB
"Hello world"
Xdebug also works!
Rob Allen ~ @akrabat
![Page 80: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/80.jpg)
Add AWS API Gatewayserverless.yml:functions: hello: handler: index.php ... events: - http: "GET /hello" - http: "GET /hi/{name}"
Rob Allen ~ @akrabat
![Page 81: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/81.jpg)
Return a PSR-15 RequestHandlerclass HelloHandler implements RequestHandlerInterface{ public function handle(ServerRequest $request): Response { $name = ($request->getQueryParams()['name'] ?? 'world'); $body = 'Hello ' . $name;
return new Response(200, ['Content-Type' => 'text/plain'], $body); }}
Rob Allen ~ @akrabat
![Page 82: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/82.jpg)
Deploy$ serverless deployServerless: Packaging service......
Service Informationservice: helloappstage: devstack: helloapp-devendpoints: GET - https://l1v6cz13zb.execute-api.eu-west-2 .amazonaws.com/dev/hello
Rob Allen ~ @akrabat
![Page 83: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/83.jpg)
Test$ curl -i https://l1v6cz...naws.com/dev/hello?name=RobHTTP/2 200content-type: text/plaincontent-length: 9
Hello Rob
Rob Allen ~ @akrabat
![Page 84: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/84.jpg)
Project 365My photo-a-day website
Rob Allen ~ @akrabat
![Page 85: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/85.jpg)
Project 365Static website to display my photo-a-day picture for each day ofthe year.
• Hosted on S3• CloudFront CDN• Lambda/PHP function
Rob Allen ~ @akrabat
![Page 86: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/86.jpg)
Lambda/PHP function
Rob Allen ~ @akrabat
![Page 87: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/87.jpg)
Serverless configurationfunctions: update: handler: index.php events: - schedule: name: project365-build rate: cron(0 */2 * * ? *)
Rob Allen ~ @akrabat
![Page 88: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/88.jpg)
Serverless configurationfunctions: update: handler: index.php events: - schedule: name: project365-build rate: cron(0 */2 * * ? *)
Rob Allen ~ @akrabat
![Page 89: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/89.jpg)
Serverless configurationfunctions: update: handler: index.php events: - schedule: name: project365-build rate: cron(0 */2 * * ? *)
Rob Allen ~ @akrabat
![Page 90: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/90.jpg)
main()function main(array $eventData) : array{ $year = $eventData['year'] ?? date('Y');
$pageCreator = new PhotoPageCreator(); $html = $pageCreator->update($year); $uploader = new Uploader($cloudFrontId); $uploader->uploadOne($year, $html, $s3Bucket); $uploader->invalidateCache(['/'.$year]);}
Rob Allen ~ @akrabat
![Page 91: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/91.jpg)
main()function main(array $eventData) : array{ $year = $eventData['year'] ?? date('Y');
$pageCreator = new PhotoPageCreator(); $html = $pageCreator->update($year); $uploader = new Uploader($cloudFrontId); $uploader->uploadOne($year, $html, $s3Bucket); $uploader->invalidateCache(['/'.$year]);}
Rob Allen ~ @akrabat
![Page 92: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/92.jpg)
main()function main(array $eventData) : array{ $year = $eventData['year'] ?? date('Y');
$pageCreator = new PhotoPageCreator(); $html = $pageCreator->update($year); $uploader = new Uploader($cloudFrontId); $uploader->uploadOne($year, $html, $s3Bucket); $uploader->invalidateCache(['/'.$year]);}
Rob Allen ~ @akrabat
![Page 93: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/93.jpg)
main()function main(array $eventData) : array{ $year = $eventData['year'] ?? date('Y');
$pageCreator = new PhotoPageCreator(); $html = $pageCreator->update($year); $uploader = new Uploader($cloudFrontId); $uploader->uploadOne($year, $html, $s3Bucket); $uploader->invalidateCache(['/'.$year]);}
Rob Allen ~ @akrabat
![Page 94: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/94.jpg)
main()function main(array $eventData) : array{ $year = $eventData['year'] ?? date('Y');
$pageCreator = new PhotoPageCreator(); $html = $pageCreator->update($year); $uploader = new Uploader($cloudFrontId); $uploader->uploadOne($year, $html, $s3Bucket); $uploader->invalidateCache(['/'.$year]);}
Rob Allen ~ @akrabat
![Page 95: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/95.jpg)
Fetch photos from Flickr $url = '?' . http_build_query([ 'api_key' => $this->flickrApiKey, 'user_id' => $flickrUserId, 'extras' => 'url_z, date_taken, owner_name', 'method' => 'flickr.photos.search', 'tags' => $year, ]);
$response = $this->client->get($url); $data = json_decode($response->getBody(), true); return $data['photos'];
Rob Allen ~ @akrabat
![Page 96: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/96.jpg)
Fetch photos from Flickr $url = '?' . http_build_query([ 'api_key' => $this->flickrApiKey, 'user_id' => $flickrUserId, 'extras' => 'url_z, date_taken, owner_name', 'method' => 'flickr.photos.search', 'tags' => $year, ]);
$response = $this->client->get($url); $data = json_decode($response->getBody(), true); return $data['photos'];
Rob Allen ~ @akrabat
![Page 97: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/97.jpg)
Fetch photos from Flickr $url = '?' . http_build_query([ 'api_key' => $this->flickrApiKey, 'user_id' => $flickrUserId, 'extras' => 'url_z, date_taken, owner_name', 'method' => 'flickr.photos.search', 'tags' => $year, ]);
$response = $this->client->get($url); $data = json_decode($response->getBody(), true); return $data['photos'];
Rob Allen ~ @akrabat
![Page 98: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/98.jpg)
Fetch photos from Flickr $url = '?' . http_build_query([ 'api_key' => $this->flickrApiKey, 'user_id' => $flickrUserId, 'extras' => 'url_z, date_taken, owner_name', 'method' => 'flickr.photos.search', 'tags' => $year, ]);
$response = $this->client->get($url); $data = json_decode($response->getBody(), true); return $data['photos'];
Rob Allen ~ @akrabat
![Page 99: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/99.jpg)
Upload to S3$s3 = new S3Client([ 'version' => 'latest', 'region' => getenv('AWS_DEFAULT_REGION')]);
$s3->putObject([ 'Bucket' => $bucketName, 'ACL' => 'public-read', 'Key' => "/$year.html", 'Body' => $data, 'ContentType' => 'text/html',]);
Rob Allen ~ @akrabat
![Page 100: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/100.jpg)
Upload to S3$s3 = new S3Client([ 'version' => 'latest', 'region' => getenv('AWS_DEFAULT_REGION')]);
$s3->putObject([ 'Bucket' => $bucketName, 'ACL' => 'public-read', 'Key' => "/$year.html", 'Body' => $data, 'ContentType' => 'text/html',]);
Rob Allen ~ @akrabat
![Page 101: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/101.jpg)
Upload to S3$s3 = new S3Client([ 'version' => 'latest', 'region' => getenv('AWS_DEFAULT_REGION')]);
$s3->putObject([ 'Bucket' => $bucketName, 'ACL' => 'public-read', 'Key' => "/$year.html", 'Body' => $data, 'ContentType' => 'text/html',]);
Rob Allen ~ @akrabat
![Page 102: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/102.jpg)
Invalidate CloudFront$cft = new CloudFrontClient([ .. ]);
$result = $cft->createInvalidation([ 'DistributionId' => $cloudFrontId, 'InvalidationBatch' => [ 'CallerReference' => date('YmdHis'), 'Paths' => [ 'Items' => ["/$year.html"], 'Quantity' => 1, ], ],]);
Rob Allen ~ @akrabat
![Page 103: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/103.jpg)
Invalidate CloudFront$cft = new CloudFrontClient([ .. ]);
$result = $cft->createInvalidation([ 'DistributionId' => $cloudFrontId, 'InvalidationBatch' => [ 'CallerReference' => date('YmdHis'), 'Paths' => [ 'Items' => ["/$year.html"], 'Quantity' => 1, ], ],]);
Rob Allen ~ @akrabat
![Page 104: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/104.jpg)
Invalidate CloudFront$cft = new CloudFrontClient([ .. ]);
$result = $cft->createInvalidation([ 'DistributionId' => $cloudFrontId, 'InvalidationBatch' => [ 'CallerReference' => date('YmdHis'), 'Paths' => [ 'Items' => ["/$year.html"], 'Quantity' => 1, ], ],]);
Rob Allen ~ @akrabat
![Page 105: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/105.jpg)
Invalidate CloudFront$cft = new CloudFrontClient([ .. ]);
$result = $cft->createInvalidation([ 'DistributionId' => $cloudFrontId, 'InvalidationBatch' => [ 'CallerReference' => date('YmdHis'), 'Paths' => [ 'Items' => ["/$year.html"], 'Quantity' => 1, ], ],]);
Rob Allen ~ @akrabat
![Page 106: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/106.jpg)
The finished website
Rob Allen ~ @akrabat
![Page 107: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/107.jpg)
To sum up
Rob Allen ~ @akrabat
![Page 108: Serverless · For example, if you take an AWS based Serverless solution, you would have something like this: API Gateway + Lambda + DynamoDB + S3 + SNS + DynamoDB Streams + SES +](https://reader035.vdocuments.net/reader035/viewer/2022081402/5f1d0760daf4b82b9b0a0a3d/html5/thumbnails/108.jpg)
Resources• https://akrabat.com• https://www.martinfowler.com/articles/serverless.html
• https://github.com/akrabat/ow-php-todo-backend• https://github.com/akrabat/project365-photos-website
• http://www.openwhisk.org• https://aws.amazon.com/lambda/• https://bref.sh
Rob Allen ~ @akrabat