Skip to main content
Winter Boot’s database layer wraps PHP’s native PDO (and optional OCI) extensions behind the PdbcTemplate interface, giving you a clean, injection-friendly API for executing SQL without managing connections, prepared statements, or result-set iteration yourself. Each configured datasource automatically produces a named PdbcTemplate bean and a transaction manager bean you can inject anywhere in your application.
Need full ORM entities and repositories instead of raw SQL? The Winter Doctrine module plugs Doctrine ORM and DBAL into the same datasource configuration.

Datasource Configuration

Declare datasources in application.yml under the top-level datasource key. You may configure as many datasources as you need — mark exactly one as the primary with isPrimary: true.
application.yml

Top-Level Datasource Properties

bool
default:"false"
Mark this datasource as the primary. The primary datasource’s PdbcTemplate is injected with a plain #[Autowired] (no qualifier needed).
string
default:"''"
SQL statement used to validate connections before use (e.g. SELECT 1).
string
default:"PdoDataSource"
Fully-qualified class name of a custom DataSource implementation.

Connection Options Reference

bool
default:"false"
Use persistent PDO connections.
string
default:"ERRMODE_EXCEPTION"
PDO error mode. One of ERRMODE_SILENT, ERRMODE_WARNING, or ERRMODE_EXCEPTION.
string
default:"CASE_NATURAL"
Column name case folding. One of CASE_NATURAL, CASE_LOWER, or CASE_UPPER.
int
default:"600"
Seconds before an idle connection is recycled.
bool
default:"true"
Enable auto-commit for non-transactional operations.
int
default:"30"
Connection-level statement timeout in seconds.
int
default:"100"
Number of rows to prefetch. Applies to the OCI driver only.

Injecting PdbcTemplate

Winter Boot automatically registers a PdbcTemplate bean for every configured datasource. Use a plain #[Autowired] to inject the primary datasource’s template, or target a specific datasource by the <datasource-name>-template bean name.
UserRepository.php
The -template suffix is part of Winter Boot’s automatic bean-naming convention. For every datasource named <name>, the framework registers a bean under <name>-template. You only need the suffix when injecting a non-primary template.

PdbcTemplate Methods

Every method accepts either a plain PHP array (positional ? or named :name placeholders) or a typed BindVars collection as its bind-variable argument.
Execute any SQL statement and optionally receive the underlying PreparedStatement in a callback.Returns: mixed — the result of the callback, or the raw execution result.
Execute a query and hand the result set to a processor callback, ResultSetExtractor, RowCallbackHandler, or RowMapper.
Return all result rows as an array of associative arrays.Returns: array[['col' => 'val', ...], ...]
Return a single row as an associative array. Throws an exception if the query returns zero or more than one row.
Return the first column of the first row as a scalar value.
Map a single result row to an object using a class name or a custom RowMapper.
Return multiple rows as an array of PPA entity objects.
Execute an INSERT, UPDATE, or DELETE statement. Supports OUT bind variables and retrieval of database-generated keys.
Execute the same parameterised SQL statement for multiple sets of bind variables in a single batch.
Persist one or more PPA entity objects. The framework generates the correct INSERT or UPDATE SQL automatically.
Delete one or more PPA entity objects from the database.

BindVars — Typed Parameters

For queries where you need explicit type control, use the BindVars fluent builder instead of a plain array.

BindType Constants


PPA — PHP Persistence API

PPA is Winter Boot’s lightweight ORM layer. An entity is any class annotated with #[Table] that either implements the PpaEntity interface or uses the PpaEntityTrait convenience trait. The framework automatically generates INSERT, UPDATE, and DELETE SQL and maps query result columns back to PHP properties.

Annotations

Use #[Table] at the class level to map the class to a database table, and #[Column] at the property level to map each property to a column.
Applied at class level. Maps the class to the named database table.
#[Column] options:
string
default:"property name"
The database column name.
bool
default:"false"
Marks this column as the primary key.
bool
default:"true"
Include this column in INSERT statements.
bool
default:"true"
Include this column in UPDATE statements.
bool
default:"true"
Allow NULL values for this column.
int
default:"0"
Column length hint.
int
default:"0"
Decimal precision.
int
default:"0"
Decimal scale.

Full Entity Example

User.php
Columns marked with insertable: false, updatable: false (like auto-generated id and created_at fields) are excluded from write operations but are still populated when reading rows back from the database.

Multi-Tenant Support

Winter Boot provides first-class multi-tenancy via MultiTenantManager and the TenantDataSourceProvider contract. Each tenant gets its own lazily-created, cached PdbcTemplate and PlatformTransactionManager backed by a separate data source resolved at runtime.

Configure a Multi-Tenant Datasource

application.yml
When the application starts, Winter Boot registers a MultiTenantManager bean under the name tenantdb-manager.

Step 1 — Implement TenantDataSourceProvider

Implement TenantDataSourceProvider to tell Winter Boot how to look up each tenant’s connection details and how to enumerate all active tenants.
MyTenantDataSourceProvider.php

Step 2 — Use MultiTenantManager in Business Classes

Inject the MultiTenantManager bean and call getPdbcTemplate() or getTransactionManager() with the tenant ID at runtime.
OrderService.php

MultiTenantManager API