Configuration file reference
Propulsion has two entirely separate configuration surfaces, loaded by different code at different times:
- Build-time properties — the flat
propulsion.*key space controlling howbin/propulsiongenerates code (builders, platform, paths, object-model options). Read byPropulsion\Generator\Config\GeneratorConfig. - Runtime configuration — the datasource/connection array your generated Object Model classes use to actually connect to the database at request time. Read by
Propulsion::init()(Propulsion\Propulsion) into aPropulsion\Config\PropulsionConfiguration.
There’s also a narrower, easy-to-conflate third thing: build-time database connections — the DSN(s) the generator itself connects with, only needed for build-time tasks that talk to a live database (schema:reverse, sql:exec, sql:diff against a live schema). This page covers all three.
This page replaces Propel 1’s propel.ext/YAML configuration file and runtime-conf.xml reference — Propulsion’s actual configuration format is different from both, as detailed below.
Build-time properties
Section titled “Build-time properties”Where and how to specify them
Section titled “Where and how to specify them”Properties come from three layers, merged in order (later layers win):
generator/default.php— the base set Propulsion ships with. A plain PHP filereturning a flat['propulsion.foo' => 'value', ...]array. This is the authoritative list of every property and its default; read it directly if this page and the code ever disagree.- One or more override files, passed with
--config(repeatable — later files win) on the console commands. Two formats are accepted, dispatched by extension:build.php(recommended) — a plain PHP file returning the same flat['propulsion.foo' => ...]shape.build.properties(legacy) — an Ant/Phing-style text file, onekey = valuepair per line,#/;comments. Still fully supported for existing Propel 1 projects; seeGeneratorConfig::parsePropertiesFile().
- Ad-hoc CLI overrides —
--databaseand--target-platformonmodel:buildsetpropulsion.database/propulsion.targetPlatformdirectly, applied after the config files.
bin/propulsion model:build schema.xml --config=build.php --database=pgsqlbin/propulsion model:build schema.xml --config=build.properties --config=build.local.properties${propulsion.some.key} placeholders are resolved against the fully-merged flat array (up to 10 passes, innermost-first), regardless of which format produced them — so propulsion.platform.class => ${propulsion.platform.${propulsion.database}.class} in default.php resolves once propulsion.database is set.
Property list
Section titled “Property list”The following tables list every propulsion.* key from generator/default.php, grouped the same way the file is. Property names below drop the propulsion. prefix and use dots for readability — write them with the full propulsion. prefix in your own build.php/build.properties.
Basic properties
Section titled “Basic properties”| Property | Default | Description |
|---|---|---|
version | 1.6.2-dev | Propulsion’s own version string. |
home | . | Propulsion’s install root, used to resolve templatePath and the XSD/XSL resource paths below. |
database | pgsql | Target database adapter: pgsql, mysql, sqlite, oracle, mssql, sqlsrv. PostgreSQL is the default (Propel 1 defaulted to mysql). |
targetPackage | “ (empty) | Default package for generated classes when a schema doesn’t set its own. |
targetPlatform | “ (empty) | Codegen dialect selector, effectively vestigial. The legacy PHP5 builders were removed from the codebase entirely (archived under archaeology/php5-builders/), so there is no alternate builder set left to select — every builder.*.class key below is unconditionally the modern builder. --target-platform and the platform-suffixed builder.*.<platform>.class override mechanism still work in general, and .php84.class entries are kept as a redundant alias for anyone still passing targetPlatform=php84 explicitly. |
runOnlyOnSchemaChange | false | Skip regeneration when the schema file’s mtime hasn’t changed. |
packageObjectModel | false | Whether to join schemas sharing a database name into a single schema. |
useDateTimeClass | true | Whether temporal getters return DateTime objects. |
dateTimeClass | DateTime | Which DateTime-compatible class to instantiate for temporal columns. |
schema.validate | true | Validate schema.xml against the bundled XSD before building. |
schema.transform | false | Run the schema through the XSL transform file before building. |
schema.autoPackage | false | Copy a table’s schema attribute to its package attribute. |
schema.autoNamespace | false | Copy a table’s schema attribute to its namespace attribute. |
schema.autoPrefix | false | Use a table’s schema attribute as a phpName prefix. |
useLeftJoinsInDoJoinMethods | true | Whether generated doSelectJoin*()-style methods default to LEFT JOIN. |
Database settings
Section titled “Database settings”| Property | Default | Description |
|---|---|---|
database.url | “ (empty) | Single build-time database DSN (fallback path — see Build-time database connections). |
database.buildUrl | ${propulsion.database.url} | DSN used specifically for build tasks. |
database.createUrl | ${propulsion.database.buildUrl} | DSN used when creating the database. |
database.driver | “ (empty) | Overrides the PDO driver segment if it differs from database. |
database.schema | “ (empty) | Default SQL schema/namespace for RDBMS that support it. |
database.encoding | “ (empty) | Character encoding for DDL generation. |
database.manualCreation | false | Skip automatic database creation. |
database.user / database.password | “ (empty) | Fallback build-time credentials, used together with database.url when no buildtime-conf is configured. |
Database-to-XML settings
Section titled “Database-to-XML settings”| Property | Default | Description |
|---|---|---|
samePhpName | false | Whether reverse-engineered columns get a phpName identical to the column name. |
addVendorInfo | false | Whether reverse engineering emits <vendor> elements. |
addValidators | none | Validator rules to emit when reverse-engineering. |
Template variables (object model)
Section titled “Template variables (object model)”| Property | Default | Description |
|---|---|---|
addGenericAccessors | true | Generate getByName()/getByPosition()/toArray(). |
addGenericMutators | true | Generate setByName()/setByPosition()/fromArray(). |
addSaveMethod | true | Generate save(). |
addTimeStamp | false | Add a generation timestamp to the phpDoc header of generated classes. |
addValidateMethod | true | Generate validate()/getValidationFailures(). |
addIncludes | false | Emit require/include statements in generated code instead of relying on autoloading. |
addHooks | true | Generate pre/post lifecycle hook call sites on save()/delete(). |
basePrefix | Base | Prefix for the abstract Base* classes. |
saveException | PropulsionException | Exception class thrown by generated save()/delete() on failure. |
emulateForeignKeyConstraints | false | Emit application-level FK constraint checks instead of relying on the database. |
disableIdentifierQuoting | false | Disable identifier quoting in generated DDL/SQL — can be necessary on PostgreSQL for certain identifier casing. |
defaultTimeStampFormat | Y-m-d H:i:s | Default format string for TIMESTAMP columns’ getByName()-style access. |
defaultTimeFormat | %X | Default format string for TIME columns. |
defaultDateFormat | %x | Default format string for DATE columns. |
namespace.om | OM | Sub-namespace segment for generated OM classes (only used by certain packaging modes). |
namespace.map | Map | Sub-namespace segment for generated *TableMap classes. |
namespace.autoPackage | true | Use a table’s namespace attribute to derive its output subdirectory. |
Directories
Section titled “Directories”| Property | Default | Description |
|---|---|---|
conf.dir | ${propulsion.project.dir} | Directory searched for runtime/buildtime config files. |
schema.dir | ${propulsion.project.dir} | Directory searched for schema.xml files. |
templatePath | ${propulsion.home}/templates | Code-generation template root. |
output.dir | ${propulsion.project.dir}/build | Root output directory (legacy Phing-style layout; the console’s --output-dir option is the modern equivalent for model:build). |
php.dir | ${propulsion.output.dir}/classes | Generated PHP class output directory (legacy path — superseded by --output-dir). |
phpconf.dir | ${propulsion.output.dir}/conf | Generated runtime-config output directory. |
sql.dir | ${propulsion.output.dir}/sql | Generated DDL/SQL output directory. |
migration.dir | ${propulsion.output.dir}/migrations | Generated migration class output directory. |
graph.dir | ${propulsion.output.dir}/graph | graph:build output directory. |
dbd2propel.dir | ${propulsion.project.dir}/dbd | DBDesigner4 import source directory. |
Default file names
Section titled “Default file names”| Property | Default | Description |
|---|---|---|
runtime.conf.file | runtime-conf.xml | Legacy default filename some tooling still probes for — not what Propulsion::init() expects; pass your PHP runtime config file’s path explicitly (see Runtime configuration). |
runtime.phpconf.file | ${propulsion.project}-conf.php | Legacy compiled runtime-config filename pattern. |
runtime.phpconf-classmap.file | classmap-${propulsion.runtime.phpconf.file} | Legacy classmap companion file. |
default.schema.basename | schema | Base filename schemas are matched against (*schema.xml). |
schema.xsd.file | ${propulsion.home}/resources/xsd/database.xsd | Schema-validation XSD path. |
schema.xsl.file | ${propulsion.home}/resources/xsl/database.xsl | Schema-transform XSL path. |
dbd2propel.xsl.file | ${propulsion.home}/resources/xsl/dbd2propel.xsl | DBDesigner4 import XSL path. |
Include/exclude and mapper settings
Section titled “Include/exclude and mapper settings”| Property | Default | Description |
|---|---|---|
schema.sql.includes / schema.sql.excludes | *schema.xml / “ | File matching for the SQL-build task. |
schema.doc.includes / schema.doc.excludes | *schema.xml / “ | File matching for documentation generation. |
schema.create-db.includes / schema.create-db.excludes | *schema.xml / “ | File matching for database creation. |
schema.init-sql.includes / schema.init-sql.excludes | *schema.xml / id-table-schema.xml | File matching for initial-data SQL. |
schema.om.includes / schema.om.excludes | *schema.xml / id-table-schema.xml | File matching for Object Model generation. |
schema.datadtd.includes / schema.datadtd.excludes | *schema.xml / id-table-schema.xml | File matching for data-DTD generation. |
dbd2propel.includes | *.xml | File matching for DBDesigner4 import. |
datasql.mapper.from / datasql.mapper.to | *.xml / *.sql | Data-XML-to-SQL filename mapping. |
datadump.mapper.from / datadump.mapper.to | *schema.xml / *data.xml | Schema-to-data-dump filename mapping. |
datadtd.mapper.from / datadtd.mapper.to | *.xml / *.dtd | Data-to-DTD filename mapping. |
sql.mapper.from / sql.mapper.to | *.xml / *.sql | Schema-to-SQL filename mapping. |
Migration settings
Section titled “Migration settings”| Property | Default | Description |
|---|---|---|
migration.editor | “ (empty) | Editor command invoked when opening a generated migration for review. |
migration.table | propulsion_migration | Append-only ledger table Propulsion uses to record migration run attempts — see Migrations: How it works. |
migration.caseInsensitive | true | Whether migration filename comparison ignores case. |
Builder settings
Section titled “Builder settings”Every builder.*.class key names the concrete class for a stage of code generation. All of them point at the modern PHP 8.4+ builders unconditionally — the PHP5-era builder classes (PHP5PeerBuilder, PHP5ObjectBuilder, PHP5TableMapBuilder, PHP5QueryBuilder, the PHP5 node/nestedset family) have been removed from the codebase entirely (archived under archaeology/php5-builders/). targetPlatform is effectively vestigial as a result — there’s no alternate builder set left to select via php5, though GeneratorConfig::getBuilderClassname() still honors a builder.*.php5.class-style override if you supply your own.
| Property | Default |
|---|---|
builder.peer.class | Propulsion\Generator\Builder\OM\PeerBuilder |
builder.object.class | Propulsion\Generator\Builder\OM\ObjectBuilder |
builder.objectstub.class | Propulsion\Generator\Builder\OM\ExtensionObjectBuilder |
builder.peerstub.class | Propulsion\Generator\Builder\OM\ExtensionPeerBuilder |
builder.objectmultiextend.class | Propulsion\Generator\Builder\OM\MultiExtendObjectBuilder |
builder.tablemap.class | Propulsion\Generator\Builder\OM\TableMapBuilder |
builder.query.class | Propulsion\Generator\Builder\OM\QueryBuilder |
builder.querystub.class | Propulsion\Generator\Builder\OM\ExtensionQueryBuilder |
builder.interface.class | Propulsion\Generator\Builder\OM\InterfaceBuilder |
builder.node.class / builder.nodepeer.class | Propulsion\Generator\Builder\OM\NodeBuilder / NodePeerBuilder |
builder.nodestub.class / builder.nodepeerstub.class | Propulsion\Generator\Builder\OM\ExtensionNodeBuilder / ExtensionNodePeerBuilder |
| builder.queryinheritance.class / builder.queryinheritancestub.class | Propulsion\Generator\Builder\OM\QueryInheritanceBuilder / ExtensionQueryInheritanceBuilder |
| builder.pluralizer.class | Propulsion\Generator\Builder\Util\DefaultEnglishPluralizer |
| builder.datasql.mysql.class | Propulsion\Generator\Builder\SQL\MySQL\MysqlDataSQLBuilder |
| builder.datasql.pgsql.class | Propulsion\Generator\Builder\SQL\PgSQL\PgsqlDataSQLBuilder |
| builder.datasql.sqlite.class | Propulsion\Generator\Builder\SQL\Sqlite\SqliteDataSQLBuilder |
| builder.datasql.mssql.class | Propulsion\Generator\Builder\SQL\MSSQL\MssqlDataSQLBuilder |
| builder.datasql.sqlsrv.class | Propulsion\Generator\Builder\SQL\Sqlsrv\SqlsrvDataSQLBuilder |
| builder.datasql.oracle.class | Propulsion\Generator\Builder\SQL\Oracle\OracleDataSQLBuilder |
| builder.datasql.class | ${propulsion.builder.datasql.${propulsion.database}.class} |
builder.*.php84.class variants of the OM builders above also exist, as an explicit alias for anyone who still passes --target-platform=php84 — they resolve to the exact same classes.
The four node/nodepeer keys drive treeMode="MaterializedPath" only. The nested_set behavior has no builder key of its own — it’s a behavior, so it modifies the ordinary object, peer and query builders rather than replacing them, and there’s nothing here to point elsewhere.
Platform classes
Section titled “Platform classes”| Property | Default |
|---|---|
platform.mysql.class | Propulsion\Generator\Platform\MysqlPlatform |
platform.pgsql.class | Propulsion\Generator\Platform\PgsqlPlatform |
platform.sqlite.class | Propulsion\Generator\Platform\SqlitePlatform |
platform.oracle.class | Propulsion\Generator\Platform\OraclePlatform |
platform.mssql.class | Propulsion\Generator\Platform\MssqlPlatform |
platform.sqlsrv.class | Propulsion\Generator\Platform\SqlsrvPlatform |
platform.class | ${propulsion.platform.${propulsion.database}.class} |
Reverse-engineering (schema parser) classes
Section titled “Reverse-engineering (schema parser) classes”| Property | Default |
|---|---|
reverse.parser.mysql.class | Propulsion\Generator\Reverse\MySQL\MysqlSchemaParser |
reverse.parser.pgsql.class | Propulsion\Generator\Reverse\PgSQL\PgsqlSchemaParser — requires PostgreSQL 15+ (uses pg_get_expr(adbin, adrelid), not the pre-12 pg_attrdef.adsrc text column). |
reverse.parser.sqlite.class | Propulsion\Generator\Reverse\SQLite\SqliteSchemaParser |
reverse.parser.mssql.class | Propulsion\Generator\Reverse\MSSQL\MssqlSchemaParser |
reverse.parser.sqlsrv.class | Propulsion\Generator\Reverse\Sqlsrv\SqlsrvSchemaParser |
reverse.parser.oracle.class | Propulsion\Generator\Reverse\Oracle\OracleSchemaParser |
reverse.parser.class | ${propulsion.reverse.parser.${propulsion.database}.class} |
MySQL-specific settings
Section titled “MySQL-specific settings”| Property | Default | Description |
|---|---|---|
mysql.tableType | InnoDB | Default storage engine for generated CREATE TABLE statements. InnoDB has been MySQL’s own default since 5.5, and native delete triggers need its foreign-key support. Set it to MyISAM for the pre-2.0 behaviour. |
mysql.tableEngineKeyword | ENGINE | Keyword used to specify the engine (TYPE on MySQL < 5, not relevant to any currently supported MySQL version). |
Oracle-specific settings
Section titled “Oracle-specific settings”| Property | Default | Description |
|---|---|---|
oracle.autoincrementSequencePattern | ${table}_SEQ | Sequence naming pattern for autoincrement columns. |
Behavior classes
Section titled “Behavior classes”| Property | Default |
|---|---|
behavior.timestampable.class | Propulsion\Generator\Behavior\TimestampableBehavior |
behavior.alternative_coding_standards.class | Propulsion\Generator\Behavior\AlternativeCodingStandardsBehavior |
behavior.soft_delete.class | Propulsion\Generator\Behavior\SoftDeleteBehavior |
behavior.auto_add_pk.class | Propulsion\Generator\Behavior\AutoAddPkBehavior |
behavior.nested_set.class | Propulsion\Generator\Behavior\NestedSet\NestedSetBehavior |
behavior.sortable.class | Propulsion\Generator\Behavior\Sortable\SortableBehavior |
behavior.sluggable.class | Propulsion\Generator\Behavior\Sluggable\SluggableBehavior |
behavior.aggregate_column.class | Propulsion\Generator\Behavior\AggregateColumn\AggregateColumnBehavior |
behavior.versionable.class | Propulsion\Generator\Behavior\Versionable\VersionableBehavior |
behavior.optimistic_lock.class | Propulsion\Generator\Behavior\OptimisticLock\OptimisticLockBehavior |
behavior.i18n.class | Propulsion\Generator\Behavior\I18n\I18nBehavior |
behavior.delegate.class | Propulsion\Generator\Behavior\DelegateBehavior |
behavior.archivable.class | Propulsion\Generator\Behavior\Archivable\ArchivableBehavior |
Object Model base classes
Section titled “Object Model base classes”| Property | Default |
|---|---|
om.BaseObject | Propulsion\OM\BaseObject |
om.Persistent | Propulsion\OM\Persistent |
What was removed relative to Propel 1
Section titled “What was removed relative to Propel 1”- All
propulsion.builder.*.php5.classdefault entries — the PHP5 builder classes they used to point at (PHP5PeerBuilder,PHP5ObjectBuilder,PHP5TableMapBuilder,PHP5QueryBuilder,PHP5NodeBuilder,PHP5NestedSetBuilder, and their extension/stub counterparts) are gone from the codebase.targetPlatform=php5no longer has anything to fall back to; only supplybuilder.*.php5.classyourself if you’ve written a replacement. propulsion.builder.nestedset.classandpropulsion.builder.nestedsetpeer.class, along with theNestedSetBuilder/NestedSetPeerBuilderclasses themselves. They servedtreeMode="NestedSet", removed in 3.0 in favour of thenested_setbehavior. A configuration still setting either key has nothing to point at.- Propel 1’s default database (
mysql) — seepropulsion.databaseabove; PostgreSQL is now the default.
What changed defaults relative to Propel 1
Section titled “What changed defaults relative to Propel 1”Only propulsion.database (mysql → pgsql) changes default value versus Propel 1’s own default.properties. Every other Propel 1 default carries over unchanged, modulo the class renames.
Build-time database connections
Section titled “Build-time database connections”Separate from the generator’s own build properties, some build-time tasks need a live database connection — reverse-engineering an existing schema (schema:reverse), diffing against a live database (sql:diff), or executing generated SQL (sql:exec). GeneratorConfig::getBuildConnections() resolves this, checked in order:
propulsion.buildtimeConfigArraybuild property — a plain PHP array already in the target shape (see below). The recommended path for new configs.propulsion.buildtimeConfFilebuild property naming a.phpfile, which isrequired and expected to return the same shape asbuildtimeConfigArray. It’s tried at aprojectDir-relative path, the given path directly, and a couple of legacybuild/propel/-style fallback locations. This is what--buildtime-confon the migration andsql:diffcommands sets.- If neither of the above resolves a connection for the requested datasource name, falls back to the single connection assembled from
propulsion.database.adapter/propulsion.database.url/.user/.password(see Database settings;database.adapterisn’t itself a documented default property).
The plain-PHP array shape:
<?phpreturn [ 'default' => 'bookstore', 'datasources' => [ 'bookstore' => [ 'adapter' => 'pgsql', 'dsn' => 'pgsql:host=localhost;dbname=bookstore', 'user' => 'me', 'password' => 'secret', ], ],];Runtime configuration
Section titled “Runtime configuration”This is the configuration your generated Object Model classes use to open a real database connection when your application runs — the Propulsion equivalent of what Propel 1 called runtime-conf.xml. It has nothing to do with the build-time properties or build-time connections above; it’s loaded separately, by your application, not by bin/propulsion.
Format: a plain PHP array, not XML
Section titled “Format: a plain PHP array, not XML”Propel 1’s runtime-conf.xml is gone. Propulsion::init($path) (Propulsion\Propulsion::init()) calls Propulsion::configure($path), which does exactly one thing: include($path) and expects the file to return an array. That array is wrapped in a Propulsion\Config\PropulsionConfiguration (an ArrayAccess container supporting dotted-key lookups like $config->getParameter('datasources.bookstore.connection.dsn')) and stored for the rest of the process.
<?phpreturn [ 'datasources' => [ 'default' => 'bookstore', 'bookstore' => [ 'adapter' => 'pgsql', 'connection' => [ // optional; defaults to the adapter's own connection class 'classname' => 'Propulsion\Adapter\Pgsql\PgsqlPropulsionPDO', 'dsn' => 'pgsql:host=localhost;dbname=bookstore', 'user' => 'app', 'password' => 'secret', 'options' => [], // PDO constructor options 'attributes' => [], // set via PDO::setAttribute() after connecting 'settings' => [ 'charset' => 'utf8', 'queries' => [], // SQL run once, immediately after connecting ], ], // optional: read-replica connections for this datasource 'slaves' => [ 'connection' => [ ['dsn' => 'pgsql:host=replica-1;dbname=bookstore'], ['dsn' => 'pgsql:host=replica-2;dbname=bookstore'], ], ], ], ],];<?phpPropulsion::init(__DIR__ . '/runtime-conf.php');
$con = Propulsion::getConnection('bookstore'); // master, by default$reader = Propulsion::getConnection('bookstore', Propulsion::CONNECTION_READ); // a slave, if configuredKey shape
Section titled “Key shape”| Key path | Description |
|---|---|
datasources.default | Name of the datasource Propulsion::getConnection() uses when called with no argument. |
datasources.<name>.adapter | Database adapter identifier (pgsql, mysql, sqlite, oracle, mssql, sqlsrv) — used to select the right DBAdapter subclass, independent from the PDO driver in dsn (e.g. an ODBC DSN targeting SQL Server would still set adapter: sqlsrv). |
datasources.<name>.connection.classname | The connection class to instantiate. Defaults to the adapter’s own (DBAdapter::getDefaultPdoClass()) — PgsqlPropulsionPDO for pgsql, MysqlPropulsionPDO for mysql, and so on, each extending the matching \Pdo\* class. A custom class must implement Propulsion\Connection\PropulsionPDO, which is an interface as of 2.0; the simplest way is to extend the driver-specific class you’re replacing, or to use PropulsionPDOTrait for the nested-transaction, logging, and statement-caching behaviour stock PDO doesn’t have. Naming the interface itself — or Propel 1’s PropelPDO, which a converted configuration carries — means “use Propulsion’s own PDO” and is substituted with the adapter’s default class rather than rejected. |
datasources.<name>.connection.dsn | The PDO DSN. Same format PHP’s PDO drivers always expected — see the PHP manual for PostgreSQL, MySQL, SQLite, Oracle, SQL Server. |
datasources.<name>.connection.user / .password | Credentials, for adapters that don’t embed them in the DSN. |
datasources.<name>.connection.options | PDO constructor options array — passed to new PDO($dsn, $user, $password, $options). Keys may be integer constants or bare names: ATTR_PERSISTENT resolves against PropulsionPDO first (where PROPEL_ATTR_CACHE_PREPARES lives) and then PDO, so the spelling Propel 1’s convert-conf emitted keeps working. An unresolvable name throws, naming both prefixes it tried. |
datasources.<name>.connection.attributes | Options applied via PDO::setAttribute() after the connection is created — same key space as options, different timing. |
datasources.<name>.connection.settings.charset | Character set applied to the connection where the RDBMS supports it. |
datasources.<name>.connection.settings.queries | Array of SQL statements executed once, immediately after connecting. |
datasources.<name>.slaves.connection | Either a single connection array, or a list of them — one is picked at random per getConnection(..., Propulsion::CONNECTION_READ) call when there’s more than one. |
cache.query | Optional. Configures the global (cross-process) query result cache — enabled, driver, ttl, namespace, plus admission, stampede, and per-driver option blocks. Fully documented in Query cache configuration. |
connection.liveness / connection.retry | Optional. The execution-strategy settings — pre-checkout liveness pings and transaction retry. Both off by default; see the connection section below. |
telemetry | Optional. Turns on OpenTelemetry span export for every statement — enabled, service_name, record_statement_text, plus exporter and sampler blocks. Off by default; see the telemetry section below. |
Read a value at runtime with Propulsion::getConfiguration() or, for a single dotted key, PropulsionConfiguration::getParameter('datasources.bookstore.connection.dsn').
The cache section
Section titled “The cache section”One of three optional top-level keys besides datasources (the others being connection and telemetry). It’s optional, and an absent cache key means the query result cache stays request-scoped, exactly as it is without any configuration:
return [ 'datasources' => [ /* ... */ ], 'cache' => [ 'query' => [ 'enabled' => true, 'driver' => 'apcu', 'ttl' => 300, ], ],];Unlike datasources, this section is strictly validated: an unknown key or a wrong value type throws a PropulsionException at parse time rather than being silently ignored, so a 'tll' => 300 typo fails at boot instead of quietly running on defaults. See Query cache configuration for every key, the shipped drivers, and how to register your own PSR-16 pool.
The connection section
Section titled “The connection section”Optional, and absent means both features are off — which is the default because each spends something real: a round trip per idle checkout, or running the caller’s closure more than once.
return [ 'datasources' => [ /* ... */ ], 'connection' => [ 'liveness' => [ 'enabled' => true, 'idle_threshold' => 5.0, ], 'retry' => [ 'enabled' => true, 'max_attempts' => 3, ], ],];| Key | Default | Effect |
|---|---|---|
connection.liveness.enabled | false | Ping a pooled connection before handing it out, replacing it if the ping fails. |
connection.liveness.idle_threshold | 5.0 | Seconds a connection must have sat unused before a checkout is worth a SELECT 1. 0.0 pings every checkout; a negative value is rejected. |
connection.retry.enabled | false | Retry a Propulsion::transaction() whose failure the adapter classifies as transient. |
connection.retry.max_attempts | 3 | Total attempts, not retries. |
connection.retry.base_delay | 50 | Milliseconds before the first retry. |
connection.retry.max_delay | 1000 | Millisecond ceiling on the computed delay. |
connection.retry.multiplier | 2.0 | Per-attempt backoff growth factor. |
connection.retry.jitter | 1.0 | 1.0 is full jitter, 0.0 none. |
Like cache, this section is strictly validated: an unknown key or a wrong value type throws a PropulsionException at parse time rather than being silently ignored. What each setting buys, what is and isn’t retried, and the requirement that a retried closure be safe to run twice are all on Connection resilience.
The telemetry section
Section titled “The telemetry section”Optional, and absent means off — under which Propulsion never references an open-telemetry/* class at all, so those packages don’t need to be installed. Turning it on gives every statement an exported OpenTelemetry span, with no application code:
return [ 'datasources' => [ /* ... */ ], 'telemetry' => [ 'enabled' => true, 'service_name' => 'bookstore-api', 'exporter' => [ 'endpoint' => 'http://otel-collector:4318/v1/traces', 'protocol' => 'http/protobuf', 'headers' => ['authorization' => 'Bearer ' . getenv('OTLP_TOKEN')], 'timeout' => 10, ], 'sampler' => ['ratio' => 0.05], 'record_statement_text' => true, ],];| Key | Default | Effect |
|---|---|---|
telemetry.enabled | false | Master gate. |
telemetry.service_name | 'propulsion' | The service.name resource attribute. |
telemetry.exporter.endpoint | — | OTLP/HTTP traces endpoint, path included. Required when enabled is true, and validated as a URL. |
telemetry.exporter.protocol | 'http/protobuf' | http/protobuf or http/json; anything else is rejected. |
telemetry.exporter.headers | [] | Extra HTTP headers on every export request. A map of string to string. |
telemetry.exporter.timeout | 10 | Export request timeout in seconds; at least 1. |
telemetry.sampler.ratio | 1.0 | TraceIdRatioBased fraction, 0.0–1.0 inclusive. |
telemetry.record_statement_text | true | Whether db.query.text is attached to spans. |
Like cache and connection, this section is strictly validated: an unknown key or a wrong value type throws a PropulsionException at parse time, so an 'enpoint' => ... typo fails at boot rather than leaving the feature looking on while shipping nothing. The packages to install, sampling, the PII trade-off on record_statement_text, worker-mode flushing and how to supply your own tracer provider are all on OpenTelemetry tracing.
What replaced runtime-conf.xml
Section titled “What replaced runtime-conf.xml”Propel 1 (runtime-conf.xml) | Propulsion (runtime array) |
|---|---|
<datasources default="bookstore"> | 'datasources' => ['default' => 'bookstore', ...] |
<datasource id="bookstore"><adapter>mysql</adapter> | 'datasources' => ['bookstore' => ['adapter' => 'pgsql', ...]] |
<connection><dsn>...</dsn><user>...</user><password>...</password></connection> | 'connection' => ['dsn' => ..., 'user' => ..., 'password' => ...] |
<connection><classname>Propel\Runtime\Connection\ConnectionWrapper</classname></connection> | 'connection' => ['classname' => 'Propulsion\Connection\PropulsionPDO'] |
<connection><options>...</options></connection> | 'connection' => ['options' => [...]] |
<connection><attributes>...</attributes></connection> | 'connection' => ['attributes' => [...]] |
<connection><settings><charset>utf8</charset><queries>...</queries></settings></connection> | 'connection' => ['settings' => ['charset' => 'utf8', 'queries' => [...]]] |
<slaves><connection>...</connection>...</slaves> | 'slaves' => ['connection' => [...]] |
Propel::init('/path/to/runtime-conf.php') (compiled from XML) | Propulsion::init('/path/to/runtime-conf.php') (hand-written PHP array, no compile step) |
Since the runtime file is plain PHP, there’s no separate “compile the XML into PHP” build step the way Propel 1’s propel-gen produced a *-conf.php alongside runtime-conf.xml — you write the array directly, or generate it yourself from whatever source you like (environment variables, a secrets manager, etc.).
Logging
Section titled “Logging”Propel 1’s runtime config carried Zend/sfLogger-flavored <log>/<logger> sections. Propulsion doesn’t read logging configuration from the runtime array at all — it logs through PSR-3 instead, and you register your own logger programmatically:
<?phpPropulsion::init(__DIR__ . '/runtime-conf.php');Propulsion::setLogger($myPsr3Logger); // e.g. a Monolog\Logger instanceWithout a registered logger, Propulsion::log() is a no-op — there’s no implicit error_log() fallback. See Logging for the full setup, including per-connection overrides.
Using it from Quiote
Section titled “Using it from Quiote”If you’re using Propulsion through Quiote’s database adapter rather than standalone, you don’t call Propulsion::init() yourself — point the propulsion database’s config parameter at this same file, and PropulsionDatabase calls it for you:
return [ 'databases' => [ 'main' => [ 'class' => 'propulsion', 'parameters' => [ 'config' => __DIR__ . '/runtime-conf.php', 'datasource' => 'bookstore', ], ], ],];That databases config is Quiote’s, not Propulsion’s, so it can equally be written as Config/databases.yaml or Config/databases.xml — see Databases. Only the config parameter’s target, the Propulsion runtime file above, is PHP by nature.
See Databases: Propulsion for the full parameter list.