ekino/tiny-png-sonata-media-bundle
Install the Bundle:
composer require ekino/tiny-png-sonata-media-bundle
Add the bundle to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
Ekino\TinyPngSonataMediaBundle\EkinoTinyPngSonataMediaBundle::class => ['all' => true],
Configure TinyPNG API Key:
Add your TinyPNG API key to config/packages/ekino_tiny_png_sonata_media.yaml:
ekino_tiny_png_sonata_media:
api_key: '%env(TINYPNG_API_KEY)%'
Ensure the key is in your .env file:
TINYPNG_API_KEY=your_api_key_here
Enable Optimization for Media Providers:
Extend your SonataMedia provider configuration to include the EkinoTinyPngSonataMediaBundle\Provider\TinyPngProvider:
sonata_media:
providers:
sonata.media.provider.image:
format: sonata.media.format.image
filesystem: sonata.media.filesystem.local
cdn: sonata.media.cdn.generic
extensions: ['jpg', 'jpeg', 'png', 'gif']
provider: sonata.media.provider.image
context: sonata.media.context.image
tiny_png: true # Enable TinyPNG optimization
First Use Case: Upload an image via SonataMedia admin. The bundle will automatically optimize the image on save if TinyPNG is enabled for the provider.
Media Upload & Optimization:
tiny_png: true flag in your media provider configuration to enable optimization for specific providers.Asynchronous Processing:
config/packages/messenger.yaml includes:
framework:
messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
ekino_tiny_png_sonata_media:
async: true
Customizing Optimization:
Ekino\TinyPngSonataMediaBundle\Client\TinyPngClient class and injecting it as a service:
services:
ekino.tiny_png.client:
class: App\Custom\TinyPngClient
arguments:
- '%env(TINYPNG_API_KEY)%'
Handling Notifications:
ekino_tiny_png_sonata_media:
notifications:
enabled: true
recipient: '%env(ADMIN_EMAIL)%'
Batch Optimization:
Re-optimize existing media by triggering the optimization process manually. Use the Ekino\TinyPngSonataMediaBundle\Command\OptimizeMediaCommand:
php bin/console ekino:tiny-png:optimize-media
Conditional Optimization: Optimize only specific media types or sizes by extending the provider logic or using event listeners.
API Key Management:
.env). Hardcoding keys in configuration files is unsafe.Async Processing Quirks:
FailedMessageHandler.Provider Configuration:
tiny_png: true flag must be set per provider. Misconfiguration may lead to optimization not being applied to all intended media.extensions include the file types you want to optimize (e.g., ['jpg', 'png']).File Size Limits:
// In a custom client or event subscriber
try {
$client->optimize($filePath);
} catch (\Ekino\TinyPngSonataMediaBundle\Exception\TinyPngException $e) {
$this->logger->error('TinyPNG optimization failed: ' . $e->getMessage());
// Fallback to local optimization or skip
}
Enable Debug Logging:
Add the following to config/packages/dev/ekino_tiny_png_sonata_media.yaml:
ekino_tiny_png_sonata_media:
debug: true
This will log API responses and errors to var/log/dev.log.
Check Event Listeners:
The bundle dispatches events (ekino.tiny_png.media.pre_optimize, ekino.tiny_png.media.post_optimize). Subscribe to these to debug the optimization pipeline:
// src/EventListener/TinyPngListener.php
public static function getSubscribedEvents()
{
return [
'ekino.tiny_png.media.pre_optimize' => 'onPreOptimize',
'ekino.tiny_png.media.post_optimize' => 'onPostOptimize',
];
}
Manual Testing: Test the TinyPNG client directly to isolate issues:
$client = $this->container->get('ekino.tiny_png.client');
$result = $client->optimize('/path/to/image.jpg');
Custom Optimization Logic:
Extend the Ekino\TinyPngSonataMediaBundle\Provider\TinyPngProvider to add pre/post-processing steps:
// src/Provider/CustomTinyPngProvider.php
class CustomTinyPngProvider extends TinyPngProvider
{
public function preOptimize(MediaInterface $media)
{
// Custom logic before TinyPNG optimization
}
public function postOptimize(MediaInterface $media, $optimizedPath)
{
// Custom logic after TinyPng optimization
}
}
Register the service in config/services.yaml:
services:
App\Provider\CustomTinyPngProvider:
tags: ['sonata.media.provider']
Add Custom Metadata: Store optimization metadata (e.g., original size, optimized size) in the media entity:
// In a post-optimize event subscriber
$media->setMetadata('tiny_png_optimized', true);
$media->setMetadata('original_size', filesize($originalPath));
$media->setMetadata('optimized_size', filesize($optimizedPath));
$media->save();
Fallback to Local Optimization:
If TinyPNG fails, fall back to local optimization (e.g., using imagick or gd):
// In a custom provider or event subscriber
if (!$tinyPngSuccess) {
$this->fallbackOptimize($media);
}
How can I help you explore Laravel packages today?