Using symfony/demo as an example
symfony/demo
serverlessly in AWS Lambda$ symfony new --demo leeds-talk
$ symfony new --demo leeds-talk
$ composer require bref/bref bref/symfony-bridge
$ composer require bref/bref bref/symfony-bridge
Bref provides
// src/Kernel.php namespace App; + use Bref\SymfonyBridge\BrefKernel; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; - use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\Routing\RouteCollectionBuilder; - class Kernel extends BaseKernel + class Kernel extends BrefKernel { // ...
// src/Kernel.php namespace App; + use Bref\SymfonyBridge\BrefKernel; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; - use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\Routing\RouteCollectionBuilder; - class Kernel extends BaseKernel + class Kernel extends BrefKernel { // ...
# config/packages/framework.yaml framework: trusted_proxies: '127.0.0.1' trusted_headers: [ 'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-host' ]
# config/packages/framework.yaml framework: trusted_proxies: '127.0.0.1' trusted_headers: [ 'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-host' ]
# config/packages/prod/monolog.yaml monolog: handlers: # ... nested: type: stream path: php://stderr
# config/packages/prod/monolog.yaml monolog: handlers: # ... nested: type: stream path: php://stderr
service: symfony provider: name: aws region: us-east-1 stage: dev runtime: provided.al2 environment: APP_ENV: prod plugins: - ./vendor/bref/bref functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28
service: symfony provider: name: aws region: us-east-1 stage: dev runtime: provided.al2 environment: APP_ENV: prod plugins: - ./vendor/bref/bref functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28
service: leeds-talk-blog provider: name: aws region: us-east-1 stage: dev runtime: provided.al2 environment: APP_ENV: prod plugins: - ./vendor/bref/bref functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28
service: leeds-talk-blog provider: name: aws region: us-east-1 stage: dev runtime: provided.al2 environment: APP_ENV: prod plugins: - ./vendor/bref/bref functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28
service: leeds-talk-blog provider: name: aws region: eu-west-2 # London stage: dev runtime: provided.al2 environment: APP_ENV: prod plugins: - ./vendor/bref/bref functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28
service: leeds-talk-blog provider: name: aws region: eu-west-2 # London stage: dev runtime: provided.al2 environment: APP_ENV: prod plugins: - ./vendor/bref/bref functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28
$ serverless deploy
$ serverless deploy
$ composer install --no-dev --optimize-autoloader $ bin/console cache:clear --env=prod $ serverless deploy
$ composer install --no-dev --optimize-autoloader $ bin/console cache:clear --env=prod $ serverless deploy
$ serverless deploy
$ serverless deploy
$ serverless plugin install -n serverless-lift
$ serverless plugin install -n serverless-lift
# serverless.yml service: leeds-talk-blog provider: ... plugins: - ./vendor/bref/bref - serverless-lift functions: ... constructs: website: type: server-side-website assets: '/build/*': public/build '/favicon.ico': public/favicon.ico '/apple-touch-icon.png': public/apple-touch-icon.png '/robots.txt': public/robots.txt
# serverless.yml service: leeds-talk-blog provider: ... plugins: - ./vendor/bref/bref - serverless-lift functions: ... constructs: website: type: server-side-website assets: '/build/*': public/build '/favicon.ico': public/favicon.ico '/apple-touch-icon.png': public/apple-touch-icon.png '/robots.txt': public/robots.txt
# serverless.yml service: leeds-talk-blog ... package: patterns: - '!assets/**' - '!node_modules/**' - '!public/build/**' - '!tests/**' - '!var/**' - 'var/cache/prod/**' - 'public/build/entrypoints.json' - 'public/build/manifest.json'
# serverless.yml service: leeds-talk-blog ... package: patterns: - '!assets/**' - '!node_modules/**' - '!public/build/**' - '!tests/**' - '!var/**' - 'var/cache/prod/**' - 'public/build/entrypoints.json' - 'public/build/manifest.json'
$ serverless deploy
$ serverless deploy
$ serverless deploy
$ serverless deploy
# serverless.yml service: leeds-talk-blog provider: ... environment: APP_ENV: prod # replaced by postgres://user:pass@host/dbName DATABASE_URL: ${construct:database.databaseUrl} plugins: ... functions: ... constructs: website: ... database: type: database/sql engine: postgres password: ${env:DB_PASSWORD}
# serverless.yml service: leeds-talk-blog provider: ... environment: APP_ENV: prod # replaced by postgres://user:pass@host/dbName DATABASE_URL: ${construct:database.databaseUrl} plugins: ... functions: ... constructs: website: ... database: type: database/sql engine: postgres password: ${env:DB_PASSWORD}
pdo_pgsql
PHP extension ⚙# php/conf.d/php.ini extension=pdo_pgsql # you can configure more INI stuff here
# php/conf.d/php.ini extension=pdo_pgsql # you can configure more INI stuff here
$ serverless deploy
$ serverless deploy
$ serverless logs -f web
$ serverless logs -f web
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "symfony_demo_post" does not exist
# serverless.yml ... functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28 console: handler: bin/console layers: - ${bref:layer.php-80} - ${bref:layer.console} timeout: 120
# serverless.yml ... functions: web: events: - httpApi: '*' handler: public/index.php layers: - ${bref:layer.php-80-fpm} timeout: 28 console: handler: bin/console layers: - ${bref:layer.php-80} - ${bref:layer.console} timeout: 120
$ serverless deploy $ vendor/bin/bref cli leeds-talk-blog-dev-console -- doctrine:migration:migrate --no-interaction
$ serverless deploy $ vendor/bin/bref cli leeds-talk-blog-dev-console -- doctrine:migration:migrate --no-interaction
crontab
?Store them in a shared store like the Database or DynamoDB
# config/services.yaml services: # ... Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler: arguments: - '%env(DATABASE_URL)%'
# config/services.yaml services: # ... Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler: arguments: - '%env(DATABASE_URL)%'
Store them in a shared store like the Database or DynamoDB
# config/packages/framework.yaml framework: session: # ... handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
# config/packages/framework.yaml framework: session: # ... handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
I want to use Symfony Messenger!
$ composer require bref/symfony-messenger
$ composer require bref/symfony-messenger
I want to use Symfony Messenger!
# serverless.yml service: leeds-talk-blog provider: name: aws environment: ... MESSENGER_TRANSPORT_DSN: ${construct:jobs.queueUrl} constructs: ... jobs: type: queue alarm: thibault@widop.com worker: handler: bin/consumer.php timeout: 20 layers: - ${bref:layer.php-80}
# serverless.yml service: leeds-talk-blog provider: name: aws environment: ... MESSENGER_TRANSPORT_DSN: ${construct:jobs.queueUrl} constructs: ... jobs: type: queue alarm: thibault@widop.com worker: handler: bin/consumer.php timeout: 20 layers: - ${bref:layer.php-80}
I want to use Symfony Messenger!
I want to use Symfony Messenger!
# bin/consumer.php <?php declare(strict_types=1); use Bref\Symfony\Messenger\Service\Sqs\SqsConsumer; use Symfony\Component\Dotenv\Dotenv; require dirname(__DIR__).'/vendor/autoload.php'; (new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); $kernel = new \App\Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']); $kernel->boot(); // Return the Bref consumer service return $kernel->getContainer()->get(SqsConsumer::class);
# bin/consumer.php <?php declare(strict_types=1); use Bref\Symfony\Messenger\Service\Sqs\SqsConsumer; use Symfony\Component\Dotenv\Dotenv; require dirname(__DIR__).'/vendor/autoload.php'; (new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); $kernel = new \App\Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']); $kernel->boot(); // Return the Bref consumer service return $kernel->getContainer()->get(SqsConsumer::class);
I want to use Symfony Messenger!
# config/packages/messenger.yaml framework: messenger: transports: async: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' options: auto_setup: false routing: 'Symfony\Component\Mailer\Messenger\SendEmailMessage': async
# config/packages/messenger.yaml framework: messenger: transports: async: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' options: auto_setup: false routing: 'Symfony\Component\Mailer\Messenger\SendEmailMessage': async
class BlogController extends AbstractController { /** * @Route("/", defaults={"page": "1", "_format"="html"}, methods="GET", name="blog_index") * @Route("/rss.xml", defaults={"page": "1", "_format"="xml"}, methods="GET", name="blog_rss") * @Route("/page/{page<[1-9]\d*>}", defaults={"_format"="html"}, methods="GET", name="blog_index_paginated") * @Cache(smaxage="10") */ public function index(Request $request, int $page, string $_format, PostRepository $posts, TagRepository $tags): Response { ... } }
class BlogController extends AbstractController { /** * @Route("/", defaults={"page": "1", "_format"="html"}, methods="GET", name="blog_index") * @Route("/rss.xml", defaults={"page": "1", "_format"="xml"}, methods="GET", name="blog_rss") * @Route("/page/{page<[1-9]\d*>}", defaults={"_format"="html"}, methods="GET", name="blog_index_paginated") * @Cache(smaxage="10") */ public function index(Request $request, int $page, string $_format, PostRepository $posts, TagRepository $tags): Response { ... } }
crontab
?# serverless.yml ... functions: ... console: handler: bin/console layers: - ${bref:layer.php-80} - ${bref:layer.console} timeout: 120 events: - schedule: # cron(minutes hours day month weekday year) rate: cron(0 12 ? * MON-FRI *) # Monday to Friday at noon input: '"app:list-users --send-to=thibault@widop.com"'
# serverless.yml ... functions: ... console: handler: bin/console layers: - ${bref:layer.php-80} - ${bref:layer.console} timeout: 120 events: - schedule: # cron(minutes hours day month weekday year) rate: cron(0 12 ? * MON-FRI *) # Monday to Friday at noon input: '"app:list-users --send-to=thibault@widop.com"'
service: leeds-talk-blog provider: name: aws region: eu-west-2 # London stage: dev runtime: provided.al2 environment: ...
service: leeds-talk-blog provider: name: aws region: eu-west-2 # London stage: dev runtime: provided.al2 environment: ...
$ serverless deploy --stage=dev $ serverless deploy --stage=staging $ serverless deploy --stage=production $ serverless deploy --stage=marketing-demo $ serverless deploy --stage=acme-corp-tenant
$ serverless deploy --stage=dev $ serverless deploy --stage=staging $ serverless deploy --stage=production $ serverless deploy --stage=marketing-demo $ serverless deploy --stage=acme-corp-tenant
# serverless.yml ... constructs: website: # ... domain: blog.leedsphp.org certificate: arn:aws:acm:us-east-1:123456615250:certificate/0a28e63d-d3a9-4578-9f8b-14347bfe8123
# serverless.yml ... constructs: website: # ... domain: blog.leedsphp.org certificate: arn:aws:acm:us-east-1:123456615250:certificate/0a28e63d-d3a9-4578-9f8b-14347bfe8123
# serverless.yml ... constructs: website: # ... domain: - www.leedsphp.org - leedsphp.org redirectToMainDomain: true certificate: arn:aws:acm:us-east-1:123456615250:certificate/0a28e63d-d3a9-4578-9f8b-14347bfe8123
# serverless.yml ... constructs: website: # ... domain: - www.leedsphp.org - leedsphp.org redirectToMainDomain: true certificate: arn:aws:acm:us-east-1:123456615250:certificate/0a28e63d-d3a9-4578-9f8b-14347bfe8123
# serverless.yml ... constructs: website: # ... domain: - www.${env:DOMAIN_NAME} - ${env:DOMAIN_NAME} redirectToMainDomain: true certificate: ${env:CERTIFICATE_ARN}
# serverless.yml ... constructs: website: # ... domain: - www.${env:DOMAIN_NAME} - ${env:DOMAIN_NAME} redirectToMainDomain: true certificate: ${env:CERTIFICATE_ARN}
It’s question time!
@t__richard
Symfony & Bref Slack
💌 thibault@widop.com
⭐ github.com/brefphp/bref
⭐ github.com/getlift/lift