Skip to main content
This guide walks you through building a minimal but complete Winter Boot microservice from scratch. By the end you will have a running HTTP server, a managed service bean, and a REST endpoint you can hit with curl. All you need is PHP 8.4+, Composer, and the Swoole extension.
A fully-featured reference implementation is available at github.com/suvera/winter-example-service. Clone it to see a real-world project layout with Docker, Phar builds, datasource configuration, and more.
1

Install PHP and Swoole

Ensure PHP 8.4 or later is installed, then install the Swoole extension for the built-in async HTTP server:
Confirm both are available:
2

Require the Composer Packages

Create a new directory for your project and initialise it with Composer, then pull in the core framework package. The optional winter-modules package adds community integrations (Redis, Kafka, Doctrine ORM, and more).
3

Create the Directory Structure

Winter Boot expects a config/ directory for application.yml and a src/ directory for your PHP classes. A minimal layout looks like this:
4

Write application.yml

Create config/application.yml. At minimum you need a server port. The winter.application block gives your service a human-readable name and version that surface in health and metrics endpoints.
config/application.yml
5

Create a Service Bean

Annotate a class with #[Service] to register it as a managed bean. Winter Boot will instantiate it, inject its dependencies, and make it available for #[Autowired] injection throughout the application context.
src/GreetingService.php
6

Create a REST Controller

Annotate a class with #[RestController] and map an HTTP route with #[GetMapping]. Inject the service bean via #[Autowired]. Return a ResponseEntity to control the HTTP status code and response body.
src/GreetingController.php
7

Create the Application Entry Point

The entry-point class carries the #[WinterBootApplication] attribute, which tells the framework where to find your configuration and which namespaces to scan for beans.
  • configDirectory — directories containing application.yml and any other config files.
  • scanNamespaces — pairs of [NamespacePrefix, BaseDirectory] the scanner should inspect.
Application.php
8

Run the Application

Start the server by executing the entry point with PHP. Swoole will fork worker processes and begin accepting HTTP connections on the port defined in application.yml.
You should see output similar to:
9

Test with curl

In a separate terminal, send a request to the greeting endpoint:
Expected response:
Test the default parameter:

What’s Next?

Now that your service is running, explore these topics to build on the foundation:

Configuration

Externalise settings with application.yml, #[Value], and additional property sources.

Dependency Injection

Learn about bean scopes, qualifiers, and #[PostConstruct] lifecycle hooks.

REST Controllers

Handle path variables, request bodies, and return custom status codes.

Databases & Transactions

Connect a datasource and manage transactions with #[Transactional].

Async & Scheduling

Run background jobs with #[Async] and #[Scheduled].

Module System

Add Redis, Kafka, Doctrine ORM, and other integrations via community modules.