Installation:
composer require ashleydawson/glide-bundle
Register the bundle in config/bundles.php (Symfony 4+) or app/AppKernel.php (Symfony 2/3):
AshleyDawson\GlideBundle\AshleyDawsonGlideBundle::class => ['all' => true],
Configure Filesystems:
Define source (original images) and cache (processed images) filesystems in config/packages/ashley_dawson_glide.yaml:
ashley_dawson_glide:
source_filesystem: 'oneup_flysystem.local_filesystem.source'
cache_filesystem: 'oneup_flysystem.local_filesystem.cache'
Use OneupFlysystemBundle for filesystem management.
First Use Case: Create a controller to serve processed images:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class ImageController extends AbstractController
{
#[Route('/images/{filename}', name: 'glide_image')]
public function show(Request $request, string $filename): Response
{
return $this->get('ashleydawson.glide.server_factory')
->create($this->get('oneup_flysystem.local_filesystem.source'))
->getImageResponse($filename, $request->query->all());
}
}
Access images via URL: /images/photo.jpg?w=300&h=200.
Request Handling:
Use query parameters to define transformations (e.g., ?w=300&h=200&fit=crop).
GlideBundle automatically parses these into manipulators.
Filesystem Integration:
local, s3).cache dir or local filesystem).ashley_dawson_glide:
source_filesystem: 'aws_s3.source'
cache_filesystem: 'aws_s3.cache'
Controller Abstraction:
Reuse the GlideServerFactory service to avoid repetition:
$glideServer = $this->get('ashleydawson.glide.server_factory')
->create($sourceFs, $cacheFs);
return $glideServer->getImageResponse($filename, $queryParams);
Dynamic Routes: Use Symfony’s routing to handle dynamic filenames:
# config/routes.yaml
glide_images:
path: /images/{filename}
controller: App\Controller\ImageController::show
defaults:
filename: null
Custom Manipulators: Extend functionality by creating custom manipulators (e.g., watermarks, filters):
// src/Glide/Manipulator/WatermarkManipulator.php
class WatermarkManipulator implements ManipulatorInterface
{
public function run(Request $request, Image $image)
{
if ($request->query->has('watermark')) {
$watermark = $this->getWatermarkImage();
$image->insert($watermark, 'bottom-right', 10, 10);
}
return $image;
}
}
Register in services.yaml:
services:
App\Glide\Manipulator\WatermarkManipulator:
tags:
- { name: ashleydawson.glide.manipulators }
Middleware for Security: Validate filenames and query parameters to prevent path traversal:
#[Route('/images/{filename}', name: 'glide_image')]
public function show(Request $request, string $filename): Response
{
if (!preg_match('/^[a-z0-9\-_]+$/i', $filename)) {
throw $this->createAccessDeniedException();
}
// Proceed with Glide processing
}
Caching Strategies:
local or memory) for cache.HttpCache or Varnish for edge caching:
framework:
http_cache:
cache_control:
rules:
- path: ^/images/
headers:
Cache-Control: 'public, max-age=31536000'
Batch Processing: Pre-generate thumbnails for performance:
$glideServer = $this->get('ashleydawson.glide.server_factory')
->create($sourceFs, $cacheFs);
$glideServer->getImageResponse('photo.jpg', ['w' => 800, 'h' => 600]); // Pre-cache
Filesystem Permissions:
local filesystems, set permissions:
chmod -R 775 var/cache/glide
Query Parameter Conflicts:
?w, ?h, ?fit, etc. Avoid naming your routes or query params similarly to prevent conflicts.?thumbnail=true instead of ?w=100 if you want to trigger a custom manipulator.Deprecated Symfony Versions:
app/cache vs. var/cache).league/glide-symfony directly.Memory Limits:
memory_limit. Increase it temporarily:
ini_set('memory_limit', '512M');
?fit=crop or ?resize to reduce memory usage.Cache Invalidation:
php bin/console cache:clear
Check Filesystem Contents: Verify files exist in the source and cache directories:
ls var/cache/glide/
ls path/to/source/
Enable Glide Debugging: Temporarily disable caching to test live processing:
ashley_dawson_glide:
cache_filesystem: null # Disables caching
Log Manipulator Execution: Add debug logs to custom manipulators:
public function run(Request $request, Image $image)
{
$this->container->get('logger')->debug('Running custom manipulator', [
'query' => $request->query->all(),
]);
// ...
}
Validate Query Parameters: Use Glide’s built-in validation or add your own:
$query = $request->query->all();
if (!isset($query['w']) || !is_numeric($query['w'])) {
throw new \InvalidArgumentException('Width must be a number');
}
Custom Server Factories:
Extend the GlideServerFactory to add default manipulators or configurations:
class CustomGlideServerFactory extends GlideServerFactory
{
public function create(Filesystem $sourceFs, Filesystem $cacheFs = null)
{
$server = parent::create($sourceFs, $cacheFs);
$server->addManipulator(new MyCustomManipulator());
return $server;
}
}
Register in services.yaml:
services:
ashleydawson.glide.server_factory:
class: App\Glide\CustomGlideServerFactory
Event Listeners:
Hook into Glide events (e.g., glide.image.processed) to log or analyze processed images:
use League\Glide\Events\ImageProcessed;
class GlideListener
{
public function onImageProcessed(ImageProcessed $event)
{
$this->logger->info('Image processed', [
'path' => $event->getPath(),
'query' => $event->getQuery(),
]);
}
}
Register as a service with the kernel.event_listener tag.
Dynamic Filesystem Configuration: Use environment variables or config files to switch filesystems dynamically
How can I help you explore Laravel packages today?