Having problems setting up AWS S3/Cloudfront with Symfony and LiipImagineBundle - symfony

I'm trying to set up AWS S3/Cloudfront to work with liipimaginebundle in Symfony, but I really have no idea what I'm doing.
So far I have tried the following documented here http://symfony.com/doc/current/bundles/LiipImagineBundle/cache-resolver/aws_s3.html:
Installed aws-sdk-php:
"require": {
"aws/aws-sdk-php": "^3.28",
}
Set up my parameters (with the correct values not this dummy data):
amazon.s3.key: "your-aws-key"
amazon.s3.secret: "your-aws-secret"
amazon.s3.bucket: "your-bucket.example.com"
amazon.s3.region: "your-bucket-region"
Set up a resolver (although I'm not sure what that even means).
"%amazon.s3.cache_bucket%" is in the documentation but the parameter doesn't exist so I used "%amazon.s3.bucket%" instead:
liip_imagine:
cache: profile_photos
resolvers:
profile_photos:
aws_s3:
client_config:
credentials:
key: "%amazon.s3.key%"
secret: "%amazon.s3.secret%"
region: "%amazon.s3.region%"
bucket: "%amazon.s3.bucket%"
get_options:
Scheme: https
put_options:
CacheControl: "max-age=86400"
Added these lines to create the services:
services:
acme.amazon_s3:
class: Aws\S3\S3Client
factory: Aws\S3\S3Client
arguments:
-
credentials: { key: "%amazon.s3.key%", secret: "%amazon.s3.secret%" }
region: "%amazon.s3.region%"
acme.imagine.cache.resolver.amazon_s3:
class: Liip\ImagineBundle\Imagine\Cache\Resolver\AwsS3Resolver
arguments:
- "#acme.amazon_s3"
- "%amazon.s3.bucket%"
tags:
- { name: "liip_imagine.cache.resolver", resolver: "amazon_s3" }
I'm currently getting this error when I run php bin/console server:run:
PHP Fatal error: Uncaught Symfony\Component\Debug\Exception\UndefinedFunctionException: Attempted to call function "S3Client" from namespace "Aws\S3". in /var/www/swing-polls/var/cache/dev/appDevDebugProjectContainer.php:360
I've tried half a dozen other configs/tutorials to no avail. If someone can point me in the right direction I'd be incredibly grateful.
Using the code provided at Simple S3 Symfony Service with a few tweaks, I've been able to get my images to upload to my s3 bucket, but I just don't know how to get liipimaginebundle work with them.

In vendor/liip/imagine-bundle/DependencyInjection/Compiler/ResolversCompilerPass.php you can see the CompilerPass is getting the value from "resolver" attribute of the tag and is using it to create a Reference object. This means the resolver should contain the id of a service.
Try replacing
tags:
- { name: "liip_imagine.cache.resolver", resolver: "amazon_s3" }
with
tags:
- { name: "liip_imagine.cache.resolver", resolver: "acme.amazon_s3" }

Related

Using RedisTagAwareAdapter in Symfony 4.4

I have an issue getting Symfony to play nicely with a tag-aware adapter for redis
Unfortunately for me, Symfony 5.2 includes this feature, but as we're not switching to a non-lts version that's kind of out of the question. I have tried checking out the configuration, but it does not quite work for me.
Here's my current setup:
# cache.yaml
framework:
cache:
prefix_seed: !php/const App\Kernel::APP_VERSION
app: cache.adapter.redis_tag_aware
redis.cache_app:
class: Redis
factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection']
arguments:
- '%env(REDIS_DNS)%'
cache.adapter.redis_tag_aware:
class: Symfony\Component\Cache\Adapter\RedisTagAwareAdapter
arguments:
$redisClient: '#redis.cache_app'
$marshaller: '#?cache.default_marshaller'
calls:
- ['setLogger', ['#?logger']]
tags:
- { name: cache.pool, provider: cache.default_redis_provider, clearer: cache.default_clearer, reset: reset }
- { name: monolog.logger, channel: cache }
But it screams about argument 0 not existing via some CompilerPass.
Is it not possible to use the App cache as a tagged cache? I suppose I could create a separate pool and maybe use that, but it seems like a weird choice.
Okay so obviously this is a config issue.
The following will work
# services.yaml
redis.cache_app:
class: Redis
factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection']
arguments:
- '%env(REDIS_DNS)%'
cache.app.redis_tag_aware:
class: Symfony\Component\Cache\Adapter\RedisTagAwareAdapter
arguments:
- '#redis.cache_app'
- ''
- 0
- '#?cache.default_marshaller'
calls:
- ['setLogger', ['#?logger']]
tags:
- { name: cache.pool, provider: redis.cache_app, clearer: cache.default_clearer, reset: reset }
- { name: monolog.logger, channel: cache }
# cache.yaml
framework:
cache:
prefix_seed: !php/const App\Kernel::APP_VERSION
app: cache.app.redis_tag_aware

How to override namespace argument in RedisAdapter for a Symfony4 app to cache

I want to use custom namespace in our RedisAdapter to cache in our Symfony4 app. However, when i want to set arguments like this in our services.yaml;
cache.adapter.redis:
class: Symfony\Component\Cache\Adapter\RedisAdapter
arguments:
- '#Redis'
- 'app'
I see this error message:
Symfony\Component\Cache\Traits\RedisTrait::init() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, string given.
By the way, our cache config(config/packages/cache.yaml) is simple like below. So, how can I set namespace directly from any config?
cache:
app: cache.adapter.redis
default_redis_provider: 'redis://%env(REDIS_HOST)%:%env(REDIS_PORT)%'
I solved it with this config:
app.cache.adapter.redis:
parent: 'cache.adapter.redis'
public: true
autowire: true
autoconfigure: false
tags:
- {name: 'cache.pool', namespace: 'app'}
If you need the namespace to be interoperable with a third-party app,
you can take control over auto-generation by setting the namespace attribute of the cache.pool service tag.
For example, you can override the service definition of the adapter:
# config/services.yaml
services:
app.cache.adapter.redis:
parent: 'cache.adapter.redis'
tags:
- { name: 'cache.pool', namespace: 'my_custom_namespace' }
more details here: https://github.com/symfony/symfony-docs/pull/12527

How can one use a defined channel, in monolog handler from a tagged service?

I have the following monolog handler definitions:
# config_prod.yml
app_generic:
type: rotating_file
max_files: 15
path: "%param.app_logging_config.log_generic_file%"
level: info
channels: [app]
app_api:
max_files: 15
path: "%param.app_logging_config.log_api_file%"
level: info
channels: [app]
level: info
app_response:
max_files: 15
path: "%param.app_logging_config.log_response_file%"
channels: [app]
level: info
And in service.yml, my intention is to inject monolog (#logger) with an array of the above defined handlers.
#service.yml
app.app_logger:
class: AppBundle\Classes\AppLogger
arguments: ['#logger': ['#app_generic', '#app_api', '#app_response']]
calls:
- [init, ['%app_logging_config%']
tags:
- { name: monolog.logger, channel: app }
How does one pass arguments to an injected argument?
Update:
Re-reading the description, I was going for this approach, by just tagging on the service definition:
app.logger:
arguments: ['#logger']
tags:
- { name: monolog.logger, channel: app }
channels: ['app']
Or even ( if I understood correctly), adding a channels: ['app'] key and just having this in service argument:
app.logger:
arguments: ['#monolog.logger.app']
I have not been able to use ( or see via dump ) the handlers defined in config_prod.yml. I have placed these at top because of other "fingers_crossed" handlers I thought may interfere.
I woud like to know, why neither of above (documented) approaches seem to work?
Handlers in
monolog:
handlers:
handler1: ...
handler2: ...
are automatically injected in #logger service.
It looks like you need new custom logger. Please read about The DependencyInjection Component
Create dependencies
services:
app_generic:
....
app_api:
....
app_response:
....
Create custom_logger service
custom_logger:
class: Monolog\Logger
arguments: ["my logger", ["#app_generic", "#app_api", "#app_response"]
Inject you custom logger in you service
app.app_logger:
class: AppBundle\Classes\AppLogger
arguments: ['#custom_logger']
calls:
- [init, ['%app_logging_config%']

Avoid Symfony to override parameters between bundles

I'm using YML parameters inside each bundle to use them as data fixtures as follows:
AppBundle\Resources\config\datafixtures.yml
parameters:
datafixtures:
defaultusers:
0:
name: john
email: john#company1.lol
1:
name: steve
email: steve#company1.lol
GeolocationBundle\Resources\config\datafixtures.yml
parameters:
datafixtures:
cities:
0:
external_service_area: Cantabria
company_area: Santander
1:
external_service_area: Gipuzkoa
company_area: San Sebastian
The problem comes when I import the files in the app config.yml file.
imports:
- { resource: '#AppBundle/Resources/config/datafixtures.yml' }
- { resource: '#GeolocationBundle/Resources/config/datafixtures.yml' }
Instead of merging the trees, it overrides them. Is there a way to make them merge?
Bassically the tree form makes them override each other, so the best way to avoid it is to define each node with a single complete name:
AppBundle\Resources\config\datafixtures.yml
parameters:
datafixtures.defaultusers:
GeolocationBundle\Resources\config\datafixtures.yml
parameters:
datafixtures.cities:

Configuring LiipImagineBundle Symfony to work with Flysystem

I've been trying to configure a CDN (S3) to work with LiipImagineBundle, but keep getting stuck when it is asking for a non-existent service.
What does this mean?
The value of the filesystem_service property must be a service that returns an instance of League\Flysystem\Filesystem.
From here: http://symfony.com/doc/current/bundles/LiipImagineBundle/cache-resolver/flysystem.html
and here: http://symfony.com/doc/current/bundles/LiipImagineBundle/data-loader/flysystem.html
I have tried to create a service that returns an instance of League\Flysystem\Filesystem as follows:
league.flysystem.s3adaptor:
class: League\Flysystem\AwsS3v3\AwsS3Adapter
arguments: ['#acme.s3_client', '%amazon.s3.bucket%', 's3_fs', '#?']
league.flysystem.filesystem:
class: League\Flysystem\Filesystem
arguments: ['#league.flysystem.s3adaptor', '#?']
calls:
- [addPlugin, ['#oneup_flysystem.plugin.list_with']]
I'm not sure if this is along the right lines or not, but I can't get this working.
Any help or advice will be greatly appreciated.
I was on the right lines, I had just misconfigured my LiipImagineBundle slightly.
To return an instance of League\Flysystem\Filesystem you first need to create a service for the adaptor that you want to use, in this case league.flysystem.s3adaptor does this. Then pass that as an argument to league.flysystem.filesystem.
league.flysystem.s3adaptor:
class: League\Flysystem\AwsS3v3\AwsS3Adapter
arguments: ['#acme.s3_client', '%amazon.s3.bucket%']
league.flysystem.filesystem:
class: League\Flysystem\Filesystem
arguments: ['#league.flysystem.s3adaptor']
calls:
- [addPlugin, ['#oneup_flysystem.plugin.list_with']]
LiipImagineBundle config:
liip_imagine:
resolvers:
profile_photos:
flysystem:
filesystem_service: league.flysystem.filesystem
root_url: "https://s3.eu-west-2.amazonaws.com/nameofthebucket/"
cache_prefix: media/cache
visibility: public
loaders:
profile_photos:
flysystem:
filesystem_service: league.flysystem.filesystem
data_loader: profile_photos
cache: profile_photos

Resources