The bundle is configured under the root key nowo_doctrine_encrypt. The only supported structure is default_config plus configs (a map of config name ⇒ options). There is no root-level encryptor_class or secret_directory_path; use a single entry under configs (e.g. default) for one encryptor. When #[Encrypted] has no alias (or uses "default"), the encryptor for default_config is used.
| Option | Type | Default | Description |
|---|---|---|---|
default_config |
string |
default |
Which config to use when the attribute has no alias or uses "default". |
batch_size |
int |
5 |
Default batch size for doctrine:decrypt:database and doctrine:encrypt:database (raw SQL). Overridable per run via the batchSize argument. Minimum: 1. |
configs |
array |
[] (normalized to one default config) |
Map of alias => options. Each alias has encryptor_class and either secret_directory_path or secret_key_env_var. Optional: secret_key_filename. |
Per-config options (under each entry in configs):
| Option | Type | Default | Description |
|---|---|---|---|
encryptor_class |
string |
Halite |
Halite, Defuse, MysqlAes, or a custom class. |
secret_directory_path |
string |
%kernel.project_dir% |
Directory for the key file. Required unless secret_key_env_var is set. Cannot be set together with secret_key_env_var. |
secret_key_filename |
string |
(pattern) | Optional custom key filename (e.g. .my_app.key). Only used when secret_directory_path is set; default pattern is .{encryptor_class}.{alias}.key. |
secret_key_env_var |
string |
null |
Use %env(APP_ENCRYPT_KEY)%. Symfony resolves it at config load and the bundle receives the key value. When set, must not set secret_directory_path or secret_key_filename. |
If configs is empty, the bundle behaves as if you had defined a single config named default with Halite and %kernel.project_dir%.
Omit the config file or define only the default config:
# config/packages/nowo_doctrine_encrypt.yaml
nowo_doctrine_encrypt:
default_config: default
configs:
default:
encryptor_class: Halite # or Defuse
secret_directory_path: '%kernel.project_dir%'Then use #[Encrypted] or #[Encrypted('default')] on properties; they will use this encryptor.
# config/packages/nowo_doctrine_encrypt.yaml
nowo_doctrine_encrypt:
default_config: personal_data
configs:
personal_data:
encryptor_class: Halite
secret_directory_path: '%kernel.project_dir%'
financial_data:
encryptor_class: Defuse
secret_directory_path: '%kernel.project_dir%/var/secrets'- Properties with
#[Encrypted]or#[Encrypted('default')]use the encryptor for personal_data (default_config). - Properties with
#[Encrypted('personal_data')]or#[Encrypted('financial_data')]use the corresponding config.
Each config has its own key file: .{encryptor_class}.{alias}.key (e.g. .Halite.personal_data.key, .Defuse.financial_data.key). Add them to .gitignore. See Usage.
-
Halite
Uses paragonie/halite. Requiresext-sodium(or works withparagonie/sodium_compat). Included as a dependency of the bundle. -
Defuse
Uses defuse/php-encryption. You must require it yourself:composer require defuse/php-encryption ^2.1
-
MysqlAes
Compatible with MySQLAES_ENCRYPT()/AES_DECRYPT()(AES-128-ECB, defaultblock_encryption_mode). The passphrase is a plain string (file or env). Use a BLOB column when encrypting in SQL. See MYSQL_AES.md (INSERT examples, repository pattern, demo/mysql-aes-note) and the symfony8 demo routes under/mysql-aes-note. Performance: PHP OpenSSL on every ORM read/write; SQLAES_ENCRYPTonly avoids PHP on insert/update for columns you manage in raw SQL. Searching secrets viaLIKEon decrypted values in SQL is among the most expensive patterns — see PERFORMANCE.md.
| Encryptor | Persist/load (Doctrine) | Typical use |
|---|---|---|
| Halite | Fastest in PHP (especially with ext-sodium) |
Default; best security/performance balance |
| Defuse | Moderate | When Defuse is required |
| MysqlAes | Moderate; weaker algorithm | MySQL legacy interop only |
Searching or filtering encrypted fields is not index-friendly on plaintext. Compare all options (including AES_DECRYPT(...) LIKE, PHP filters, and LIKE on ciphertext) in PERFORMANCE.md.
For each config you either use a key file or a env var:
- Key file: Set
secret_directory_path(and optionallysecret_key_filename). The key file path is{secret_directory_path}/{secret_key_filename}or, ifsecret_key_filenameis omitted,{secret_directory_path}/.{encryptor_class}.{alias}.key(e.g..Halite.default.key,.Defuse.financial_data.key). - Env var: Set
secret_key_env_varto%env(APP_ENCRYPT_KEY)%. Symfony resolves it when loading config and the bundle receives the key value. Do not setsecret_directory_pathorsecret_key_filename. The value must be the same format as the key file content (for Halite: hex-encoded key; for Defuse or MysqlAes: the password/passphrase string). Rundoctrine:encrypt:generate-secret-keyfor configs without path to get the key value, then set it in your.envor environment.
Key file per config: .{encryptor_class}.{alias}.key (or your secret_key_filename) inside that config’s secret_directory_path.
Important: Add key files to .gitignore so they are never committed:
.Halite.key
.Defuse.key
.Halite.*.key
.Defuse.*.keyIf no key file exists, the bundle can generate one (e.g. via the doctrine:encrypt:generate-secret-key command, if available). See Commands.
Symfony loads configuration from:
config/packages/nowo_doctrine_encrypt.yaml(all environments)config/packages/{env}/nowo_doctrine_encrypt.yaml(per environment)
If no config file exists, the bundle uses one default config (Halite, %kernel.project_dir%).