jlm/aws-bundle
JLM AWS Bundle integrates Amazon Web Services with PHP applications, offering configuration and service wiring for AWS clients so you can add cloud storage, messaging, and other AWS-backed features with less boilerplate. It streamlines setup and keeps AWS access consistent across your app.
This is a thin Symfony2 bundle around AWS PHP SDK 2.x (the Aws\Common\Aws service locator era), last touched in early 2014. Treat it as a convenience for wiring SDK credentials/region into the container, not as an abstraction layer — you will still be writing SDK 2.x client code.
Install and wire it up:
composer require jlm/aws-bundle:dev-master
Register in app/AppKernel.php:
public function registerBundles()
{
$bundles = array(
// ...
new JLM\AwsBundle\JLMAwsBundle(),
);
return $bundles;
}
Configure credentials in app/config/config.yml (typically jlm_aws as the root key — confirm against DependencyInjection/Configuration.php, since the bundle ships no meaningful docs):
jlm_aws:
key: "%aws_key%"
secret: "%aws_secret%"
region: "us-east-1"
Put the actual values in parameters.yml and never in config.yml. Then load the clients from the container.
Where to look first (in order):
DependencyInjection/Configuration.php — the authoritative list of config keys and defaults.Resources/config/services.xml (or .yml) — the authoritative service IDs. Do not guess jlm_aws.s3; grep for it.DependencyInjection/JLMAwsExtension.php — how config maps onto the Aws factory and which clients are pre-registered.First use case — an S3 upload from a controller:
$aws = $this->get('jlm_aws'); // the Aws\Common\Aws locator
$s3 = $aws->get('s3'); // returns Aws\S3\S3Client
$s3->putObject(array(
'Bucket' => 'my-bucket',
'Key' => 'uploads/'.$filename,
'SourceFile' => $path,
'ACL' => 'private',
));
If the service ID differs, the pattern is the same: the bundle hands you the SDK's service locator, and ->get('s3'), ->get('sqs'), ->get('dynamodb'), ->get('ses') yield the individual clients.
Inject the locator, not individual clients. Registering the bundle means the Aws locator is a shared service. Inject jlm_aws into your own services and resolve clients lazily per method call. This avoids instantiating every client for every request:
class AssetUploader
{
private $aws;
private $bucket;
public function __construct(\Aws\Common\Aws $aws, $bucket)
{
$this->aws = $aws;
$this->bucket = $bucket;
}
public function upload($path, $key)
{
return $this->aws->get('s3')->putObject(array(
'Bucket' => $this->bucket,
'Key' => $key,
'SourceFile' => $path,
));
}
}
Wire it in services.yml with <argument type="service" id="jlm_aws" />.
Keep bucket/queue/table names in parameters, not inline in code or in the bundle config. The bundle config should hold credentials and region; resource names belong to your application config so they can vary per environment (dev bucket vs prod bucket).
Wrap the SDK in a small domain service. Because the bundle is a raw passthrough, every caller that does $aws->get('s3')->putObject(...) is coupled to SDK 2.x. A single StorageService / QueueService per AWS domain gives you one place to change when you eventually migrate off SDK 2.x, and it makes the SDK mockable in tests.
Long-running work belongs in a console command. S3 multipart uploads, SQS polling, and SES batch sends should run from app/console commands rather than in the request cycle. The bundle works identically in CLI, but remember to warm the client once and reuse it — creating an Aws locator per message is wasteful.
Mocking for tests. Because the container returns a real Aws\Common\Aws, the cleanest test seam is your own wrapper service. In unit tests, build a stub Aws that returns a mocked S3Client (getMockBuilder('Aws\S3\S3Client')->disableOriginalConstructor()), or override the jlm_aws service in a test container with a fake locator.
Per-environment config. Symfony2's config_dev.yml / config_prod.yml can override jlm_aws keys. A common pattern is a stub IAM user with a narrow policy for dev and a distinct key pair in prod, both injected via parameters.yml from your deployment tooling.
Integrating with the rest of the stack. SDK 2.x clients accept a Guzzle\Common\Collection of options; the bundle usually exposes a way to pass extra client options through config. Use it to set curl.options timeouts and to attach the Symfony logger (see gotchas). For anything the bundle does not expose, call $aws->factory(array(...)) yourself to create an ad-hoc client — you do not have to go through the bundle's service for every AWS API.
This bundle is archived and unmaintained (last release 2014), and AWS SDK 2.x is itself end-of-life. It depends on Guzzle 3, which conflicts with essentially every modern PHP package. Composer will frequently refuse to install it alongside anything current. If you inherit a project using it, budget for migration rather than extension.
PHP version ceiling. SDK 2.x targets PHP 5.3–5.6. It will not run cleanly on PHP 7+ — expect deprecation noise and outright failures on 8.x. Do not attempt to use this on a modern runtime.
Signature and region quirks. SDK 2.x predates widespread SigV4 defaults. Some regions (notably newer ones like eu-central-1, ap-northeast-2) require explicitly setting signature => 'v4' on the client, and S3 in those regions needs the same. If you get AuthorizationHeaderMalformed or signature errors on a region that "should work", this is why. Pass the option through the bundle config or via $aws->factory().
Service IDs are not documented. The README is minimal. Always grep Resources/config/ before assuming a service name; the bundle may expose only the locator (jlm_aws) and nothing per-service. Guessing produces ServiceNotFoundException that looks like a bundle-registration problem but isn't.
Credential leakage in the container. jlm_aws config values are visible via app/console container:debug and in the profiler. Keep secrets in parameters.yml (gitignored) and consider an IAM instance role or environment variables instead of static keys — SDK 2.x can pick up credentials from the instance metadata if you omit the key/secret, which is usually the better pattern on EC2.
Errors are SDK exceptions, not Symfony ones. Catch Aws\Common\Exception\AwsException (and the more specific Aws\S3\Exception\S3Exception, Aws\Sqs\Exception\SqsException) around every call. AwsException::getAwsErrorCode() and getAwsErrorMessage() are your debugging entry points — the raw message alone often hides the actual AWS error code.
Enable logging early. SDK 2.x logs through Guzzle's log plugin. Attaching the Symfony logger to the client ($client->addSubscriber(new Guzzle\Plugin\Log\LogPlugin(...)) or via client options) is the fastest way to see the exact request, signature string, and response when something fails cryptically.
Retries and timeouts are not handled for you. Set explicit curl.options timeouts and rely on Guzzle's backoff plugin for throttling (ProvisionedThroughputExceededException on DynamoDB, RequestLimitExceeded on S3). The bundle does not add these.
Extension points are limited to config and the locator. There is no compiler pass for adding custom clients, so if you need a service the bundle does not register, register it yourself in your app's services.yml using $aws->factory() inside a factory method. That is the practical escape hatch.
Migration path. When you can, replace this bundle with aws/aws-sdk-php v3 directly (or async-aws/* for a lightweight footprint). The bundle adds almost nothing beyond credential wiring; a small AwsFactory service in your own code reproduces its entire value and keeps you on a supported SDK.
How can I help you explore Laravel packages today?