Skip to content

Repository files navigation

Winter Kernel

Latest Version on PackagistPHP Version RequireSoftware License

The kernel of the Winter framework — a PHP 8.4 library that turns a directory of classes into a running application. It carries the HTTP layer, dependency injection, the database layer (PPA), managed processes and daemons, scheduling, and the console.

It is a library, not a skeleton: there is nothing to scaffold and no directory tree to create. You add it to a project, write one class that says what the application contains, and run it.


Requirements

PHP8.4+
Extensionspcntl, posix, fileinfo (required) · swoole (for the HTTP server, coroutines and connection pooling) · pdo for a database

Everything else is pulled by composer.


Install

composer require flytachi/winter-kernel

The whole application: two files

bootstrap.php — loads the autoloader and declares what the application contains:

<?phpdeclare(strict_types=1);
useFlytachi\Winter\Kernel\App\Attribute\EnableWeb;
useFlytachi\Winter\Kernel\WinterApplication;
require__DIR__ . '/vendor/autoload.php';
#[EnableWeb]
finalclass Application extends WinterApplication
{
publicstaticfunctionmain(array$argv): never
{
parent::run($argv);
}
}

call — the single entry point (make it executable with chmod +x call):

#!/usr/bin/env php<?phpchdir(__DIR__);
require'./bootstrap.php';
Application::main($argv);

That is a working project. No .env, no directories — the kernel creates what it needs, when it needs it.

php call # console: the command list
php call run # bring the application up
php call run dev # same, restarting on file changes

Add a controller anywhere under the project and it is found by the scan:

useFlytachi\Winter\Kernel\Route\Annotation\GetMapping;
useFlytachi\Winter\Kernel\Http\Stereotype\Controller;
finalclass PingController extends Controller
{
#[GetMapping('/ping')]
publicfunctionping(): array
{
return ['pong' => true];
}
}

What the application contains — #[Enable*]

The attributes on the application class are the manifest. Each one adds a component; declare none and the boot fails rather than starting an application that does nothing.

AttributeEffect
#[EnableWeb]the Swoole HTTP server
#[EnableActuator]/actuator diagnostics (health, info, metrics, mappings)
#[EnableScheduler]runs #[Scheduled] methods on their triggers
#[EnableProcess(Foo::class)]a managed worker beside the server
#[EnableDaemon(Bar::class)]a supervised fleet of workers beside the server
#[EnableAsync]proxies #[Async] methods so they run off the request
#[Import('vendor/pkg', '/prefix')]mounts a plugin package under a URL prefix

Everything else is configured by ordinary classes the scan finds — there are no configuration hooks to override:

#[Configuration] / #[Bean] // DI factories
WebConfigurer // host, port, Swoole tuning, CORS, static files
LoggingConfigurer // extra log channels

Project layout

Only two directories are conventional, and both are optional:

resources/
static/ web assets — served by Swoole when enabled (see WebConfigurer)
views/ view files — ResponseView's default root
storage/
logs/ cache/ runnable/ created on demand, never committed

There is no public/: that belongs to the FPM document-root model, and the server here decides for itself what it serves. Static files are opt-in:

finalclass WebConfig extends WebConfigurerAdapter
{
publicfunctionconfigureServer(ServerSettings$server, ApplicationArguments$args): void
{
$server->port(8000)
->staticPath('resources/static'); // resources/static/app.css → /app.css
}
}

Configuration

.env is optional; every variable has a working default.

VariableDefaultMeaning
DEBUGfalseverbose errors and a full rescan on every boot
LOG_LEVEL(empty — logging off)debugemergency
LOG_OUTPUTauto → stdoutstdout, stderr, file, syslog, null
LOG_FILEstorage/logs/<channel>.logabsolute path when LOG_OUTPUT=file
SERVER_WORKERSSwoole defaultworker count
WINTER_KEY(none)signs payloads handed to background processes
PPA_POOL_TELEMETRY5seconds between pool-stat publishes; 0 disables

Console

php call # command list
php call run [dev] # serve
php call make -c UserController # scaffold a class
php call daemon <dot.Class> start [-d] | stop | status
php call process <dot.Class> start [-d] | stop | status
php call db ping | migrate | sql | pool
php call schedule start [-d] | stop | status
php call cfg completion -i # shell completion

Class names use dot notation: main.process.EmailsMain\Process\Emails.


Runtimes

The kernel runs the same application two ways:

  • Swoole — one long-lived server process; coroutines, connection pooling and static files handled in C. This is the primary target.
  • CLI / plain processes — the console, and processes or daemons started on their own.

FPM is not served by the kernel itself; it is moving to a separate winter-fpm project.


Documentation

  • docs/starter/00-quickstart.md — from an empty directory to a served request, then to a background worker.
  • docs/ — the reference for each subsystem (routing, request binding, responses, PPA, processes and daemons, scheduling, console, configuration).

Development

vendor/bin/phpunit # the default suite
vendor/bin/phpunit --group integration # real forks, signals and servers
vendor/bin/phpcs # PSR-12

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages