Skip to content

Configuration in Winter Boot: Properties, Beans & Sources

Winter Boot’s configuration system is built around two complementary models: static property externalisation via application.yml and programmatic bean construction via #[Configuration] classes. Both are fully integrated with the dependency-injection container, so any property or bean is available for injection anywhere in your application. This page covers every layer of the system — from the YAML file structure and the #[Value] attribute, through additional property sources, to the || fallback-chain syntax.

All externalised properties live in config/application.yml (the path is set by the configDirectory option of #[WinterBootApplication]). Winter Boot parses this file at startup and makes every key available to the property context. The reserved top-level keys used by the framework are shown below; custom application keys can live anywhere else in the file.

config/application.yml
server:
port: 8080 # Port the Swoole HTTP server binds to
address: 127.0.0.1 # Network interface to listen on
context-path: / # URL prefix for all routes
winter:
application:
name: My Microservice # Human-readable service name
id: my-microservice # Machine-readable identifier
version: 1.0.0-DEV # Semantic version string
datasource:
- name: default
url: "sqlite:/opt/databases/mydb.sq3"
username:
password:
validationQuery: SELECT 'ok'
driverClass: dev\winterframework\pdbc\pdo\PdoDataSource
connection:
persistent: true
errorMode: ERRMODE_EXCEPTION
columnsCase: CASE_NATURAL
idleTimeout: 300
autoCommit: true
defaultrowprefetch: 100
# Custom application properties — any structure you like:
myApp:
value1: This is a string property
value2: 99
value3: true
value4: 10.89
  • `` integer (default: 8080) Port the Swoole HTTP server binds to.

  • `` string (default: 127.0.0.1) Network interface the server listens on. Use 0.0.0.0 to bind all interfaces.

  • `` string (default: /) URL prefix prepended to all mapped routes.

  • `` string Human-readable service name. Exposed by health and metrics endpoints.

  • `` string Machine-readable service identifier used in logs and service-discovery registrations.

  • `` string Semantic version string for the running service.

  • `` array List of datasource definitions. Each entry requires at least name, url, and driverClass.

#[WinterBootApplication] Attribute Options

Section titled “#[WinterBootApplication] Attribute Options”

The entry-point attribute controls how Winter Boot boots your application. All parameters are optional and have sensible defaults.

Application.php
<?php
use dev\winterframework\stereotype\WinterBootApplication;
use dev\winterframework\core\app\WinterWebSwooleApplication;
#[WinterBootApplication(
// Directories to search for application.yml and other config files
configDirectory: [__DIR__ . '/config'],
// Namespace-to-directory mappings for component scanning:
// each entry is [NamespacePrefix, BaseDirectory]
scanNamespaces: [
['com\\example\\myapp', __DIR__ . '/src']
],
// If true, the autoloader will attempt to load unknown classes during scan
autoload: false,
// Namespaces the scanner should skip entirely
scanExcludeNamespaces: ['com\\example\\myapp\\generated'],
// Optional: profile name to load profile-specific config (e.g. application-prod.yml)
profile: null,
// Set to true to instantiate all beans eagerly at startup
// (predictable boot but slower start time)
eager: false
)]
class Application
{
public static function main(): void
{
(new WinterWebSwooleApplication())->run(Application::class);
}
}
Parameter Type Default Description
configDirectory array [] Directories scanned for application.yml and other config files.
scanNamespaces array [] Pairs of [NamespacePrefix, BaseDirectory] for component scanning.
autoload bool false Whether the scanner tries to autoload unknown classes it encounters.
scanExcludeNamespaces array [] Namespaces the scanner skips entirely.
profile string|null null Loads application-{profile}.yml and merges it over the base config.
eager bool false When true, all beans are instantiated at startup rather than lazily.

The #[Value] attribute injects a property from the application context into any bean property or constructor parameter. Reference YAML keys with dot notation inside ${ }.

src/AppConfig.php
<?php
declare(strict_types=1);
namespace com\example\myapp;
use dev\winterframework\stereotype\Service;
use dev\winterframework\stereotype\Value;
#[Service]
class AppConfig
{
#[Value('${server.port}')]
private int $serverPort;
#[Value('${winter.application.name}')]
private string $appName;
#[Value('${myApp.value1}')]
private string $customMessage;
#[Value('${myApp.value2}')]
private int $numericSetting;
public function getServerPort(): int { return $this->serverPort; }
public function getAppName(): string { return $this->appName; }
}

For beans that require construction logic — datasource pools, transaction managers, cache providers, third-party clients — use a #[Configuration] class. Methods annotated with #[Bean] are called once at startup and their return values are registered as managed beans. Winter Boot automatically injects other beans as method parameters.

src/DatabaseConfig.php
<?php
declare(strict_types=1);
namespace com\example\myapp;
use dev\winterframework\stereotype\Configuration;
use dev\winterframework\stereotype\Bean;
use dev\winterframework\stereotype\Value;
#[Configuration]
class DatabaseConfig
{
#[Value('${datasource[0].url}')]
private string $dbUrl;
/**
* Produces a DataSource bean available for #[Autowired] injection.
*/
#[Bean]
public function getDataSource(): DataSource
{
return new PdoDataSource($this->dbUrl);
}
/**
* Winter Boot injects the DataSource bean defined above automatically.
*/
#[Bean]
public function getTransactionManager(DataSource $ds): PlatformTransactionManager
{
return new PdoTransactionManager($ds);
}
}

Beyond application.yml, Winter Boot supports pluggable PropertySource implementations. Register them in application.yml under the propertySources key and reference their values with $sourceName.key notation.

The built-in EnvPropertySource reads from $_ENV. Register it and reference variables with the $env. prefix:

config/application.yml
propertySources:
- name: env
provider: dev\winterframework\io\EnvPropertySource
datasource:
- name: default
username: "$env.DB_USERNAME"
password: "$env.DB_PASSWORD"

A property value can be a ||-separated chain. Winter Boot tries each term from left to right and uses the first present value. This lets you layer sources — environment variable first, INI file second, hard-coded default last — without any PHP code.

config/application.yml
propertySources:
- name: env
provider: dev\winterframework\io\EnvPropertySource
- name: ini
provider: dev\winterframework\io\IniPropertySource
filePath: /etc/myapp/secrets.ini
datasource:
- name: default
# Try ENV first, then INI file, fall back to literal default
username: "$env.DB_USERNAME || $ini.dbUsername || appuser"
password: "$ini.dbPassword || $vault.db_password || secret"
# Booleans and numbers keep their type when used as literals
sslEnabled: "$env.DB_SSL || false"
poolSize: "$env.DB_POOL_SIZE || $ini.poolSize || 10"
# A chain can end with null to make the property optional
optionalNote: "$env.DB_NOTE || null"
# Quoted string literal as the final default
welcome: "$env.DB_GREETING || 'hello world'"
Presence and fall-through rules
Value Behaviour
Any non-empty, non-null value Present — stops the chain and uses this value.
false, 0, '0' Present — stops the chain immediately.
null or '' Falls through to the next term in the chain.
Unknown source name Treated as a missing key — falls through.
Single $source.key (no `
Plain value with no $source.key Never treated as a chain — `“a

Use the profile parameter of #[WinterBootApplication] to load environment-specific configuration. Winter Boot merges application-{profile}.yml on top of the base application.yml, with profile-specific values taking precedence.

Application.php
<?php
declare(strict_types=1);
use dev\winterframework\stereotype\WinterBootApplication;
use dev\winterframework\core\app\WinterWebSwooleApplication;
require_once __DIR__ . '/vendor/autoload.php';
#[WinterBootApplication(
configDirectory: [__DIR__ . '/config'],
scanNamespaces: [['com\\example\\myapp', __DIR__ . '/src']],
profile: 'prod' // loads config/application-prod.yml
)]
class Application
{
public static function main(): void
{
(new WinterWebSwooleApplication())->run(Application::class);
}
}
Application::main();
config/application-prod.yml
server:
port: 80
address: 0.0.0.0
winter:
application:
version: 1.0.0

The example below shows a full application.yml combining a custom property source, fallback chains, and all standard Winter Boot keys:

config/application.yml
server:
port: "$env.SERVER_PORT || 8080"
address: "$env.SERVER_ADDRESS || 0.0.0.0"
winter:
application:
name: "$env.APP_NAME || My Service"
id: my-service
version: 1.0.0
propertySources:
- name: env
provider: dev\winterframework\io\EnvPropertySource
- name: ini
provider: dev\winterframework\io\IniPropertySource
filePath: /run/secrets/app.ini
datasource:
- name: default
url: "$env.DB_URL || $ini.dbUrl"
username: "$env.DB_USER || $ini.dbUser || appuser"
password: "$env.DB_PASS || $ini.dbPass"
validationQuery: SELECT 1
driverClass: dev\winterframework\pdbc\pdo\PdoDataSource
connection:
persistent: true
autoCommit: true
idleTimeout: 300