Skip to content

Instantly share code, notes, and snippets.

@dbu
Last active March 4, 2024 15:13
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dbu/51f8df1732f8be44870e491b8d55acd1 to your computer and use it in GitHub Desktop.
Save dbu/51f8df1732f8be44870e491b8d55acd1 to your computer and use it in GitHub Desktop.
Conditionally tag a service in Symfony

My use case was a cache warmer that should only be run on the servers but not in other places. The cache warmer connects to a server to pre-fetch data. The warmer is configured with environment variables / DotEnv variables.

This might come in handy if you need your own conditional services.

  1. Prevent autoconfigure for this service
  2. Have a compiler pass that checks if the environment variable is defined, tag service if it exists

To know if a variable exists, let the ContainerBuilder resolve the env placeholders with format as true:

$container->resolveEnvPlaceholders('%env(API_DOMAIN)%', true);

Note that this evaluates the environment variable in the context where the container is built. If you build the container in a ci environment and then push to services, this would not see environment variables available only on the server. For that scenario, you would need to run a separate command on your servers when initializing the application.

<?php
// src/DependencyInjection/CacheWarmerCompilerPass.php
namespace App\DependencyInjection;
use App\Cache\MyCacheWarmer;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
/**
* Decide whether to warm the cache, depending on whether the api config parameter exists.
*
* (Not available on the CI server).
*/
class CacheWarmerCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
try {
$container->resolveEnvPlaceholders('%env(API_DOMAIN)%', true);
} catch(EnvNotFoundException $e) {
// do not tag service
return;
}
$warmerDefinition = $container->getDefinition(MyCacheWarmer::class);
$warmerDefinition->addTag('kernel.cache_warmer');
}
}
# app/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
# Implements Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface
App\Cache\MyCacheWarmer:
arguments:
# API_DOMAIN may or may not exist
$domain: '%env(API_DOMAIN)'
$cache: '@api_cache'
# Disable autoconfigure for this service, otherwise it will always be loaded
autoconfigure: false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment