Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

We sometimes might have different values for same parameter in different environments. This example shows us how to define environment specific parameters in Symfony 4 applications. We will use a realy AWS SES utility class to send emails in prod environment but in dev and test environments we will use the mock utility class instead.


AwsController


namespace App\Controller;

use App\Util\Aws\AwsSesUtil;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

/**
* @Route("/aws")
*/
class AwsController
{
private $awsSesUtil;

public function __construct(AwsSesUtil $awsSesUtil)
{
$this->awsSesUtil = $awsSesUtil;
}

/**
* @Route("/ses")
* @Method({"GET"})
*/
public function send(): Response
{
$to = ['to@email.com'];
$from = 'from@email.com';
$subject = 'Test';
$body = 'This is a test';

$id = $this->awsSesUtil->sendEmail($to, $from, $subject, $body);

return new JsonResponse($id);
}
}

AwsSesUtil


This is the real one.


namespace App\Util\Aws;

use App\Exception\AwsException;
use Aws\Result;
use Aws\Ses\Exception\SesException;
use Aws\Ses\SesClient;

class AwsSesUtil extends AwsAbstractUtil
{
private const CHARSET = 'UTF-8';

public function sendEmail(
iterable $toAddresses,
string $fromAddress,
string $subject,
string $body
): ?string {
try {
/** @var SesClient $client */
$client = $this->sdk->createSes();

/** @var Result $result */
$result = $client->sendEmail([
'Destination' => [
'ToAddresses' => $toAddresses,
],
'Source' => $fromAddress,
'Message' => [
'Subject' => [
'Charset' => self::CHARSET,
'Data' => $subject,
],
'Body' => [
'Text' => [
'Charset' => self::CHARSET,
'Data' => $body,
],
],
],
]);

return $result->get('MessageId');
} catch (SesException $e) {
throw new AwsException(sprintf('[AWS SES] %s', $e->getAwsErrorMessage()));
}
}
}

AwsSesUtilMock


This is the mock version.


declare(strict_types=1);

namespace App\Tests\Mock;

use App\Util\Aws\AwsSesUtil;
use App\Exception\AwsException;

class AwsSesUtilMock extends AwsSesUtil
{
public function sendEmail(
iterable $toAddresses,
string $fromAddress,
string $subject,
string $body
): ?string {
if (
is_array($toAddresses) &&
$fromAddress &&
$subject &&
$body
) {
return 'MESSAGE_ID';
}

throw new AwsException('[AWS SES] Error while sending an email.');
}
}

Configuration files


config/services.yaml


imports:
- { resource: services/* }

parameters:

aws_sdk:
version: 'latest'
region: 'eu-west-1'
credentials:
key: 'AWS_KEY'
secret: 'AWS_SECRET'

services:
_defaults:
autowire: true
autoconfigure: true
public: false

App\:
resource: '../src/*'
exclude: '../src/{Controller,Util,Kernel.php}'

config/services/controllers.yaml


services:
_defaults:
autowire: true
autoconfigure: true
public: true

App\Controller\:
resource: '../../src/Controller'
tags: ['controller.service_arguments']

App\Controller\AwsController:
arguments:
- '@app.util.aws_ses_util'

config/services/utils.yaml


services:
_defaults:
autowire: true
autoconfigure: true
public: false

App\Util\:
resource: '../../src/Util'

Aws\Sdk:
arguments:
- '%aws_sdk%'

app.util.aws_ses_util:
class: '%aws_ses_util_class%'

config/packages/dev/parameters.yaml


This is pointing at the mock class.


parameters:

aws_ses_util_class: 'App\Tests\Mock\AwsSesUtilMock'

config/packages/test/parameters.yaml


This is pointing at the mock class.


parameters:

aws_ses_util_class: 'App\Tests\Mock\AwsSesUtilMock'

config/packages/prod/parameters.yaml


This is pointing at the real class.


parameters:

aws_ses_util_class: 'App\Util\Aws\AwsSesUtil'

Test


If you update the value for APP_ENV variable and call http://localhost.dev/aws/ses, you will see MESSAGE_ID as response for dev and test environments. If you change it to prod you will see the real message id such as 000201642d907400-0e7ea6ae-1111-2222-bc4c-e9039f4d15c5-333333 as the response.