Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Flysystem & S3

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

With our key & secret in hand, and this unescapable feeling of power that they're giving us, let's hook up Flysystem to use an S3 adapter. Oh, first, go check on that library we were installing. Done! This is a PHP library for interacting with any AWS service, and it has nothing to do with Symfony or Flysystem. Copy the example configuration. Our first job is to register a service for this S3Client class that comes from that library.

Registering the S3Client Service

Let's close all these tabs so we can concentrate. Open config/services.yaml and, at the bottom, paste that config! But I'm going to simplify this: copy the class name, remove it, and paste that as the service id. Why? First, because, when possible, it's just easier to use the class name as the service id instead of inventing a string id. And second, this will allow us to autowire the S3Client service into any of our services or controllers. We won't need that for what we're doing, but it's nice.

... lines 1 - 53
Aws\S3\S3Client:
arguments:
-
version: '2006-03-01' # or 'latest'
region: "region-id" # 'eu-central-1' for example
credentials:
key: "s3-key"
secret: "s3-secret"

This takes just one argument: a big array of config. This old looking API version is actually still the most recent. For region, this depends on what region you chose for your bucket. Mine is us-east-1 because I selected Virginia. If you selected a different region, it won't work. Kidding! Just do some Googling to find the right region id.

What about the key and secret? These are the values IAM gave us after creating the user. But, we probably don't want to put their values right here and commit them to the repository. Instead, open the .env file and, inside of the custom vars section we created in a previous tutorial, let's invent two new environment variables AWS_S3_ACCESS_ID and AWS_S3_ACCESS_SECRET.

38 lines .env
... lines 1 - 32
AWS_S3_ACCESS_ID=
AWS_S3_ACCESS_SECRET=
... lines 35 - 38

If you want, you could copy the values and put them directly into this file. But remember, the .env file is committed to your git repository... and you really don't want any secret value to be committed. Instead, create a new file at the root of your app called .env.local. This file is also read by Symfony and any values will override the ones in .env. It's also ignored from git via our .gitignore file.

Copy the two keys from .env and paste them here. And now we can grab the real values. Copy the id, paste, then show the secret, copy, and paste that.

Environment variables, set! To use them, head back to services.yaml. Replace the key with the special environment variable syntax: %env()% and inside, AW... go copy the name - AWS_S3_ACCESS_ID. Re-use that syntax for the secret: AWS_S3_ACCESS_SECRET.

... lines 1 - 53
Aws\S3\S3Client:
arguments:
-
version: '2006-03-01'
region: 'us-east-1'
credentials:
key: '%env(AWS_S3_ACCESS_ID)%'
secret: '%env(AWS_S3_ACCESS_SECRET)%'

If you forget about Flysystem for a minute, we now have a fully functional S3Client service that we an autowire and use to do anything with our new bucket! The question now is: how can we tell Flysystem to use this?

The Flysystem AWS-S3-V3 Adapter

Go back to the OneupFlysystemBundle docs. Ok, so once the service is set up, we apparently need to go into the actual config for this bundle and change to a new adapter: awss3v3.

But to use that... hmm... it's not too obvious on this page. Go back to the Flysystem docs about S3 and scroll up. Here we go: the Flysystem S3 adapter is its own separate package. Copy this line, find your terminal and paste:

composer require "league/flysystem-aws-s3-v3:^1.0"

Once that finishes... there. Now we can use this awss3v3 adapter. Open up config/packages/oneup_flysystem.yaml. Remove all that local config. Replace it with awss3v3:. The first sub-key this needs is: client, which points to the service id for the S3Client.

... line 1
oneup_flysystem:
adapters:
public_uploads_adapter:
awss3v3:
... lines 6 - 19

Add client:, copy the service id, and paste.

... line 1
oneup_flysystem:
adapters:
public_uploads_adapter:
awss3v3:
client: Aws\S3\S3Client
... lines 7 - 19

The adapter also needs to know what S3 bucket it should be talking to. This is also something that you might not want to commit to your repository, because production will probably use a different bucket than when you're developing locally. So, back in our trusty .env file, add a third environment variable AWS_S3_ACCESS_BUCKET... well, I could just call this AWS_S3_BUCKET... I didn't really mean to keep that ACCESS part in there. But, no problem.

39 lines .env
... lines 1 - 34
AWS_S3_BUCKET_NAME=
... lines 36 - 39

Just like before, copy that, duplicate it in .env.local and give it a real value, which... if you go back to S3, is sfcasts-spacebar. Paste that.

Finally, copy the new variable's name, open oneup_flysystem.yaml, and set bucket to %env(AWS_S3_ACCESS_BUCKET)%.

... line 1
oneup_flysystem:
adapters:
public_uploads_adapter:
awss3v3:
client: Aws\S3\S3Client
bucket: '%env(AWS_S3_BUCKET_NAME)%'
... lines 8 - 19

That's it! What about the private_uploads_adapter? Well, temporarily, copy the config from the public adapter and paste it exactly down there. We're actually not going to need two filesystems anymore... but we'll talk about that soon.

... line 1
oneup_flysystem:
adapters:
public_uploads_adapter:
awss3v3:
client: Aws\S3\S3Client
bucket: '%env(AWS_S3_BUCKET_NAME)%'
... lines 8 - 19

Oh, and don't forget the % sign at the end of the %env()% syntax! I did do that correctly in services.yaml.

Ok, I think we're ready! Both filesystems will use an awss3v3 adapter and each of those knows to us the S3Client service that's reading our key and secret. So... it should... just kinda work! The easiest way to find out is to reload the fixtures:

php bin/console doctrine:fixtures:load

And yes, I do recommend using S3 when developing locally if that's what you're using on production. You could change the adapter to be the local adapter, but the less differences you have between your local environment & production, the better.

Fixtures done! Go and refresh the S3 page. Hey! We have an article_image directory and it's full of images! I think it worked! Go the homepage and... nothing works. That's because our paths are all still pointing at the local server - not at S3. Let's fix that next!

Leave a comment!

21
Login or Register to join the conversation

Hello,
When install the composer require league/flysystem-aws-s3-v3 on symfony 5, the script not install config file oneup_flysystems.yaml on packages/, and the composer.json have "league/flysystem-aws-s3-v3": "^2.0".
I not understand happend. Some any idea?

Reply

Hey mitosu

Do your composer allows to install third party recipes? Inside your `composer.json` you should have this piece of config


{
...
"extra": {
"symfony": {
"allow-contrib": true,
}
},
...
}

You can re-run any recipe by running this command composer recipes:install vendor/package --force -v

Cheers!

Reply
Nikolaj M. Avatar
Nikolaj M. Avatar Nikolaj M. | MolloKhan | posted 1 year ago | edited

Greetings MolloKhan ,

I'm having the same issue as @Miguel described above and was wondering what I could do to resolve this issue.
My composer json contains the following records:
"aws/aws-sdk-php": "^3.173",
"league/flysystem-aws-s3-v3": "^2.0",

This with allow-contrib at true and forcing the recipes to be installed, the yaml file does not generated.
if I add the file manually, then the system generates the following error:

There is no extension able to load the configuration for "oneup_flysystem" (in "/var/www/config/packages/oneup_flysystem.yaml")

From what i can see, is that the oneup/flysystem-bundle is no longer part of the package when installing flysystem-aws-s3-v3 as this is not compatible with league/flysystem

EDIT: i was able to resolve to lock the packages to the versions you used in the video from the composer.json.
It seems the new version of flysystem-aws-s3-v3 is operating differently and no longer requires the flysystem-bundle

Reply

Hey Nikolaj M.

Did you get that error after installing the oneup/flysystem-bundle bundle? As I can tell the bundle configuration still exists in the master branch https://github.com/1up-lab/...

Cheers!

Reply
Default user avatar
Default user avatar Nikolaj Malezsewski | MolloKhan | posted 1 year ago

Hey @Diego, sorry for the late response. The problem lied in the fact that the new league/flysystem-aws-s3-v3 comes with a different recipe and thus does not install the flysystem-bundle. When I installed the package versions you used in this demo, the functionalities work just fine as expected/explained. I tried installing the bundle manually but the updated s3 package does not use it so a different configuration/method is required then what is documented here.

Perhaps it would be good to update the text with the used version number to prevent users having the same issue in the future.

Reply

Hey Nikolaj Malezsewski and Nikolaj

I tried to replicate this problem by creating a new Sf5 project and install both libraries. I didn't get any errors. So, seems like we got confused. The package league/flysystem-aws-s3-v3 does not install any recipes because it has nothing to do with Symfony but the bundle oneup/flysystem-bundle is the one which comes with a recipe. Is there a chance that you added the config/packages/oneup_flysystem.yaml file before installing the bundle?

Reply

Hey Nikolaj Malezsewski

Thanks for the explanation, it's clearer now what happened. We'll add a note on the video to avoid this hassle to other users. Thanks!

Reply
Kiuega Avatar

Hello, I see that we are required to enter our credit card to create an account on AWS, even to take advantage of only the free option. I would just like to use it to find out for now. Is it possible to create an account with my credit card in it, then cancel just before the end of my free period in order to pay nothing? And why not recreate an account and benefit from the free period again?

Reply

Hey Kiuega!

> Hello, I see that we are required to enter our credit card to create an account on AWS, even to take advantage of only the free option

It's been so long since I signed up, I wasn't aware of that! I get why they do it - but yea, it's unfortunate for testing :/.

> Is it possible to create an account with my credit card in it, then cancel just before the end of my free period in order to pay nothing?

If I remember correctly (but I may not), it's not exactly a free period (e.g. free 1 month), it's a free "tier". Like you can use a certain number of free EC2 hours per month... though all of this only applies for the first 12 months of your account. My point is, if you stick to the truly free features/tiers, then you don't need to cancel at all: you're simply not charged. S3 also has a free tier - https://aws.amazon.com/s3/p...

> And why not recreate an account and benefit from the free period again?

You could - but you'd have to do it every 12 months and the only thing you'd be getting for free are really low-level EC2 instances, S3 etc. It's not a ton of value.

By the way, they have a good cost tracker in the billing section. If you accidentally started using something that's not free, you could find out pretty quickly (probably before you spend even $1).

Cheers!

1 Reply
Raed Avatar

Hey team,

I have an error when installing composer require league/flysystem-aws-s3-v3

PS C:\xampp\htdocs\SymfonyCasts\Symfony4\AllaboutUplFiles\01_start> composer require league/flysystem-aws-s3-v3
Using version ^1.0 for league/flysystem-aws-s3-v3
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Restricting packages listed in "symfony/symfony" to "4.2.*"
Nothing to install or update
Package easycorp/easy-log-handler is abandoned, you should avoid using it. No replacement was suggested.
Package zendframework/zend-code is abandoned, you should avoid using it. Use laminas/laminas-code instead.
Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead.
Generating autoload files
3 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
Executing script cache:clear [KO]
[KO]
3 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
Executing script cache:clear [KO]
[KO]
Script cache:clear returned with error code 1
!!
!! In CheckDefinitionValidityPass.php line 69:
!!
!! The definition for "arguments" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true.
!! If this is an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this
e
!! rror.
Script @auto-scripts was called via post-update-cmd

Installation failed, reverting ./composer.json to its original content.

In services.yaml
services:
# default configuration for services in *this* file
_defaults:
autowire: true
autoconfigure: true
public: false

I don't know that synthetic=true should be declared.
I would appreciate your help !

Reply

Hey Raed

That's odd. Would be nice to know which service is triggering that error. If you clear your cache without installing that bundle, does the error happens?
Also, try re-installing your vendors

Reply
Raed Avatar
Raed Avatar Raed | MolloKhan | posted 2 years ago | edited

Hey MolloKhan,

Thanks for your reply!

I could install the composer require league/flysystem-aws-s3-v3
Then i removed the vendor and tried to run composer install however i had the same error the installation could 'not be completed
the error :

!! In CheckDefinitionValidityPass.php line 69:
!!
!! The definition for "arguments" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is an
!! abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.
!!

Reply

Hmm, we need to gather more information. Can you "composer install" again but passing in -vvv so we can get more debugging info. Also, can you tell me which Symfony version are you using and what OS you are using?

Reply
Raed Avatar
Raed Avatar Raed | MolloKhan | posted 2 years ago | edited

Hey <code>MolloKhan,

Thanks for your reply !

After i tried to run "composer install -vvv" i got :


Reading ./composer.json
Loading config file ./composer.json
Checked CA file C:\Users\Raed\AppData\Local\Temp\ope6C68.tmp: valid
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): git branch --no-color --no-abbrev -v
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): git describe --exact-match --tags
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): git log --pretty="%H" -n1 HEAD
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): hg branch
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): fossil branch list
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): fossil tag list
Executing command (C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start): svn info --xml
Reading C:/Users/Raed/AppData/Roaming/Composer/composer.json
Loading config file C:/Users/Raed/AppData/Roaming/Composer/composer.json
Reading C:\xampp\htdocs\SymfonyCasts2\Symfony4\AllaboutUplFiles\01_start/vendor/composer/installed.json
Reading C:/Users/Raed/AppData/Roaming/Composer/vendor/composer/installed.json
Loading plugin Symfony\Flex\Flex
Loading plugin PackageVersions\Installer
Running 1.10.7 (2020-06-03 10:03:56) with PHP 7.4.5 on Windows NT / 10.0
Reading ./composer.lock
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Reading ./composer.lock
Resolving dependencies through SAT
Looking at all rules.

Dependency resolution completed in 0.028 seconds
Analyzed 291 packages to resolve dependencies
Analyzed 1135 rules to resolve dependencies
Nothing to install or update
Package easycorp/easy-log-handler is abandoned, you should avoid using it. No replacement was suggested.
Package zendframework/zend-code is abandoned, you should avoid using it. Use laminas/laminas-code instead.
Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead.
Generating autoload files
17 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
Looking at all rules.

Dependency resolution completed in 0.028 seconds
Analyzed 291 packages to resolve dependencies
Analyzed 1135 rules to resolve dependencies
Nothing to install or update
Package easycorp/easy-log-handler is abandoned, you should avoid using it. No replacement was suggested.
Package zendframework/zend-code is abandoned, you should avoid using it. Use laminas/laminas-code instead.
Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead.
Generating autoload files
17 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
> post-install-cmd: @auto-scripts
Executing script cache:clear
Executed script cache:clear [KO]
[KO]
Script cache:clear returned with error code 1
!!
!! In CheckDefinitionValidityPass.php line 69:
!!
!! The definition for "arguments" has no class. If you intend to inject this service dynamically at runtime, please mark it as synthetic=true. If this is
!! an abstract definition solely used by child definitions, please add abstract=true, otherwise specify a class to get rid of this error.
!!
Script @auto-scripts was called via post-install-cmd

- I'm using PHP version 7.4.5 but in the project is set to 7.1.3 with Windows Operating Systems.

Thanks for your help !

Reply

Hey Raed!

Hmm. I have a *feeling*, but I could be wrong, that this is not directly related to installing the league/flysystem-aws-s3-v3 package. The error makes it seem like you have this in a service file somewhere (e.g. in your services.yaml file):


services:
# ... any number of lines

# some service registration
Some\ServiceHere:
# set some arguments on the service
arguments:
$isFoo: true

Do you see the problem? In my code, arguments is NOT indented *under* the Some\ServiceHere service - it should have 8 spaces in front of it, not 4. With this config (or, at least some config *like* this), Symfony would think that arguments is the id of a *new* service that we're registering. And then it would fail because we never set a "class" for this service.

So, double-check your service code everywhere. In theory, you should be seeing this code even if you uninstalled the library. If you can't find it, post your services.yaml file and we'll see if we can spot the problem :).

Cheers!

Reply
sadikoff Avatar sadikoff | SFCASTS | Raed | posted 2 years ago | edited

Hey Raed

Which PHP version do you use? Second question did the bundle installed? I don't see installation records in your log.

Cheers!

Reply
Raed Avatar
Raed Avatar Raed | sadikoff | posted 2 years ago | edited

Hey sadikoff,

I use version PHP 7.4.5. The bundle could'not be installed.

Reply
Patrick M. Avatar
Patrick M. Avatar Patrick M. | posted 3 years ago

I have the same error, what can I do ?
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

Reply

Hey Patrick,

Could you explain what exactly are you doing when seeing this error?

Cheers!

Reply
Edison V. Avatar
Edison V. Avatar Edison V. | posted 3 years ago

Anyone facing (faced) this ugly error?

AWS HTTP error: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl...

I've read tons of articles about it, but nothing worked....(I'm on Windows, symfony local cert authority installed)

Thanks!

Reply

Hey Edison V.

We were applying some changes to our Challenges system but it should be OK now. I'm sorry for any inconvenience

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built on Symfony 4 but works great in Symfony 5!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "aws/aws-sdk-php": "^3.87", // 3.87.10
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-time-bundle": "^1.8", // 1.9.0
        "league/flysystem-aws-s3-v3": "^1.0", // 1.0.22
        "league/flysystem-cached-adapter": "^1.0", // 1.0.9
        "liip/imagine-bundle": "^2.1", // 2.1.0
        "nexylan/slack-bundle": "^2.0,<2.2.0", // v2.1.0
        "oneup/flysystem-bundle": "^3.0", // 3.0.3
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.2.4
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.2.3
        "symfony/console": "^4.0", // v4.2.3
        "symfony/flex": "^1.9", // v1.17.6
        "symfony/form": "^4.0", // v4.2.3
        "symfony/framework-bundle": "^4.0", // v4.2.3
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.2.3
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "^4.0", // v4.2.3
        "symfony/validator": "^4.0", // v4.2.3
        "symfony/web-server-bundle": "^4.0", // v4.2.3
        "symfony/yaml": "^4.0", // v4.2.3
        "twig/extensions": "^1.5" // v1.5.4
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.1.0
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/debug-bundle": "^3.3|^4.0", // v4.2.3
        "symfony/dotenv": "^4.0", // v4.2.3
        "symfony/maker-bundle": "^1.0", // v1.11.3
        "symfony/monolog-bundle": "^3.0", // v3.3.1
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.3
        "symfony/profiler-pack": "^1.0", // v1.0.4
        "symfony/var-dumper": "^3.3|^4.0" // v4.2.3
    }
}