Skip to content

Doctrine Sample Application

Build a REST API that manages users through Doctrine ORM entities. You use Winter Boot for the application runtime and the winter-doctrine package for the EntityManager and transaction manager. Writes run inside programmatic transactions via EmTransactionManager.

You need PHP 8.5 or later with the pdo_pgsql extension. You also need a PostgreSQL server. The sample config points at localhost:5432, database appdb, user appuser — replace them with your own server.

Start PostgreSQL before you run the app:

Terminal window
docker run -d -p 5432:5432 --name postgres \
-e POSTGRES_DB=appdb \
-e POSTGRES_USER=appuser \
-e POSTGRES_PASSWORD=apppass \
postgres:16

The sample uses this layout:

doctrine/
├── bin/
│ └── application.php # Application entry point
├── config/
│ └── application.yml # Datasource and Doctrine module config
├── create-table.sql # Table setup script
├── src/
│ ├── DoctrineSampleApplication.php # Main application class
│ ├── controller/
│ │ └── UserController.php # User REST endpoints
│ ├── model/
│ │ └── User.php # Doctrine entity
│ └── service/
│ └── UserService.php # Transactional user operations
└── composer.json # Dependencies

Require the framework and the Doctrine package:

Terminal window
composer require suvera/winter-boot suvera/winter-doctrine

Switch between the source files. Each tab shows the exact file from the sample.

The single entry point. #[EnableTransactionManagement] activates the transaction infrastructure used by the service.

<?php
namespace dev\example;
use dev\winterframework\stereotype\WinterBootApplication;
use dev\winterframework\stereotype\txn\EnableTransactionManagement;
#[WinterBootApplication(
configDirectory: [__DIR__ . "/../config"],
scanNamespaces: [
['dev\\example', __DIR__ . '']
]
)]
#[EnableTransactionManagement]
class DoctrineSampleApplication {
public static function main(): void {
$winterApp = new \dev\winterframework\core\app\WinterWebSwooleApplication();
$winterApp->run(self::class);
}
}

Switch between the two config files. application.yml registers the module and the datasource, and create-table.sql creates the table.

The full sample file registers DoctrineModule, marks defaultdb as primary, and points the ORM at the model directory. It keeps only the server, app identity, module, and datasource keys:

server:
port: 8080
address: 0.0.0.0
context-path: /
winter:
application:
name: Doctrine Sample Application
id: doctrine-sample-app
version: 1.0.0
modules:
- module: dev\winterframework\doctrine\DoctrineModule
enabled: true
datasource:
- name: defaultdb
isPrimary: true
url: "pgsql:host=localhost;port=5432;dbname=appdb"
username: appuser
password: apppass
validationQuery: SELECT 'Database Connected'
driverClass: dev\winterframework\pdbc\pdo\PdoDataSource
connection:
persistent: false
errorMode: ERRMODE_EXCEPTION
autoCommit: false
defaultrowprefetch: 100
idleTimeout: 180
charset: utf8
schema: public
doctrine:
entityPaths:
- /path/to/src/model

Replace the connection details with your own server, and entityPaths with the absolute path of your src/model directory. See Configuration for every application.yml key.

Create the table, start the app, then create and read a user.

1. Create the table:

Terminal window
psql -h localhost -p 5432 -U appuser -d appdb -f create-table.sql

2. Start the application:

Terminal window
composer install
php bin/application.php

3. Create a user:

Terminal window
curl -X POST "http://localhost:8080/users" \
-H "Content-Type: application/json" \
-d '{"name":"Ada Lovelace","email":"ada@example.com"}'

4. List users:

Terminal window
curl "http://localhost:8080/users"

5. Delete the user:

Terminal window
curl -X DELETE "http://localhost:8080/users/1"
  • Read the Doctrine module for DBAL access, multi-tenant datasources, and #[Transactional] managers.
  • Browse all Libraries when you need Redis, Kafka, S3, or OpenSearch in the same app.