Процессоры переменных окружения

Дата обновления перевода 2024-07-16

Процессоры переменных окружения

Использование переменных окружения для конфигурации приложений Symfony - это распространённая практика для того, чтобы сделать ваше приложение дейтвительно динамическим.

Главная проблема переменных окружения в том, что их значения могут быть только строками, а вашему приложению могут быть нужны другие типы данных (целые числа, булевы и т.л.). Symfony решает эту проблему с помощью "процессоров переменных окружения", которые преобразуют изначальное содержание заданных переменных окружения. Следующий пример использует процессор целого числа, чтобы преобразовать значение переменной окружения HTTP_PORT в целое число:

1
2
3
4
# config/packages/framework.yaml
framework:
    router:
        http_port: '%env(int:HTTP_PORT)%'

Встроенные процессоры переменных окружения

Symfony предоставляет следующие процессоры переменных окружения:

env(string:FOO)

Преобразует FOO в строку:

1
2
3
4
5
# config/packages/framework.yaml
parameters:
    env(SECRET): 'some_secret'
framework:
    secret: '%env(string:SECRET)%'
env(bool:FOO)

Преобразует FOO в булево значение (значения true - 'true', 'on', 'yes' и все числа, кроме 0 и 0.0; всё другое - false):

1
2
3
4
5
# config/packages/framework.yaml
parameters:
    env(HTTP_METHOD_OVERRIDE): 'true'
framework:
    http_method_override: '%env(bool:HTTP_METHOD_OVERRIDE)%'
env(not:FOO)

Преобразует FOO в булево значение (как и env(bool:...)), но возвращает инвертированное значение (ложные значения возвращаются как true, правильные значения возвращаются какэ false):

1
2
3
# config/services.yaml
parameters:
    safe_for_production: '%env(not:APP_DEBUG)%'
env(int:FOO)
Преобразует FOO в целое число.
env(float:FOO)
Преобразует FOO в плавающее число.
env(const:FOO)

Находит константное значение, именованное в FOO:

1
2
3
4
5
6
# config/packages/security.yaml
parameters:
    env(HEALTH_CHECK_METHOD): 'Symfony\Component\HttpFoundation\Request::METHOD_HEAD'
security:
    access_control:
        - { path: '^/health-check$', methods: '%env(const:HEALTH_CHECK_METHOD)%' }
env(base64:FOO)
Расшифровывает содержание FOO, который является строкой, зашифрованной в base64.
env(json:FOO)

Расшифровывает содержание FOO, который является строкой, зашифрованной в JSON. Возвращает массив или null:

1
2
3
4
# config/packages/framework.yaml
parameters:
    env(ALLOWED_LANGUAGES): '["en","de","es"]'
    app_allowed_languages: '%env(json:ALLOWED_LANGUAGES)%'
env(resolve:FOO)

Если содержание FOO имеет параметры контейнера (с синтаксисом %parameter_name%), заменяет параметры их значениями:

1
2
3
4
5
6
# config/packages/sentry.yaml
parameters:
    sentry_host: '10.0.0.1'
    env(SENTRY_DSN): 'http://%sentry_host%/project'
sentry:
    dsn: '%env(resolve:SENTRY_DSN)%'
env(csv:FOO)

Расшифровывает содержание FOO, который является строкой, зашифрованной в CSV:

1
2
3
4
# config/packages/framework.yaml
parameters:
    env(ALLOWED_LANGUAGES): "en,de,es"
    app_allowed_languages: '%env(csv:ALLOWED_LANGUAGES)%'
env(shuffle:FOO)

Рандомно перемешивает значения переменной окружения FOO, которая должна быть массивом.

1
2
3
4
5
6
7
# config/packages/framework.yaml
parameters:
    env(REDIS_NODES): "127.0.0.1:6380,127.0.0.1:6381"
services:
    RedisCluster:
        class: RedisCluster
        arguments: [null, "%env(shuffle:csv:REDIS_NODES)%"]
env(file:FOO)

Возвращает содержание файла, чей путь является значением переменной окружения FOO:

1
2
3
4
5
# config/packages/framework.yaml
parameters:
    env(AUTH_FILE): '%kernel.project_dir%/config/auth.json'
google:
    auth: '%env(file:AUTH_FILE)%'
env(require:FOO)

require() PHP-файл, чей путь является значением переменной окружения FOO и возвращает значение, возвращённое из нее.

1
2
3
4
5
# config/packages/framework.yaml
parameters:
    env(PHP_FILE): '%kernel.project_dir%/config/.runtime-evaluated.php'
app:
    auth: '%env(require:PHP_FILE)%'
env(trim:FOO)

Усекает содержание переменной окружения FOO, удаляя пробелы в начале и конце строки. Это особенно полезно в сочетании с процессором file, так как он удалит пустые строчки в конце файла.

1
2
3
4
5
# config/packages/framework.yaml
parameters:
    env(AUTH_FILE): '%kernel.project_dir%/config/auth.json'
google:
    auth: '%env(trim:file:AUTH_FILE)%'
env(key:FOO:BAR)

Извлекает значение, ассоциированное с ключом FOO из массива, чьё содержание хранится в переменной окружения BAR:

1
2
3
4
5
# config/services.yaml
parameters:
    env(SECRETS_FILE): '/opt/application/.secrets.json'
    database_password: '%env(key:database_password:json:file:SECRETS_FILE)%'
    # if SECRETS_FILE contents are: {"database_password": "secret"} it returns "secret"
env(default:fallback_param:BAR)

Извлекает значение параметра fallback_param, если переменная окружения BAR не доступна:

1
2
3
4
5
# config/services.yaml
parameters:
    # если PRIVATE_KEY не является валидным путём файла, возвращается содержание raw_key
    private_key: '%env(default:raw_key:file:PRIVATE_KEY)%'
    raw_key: '%env(PRIVATE_KEY)%'

Если опускается резервный параметр (например, env(default::API_KEY)), то возвращённое значение - null.

env(url:FOO)

Анализирует абсолютный URL и возвращает его компоненты как ассоциативный массив.

1
2
# .env
MONGODB_URL="mongodb://db_user:db_password@127.0.0.1:27017/db_name"
1
2
3
4
5
6
7
8
9
10
11
# config/packages/mongodb.yaml
mongo_db_bundle:
    clients:
        default:
            hosts:
                - { host: '%env(string:key:host:url:MONGODB_URL)%', port: '%env(int:key:port:url:MONGODB_URL)%' }
            username: '%env(string:key:user:url:MONGODB_URL)%'
            password: '%env(string:key:pass:url:MONGODB_URL)%'
    connections:
        default:
            database_name: '%env(key:path:url:MONGODB_URL)%'

Caution

Для того, чтобы облегчить извлечение источника из URL, лидирующий / усекается из компонента path.

env(query_string:FOO)

Анализирует часть строки запроса заданного URL и возвращает его компоненты как ассоциативный массив.

1
2
# .env
MONGODB_URL="mongodb://db_user:db_password@127.0.0.1:27017/db_name?timeout=3000"
1
2
3
4
5
6
# config/packages/mongodb.yaml
mongo_db_bundle:
    clients:
        default:
            # ...
            connectTimeoutMS: '%env(int:key:timeout:query_string:MONGODB_URL)%'
env(enum:FooEnum:BAR)

Пробует преобразовать переменную окружения в реальное значение \BackedEnum. Этот процессор берёт полностью квалифицированное имя \BackedEnum в качестве аргумента.

1
2
3
4
5
6
# App\Enum\Environment
enum Environment: string
{
    case Development = 'dev';
    case Production = 'prod';
}
1
2
3
# config/services.yaml
parameters:
    typed_env: '%env(enum:App\Enum\Environment:APP_ENV)%'
env(defined:NO_FOO)

Оценивается как true, если переменная окружения существует и её значение - не '' (пустая строка) или null; в обратном случае, возвращает false.

1
2
3
# config/services.yaml
parameters:
    typed_env: '%env(defined:FOO)%'
env(urlencode:FOO)

ифрует содержание переменной окружения FOO с помощью PHP-функции urlencode2c0ca11862ef0d5391ea7bb29b746f57feb5e68aFOO` не совместимо с синтаксисом DSN.

1
2
3
4
# config/packages/framework.yaml
parameters:
    env(DATABASE_URL): 'mysql://db_user:foo@b$r@127.0.0.1:3306/db_name'
    encoded_database_url: '%env(urlencode:DATABASE_URL)%'

7.1

Процессор переменной окружения env(urlencode:...) был представлен в Symfony 7.1.

Также возможно объединить любое количество процессоров:

1
2
3
4
5
6
7
8
9
# config/packages/framework.yaml
parameters:
    env(AUTH_FILE): "%kernel.project_dir%/config/auth.json"
google:
    # 1. получает значение переменной окружения AUTH_FILE
    # 2. заменяет значения любого параметра конфигурации, чтобы получить путь конфигурации
    # 3. получает содержание файла, хранящегося по этому пути
    # 4. JSON-расшифровывает содержание файла и возвращает его
    auth: '%env(json:file:resolve:AUTH_FILE)%'

Пользовательские процессоры переменных окружения

Также возможно добавлять ваши собственные процессоры для переменных окружения. Для начала, создайте класс, реализующий EnvVarProcessorInterface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;

class LowercasingEnvVarProcessor implements EnvVarProcessorInterface
{
    public function getEnv(string $prefix, string $name, \Closure $getEnv): string
    {
        $env = $getEnv($name);

        return strtolower($env);
    }

    public static function getProvidedTypes(): array
    {
        return [
            'lowercase' => 'string',
        ];
    }
}

Чтобы включить новый процессор в приложении, зарегистрируйте его как сервис и добавьте тег container.env_var_processor. Если вы используете конфигурацию services.yaml по умолчанию , это уже сделано за вас, благодаря автоконфигурации .