Начало работы

Установка

Winter — библиотека, а не каркас с обязательной структурой. Проект собирается из нескольких файлов, и ниже разобран каждый: что он делает и почему нужен. Если разбирать не хочется — первая же команда на этой странице даёт работающий проект.

Требования

Требование Значение
PHP 8.4 или выше
Composer 2.x
Расширения ext-pcntl, ext-posix, ext-fileinfo
Для веб-приложения ext-swoole

Веб-слой работает только на Swoole

Winter не использует встроенный сервер PHP. Если приложение объявляет #[EnableWeb], запуск требует расширение Swoole и без него откажется стартовать:

`call run` with a web tier needs ext-swoole (pecl install swoole).

Это касается и режима разработки — он отличается только наблюдением за файлами, сервер тот же самый.

Приложению без веба — только процессы, демоны или планировщик — Swoole не обязателен.

Остальные расширения ставятся под конкретные задачи:

Расширение Зачем
ext-pdo Доступ к базе данных
ext-simplexml Разбор XML в теле запроса
ext-bcmath, ext-decimal Точные числовые типы при привязке параметров
ext-shmop Передача данных дочернему процессу через разделяемую память; без него используется канал

Проверка окружения

php -v покажет версию, php -m — список расширений. Отсутствие swoole в этом списке — самая частая причина, по которой первый запуск не удаётся.

Три пути

Путь Когда
Готовый каркас — create-project Новый проект; нужен работающий скелет за одну команду
Через Docker На машине нет PHP или нужных расширений
С нуля — require winter-kernel Встраивание в существующий проект, своя раскладка, или желание понимать каждый файл

Готовый каркас

bash
composer create-project flytachi/winter my-app
cd my-app
php call run dev

Composer после установки сам доводит проект до рабочего состояния — это видно в его выводе:

text
> @php call storage init
|	 storage ..................................................... [CREATED]
|	 storage/cache ............................................... [CREATED]
|	 storage/logs ................................................ [CREATED]
> chmod -R 777 storage
> @php call cfg init
|	 .env ........................................................ [CREATED]
|	 Old key    (empty)
| [✓] WINTER_KEY generated and saved to .env
|	 New key    bf4ee7d770a565c21598e57e87d46fde6637c0181cac13f4c37fd7b4c194c652

Каталоги созданы и доступны на запись, .env на месте, ключ — свой, а не общий с чужим проектом. Ставить и настраивать больше нечего.

В каркасе ровно то же, что собирается вручную ниже: bootstrap.php с классом приложения, файл call, PSR-4 Main\ → main/, готовый MainController и monolog/monolog в require-dev — чтобы логи было куда писать сразу.

Дальше можно не читать

Если каркас подошёл, переходите к Быстрому старту. Разделы ниже — для тех, кому нужно собрать проект руками или понять, из чего он состоит.

Через Docker, если PHP нет

create-project — тоже PHP-программа, но запустить её можно в одноразовом контейнере: образ несёт PHP внутри, а проект остаётся у вас в примонтированном каталоге.

bash
docker run --rm -v "$PWD":/app -w /app composer:2 \
  create-project flytachi/winter my-app --ignore-platform-reqs

--ignore-platform-reqs нужен потому, что ядро требует ext-pcntl и ext-posix — они нужны работающему приложению, а не установщику, и в рабочем образе они есть.

Дальше проект поднимается своим контейнером, где Swoole уже собран, а консольные команды выполняются тем же одноразовым способом. Подробно, с командами — в Быстром старте.

Сборка проекта с нуля

1. Каталог и зависимость

bash
mkdir my-app && cd my-app
composer require flytachi/winter-kernel

2. Каталог кода и автозагрузка

Winter ничего не навязывает: каталог и пространство имён выбираете вы — дальше в примерах это main/ и Main\.

bash
mkdir main

Теперь свяжите их в composer.json:

composer.json
{
  "autoload": {
      "psr-4": {
          "Main\\": "main/"
      }
  },
  "require": {
      "php": ">=8.4",
      "flytachi/winter-kernel": "^4.0"
  }
}
bash
composer dump-autoload

3. Класс приложения — bootstrap.php

Это единственный файл настройки. Он подключает автозагрузчик и объявляет, из чего состоит приложение:

bootstrap.php
<?php

declare(strict_types=1);

use Flytachi\Winter\Kernel\App\Attribute\EnableWeb;
use Flytachi\Winter\Kernel\WinterApplication;

require __DIR__ . '/vendor/autoload.php';

#[EnableWeb]
final class Application extends WinterApplication
{
  public static function main(array $argv): never
  {
      parent::run($argv);
  }
}

Хуков, которые нужно переопределять, здесь нет — всё остальное живёт в обычных классах, которые находит сканер. Что можно объявить помимо #[EnableWeb] — на странице Состав приложения.

Каталог этого файла становится корнем проекта: от него отсчитываются .env, storage/, resources/ и начало обхода файлов.

4. Файл запуска — call

Через него идут все команды, включая запуск сервера:

call
#!/usr/bin/env php
<?php

if (PHP_VERSION_ID < 80400) {
  echo "Please use PHP version 8.4 or higher. Current: " . PHP_VERSION . "\n";
  exit(1);
}

chdir(__DIR__);
require './bootstrap.php';

Application::main($argv);
bash
chmod +x call

chdir() здесь обязателен: он привязывает относительные пути — .env, storage/, resources/ — к каталогу проекта, а не к тому, откуда вы вызвали команду.

5. Окружение и каталоги

bash
php call cfg init       # .env из шаблона + свежий WINTER_KEY
php call storage init   # служебные каталоги внутри storage/

Получившийся .env минимален:

.env
WINTER_KEY=<сгенерированный ключ>
TIME_ZONE=UTC
DEBUG=true

Остальные переменные — база, логи, параметры сервера — добавляются по мере надобности, см. Конфигурацию.

6. Первый контроллер

bash
php call make -c .Main   # → main/MainController.php

Генератор создаёт рабочую заготовку: метод hello() с атрибутом #[RequestMapping] без аргументов. Такой атрибут монтирует метод по имени класса и отвечает на все основные HTTP-методы — проверить можно, не открывая файл:

bash
php call mapping show
text
 | [ Routes (5) ]
|	 GET     /main                                 → Main\MainController::hello
|	 POST    /main                                 → Main\MainController::hello
|	 PUT     /main                                 → Main\MainController::hello
|	 PATCH   /main                                 → Main\MainController::hello
|	 DELETE  /main                                 → Main\MainController::hello
| [ Routes ]

Что получилось

text
my-app/
├── bootstrap.php     — класс приложения: из чего оно состоит
├── call              — точка входа для всех команд
├── composer.json     — автозагрузка и зависимости
├── .env              — окружение
├── main/             — ваш код
└── storage/          — служебные каталоги

Каталог resources/ для шаблонов и переводов появится, когда понадобится. Что за что отвечает — Структура проекта.

Первый запуск

bash
php call run dev

Сервер слушает порт 8000 на всех интерфейсах.

Открывать нужно /main, а не /

Корень / не отвечает, пока вы сами не объявите там маршрут, — на него приходит честный 404 Not Found [ GET / ]. Сгенерированный контроллер живёт по адресу http://localhost:8000/main; какие пути заняты, всегда показывает php call mapping show.

Слово dev включает наблюдение за файлами: при изменении любого .php приложение перезапускается само. В рабочем режиме запускают без него — php call run.

Адрес и порт переопределяются флагами:

bash
php call run dev --port=9000
php call run dev --host=127.0.0.1 --port=9000   # только локально

Что делает cfg init

Команда одна, а действий несколько — их стоит знать, потому что одно из них необратимое.

Действие Подробности
Приводит composer.json в порядок name → project/<каталог>, description → My Project <каталог>, удаляет keywords, scripts, чистит authors
Создаёт .env Из шаблона, если файла ещё нет; существующий не трогает
Генерирует WINTER_KEY Каждый раз заново, поверх текущего
Кладёт файл подсказок для PhpStorm vendor/.phpstorm.meta/.phpstorm.meta.php

На существующем проекте cfg init не запускают

Ключ перевыпускается безусловно, а WINTER_KEY подписывает данные, которые ядро передаёт дочерним процессам. Процессы и демоны, запущенные со старым ключом, после смены не пройдут проверку подписи.

Нужны отдельные шаги — берите отдельные команды: cfg env -i создаст .env, cfg key -g перевыпустит ключ осознанно.

Склонировали существующий проект

После git clone каркас уже есть, но всё, что не попадает в репозиторий, нужно создать заново:

bash
composer install

php call cfg env -i       # создать .env, если его нет
php call cfg key -g       # сгенерировать свой WINTER_KEY
php call storage init     # создать каталоги внутри storage/

php call run dev

Ключ у каждой установки свой

WINTER_KEY не переезжает из чужого проекта или из репозитория — генерируйте его на месте. Файл .env по той же причине не коммитится.

Право на исполнение у call хранится в самом репозитории, так что chmod +x обычно не нужен. Если файл всё же пришёл без него — например, через архив, — верните бит: chmod +x call.

Пакеты по надобности

В ядре нет ни слоя базы данных, ни клиента Redis: они живут отдельными пакетами и ставятся, когда нужны. Ядро подхватывает их само — ничего включать не требуется.

bash
composer require flytachi/winter-ppa      # база: репозитории, сущности, миграции
composer require flytachi/winter-redis    # Redis: сторы, хеши, списки, стримы
composer require flytachi/jwt             # JWT и JWKS

Пока пакет не установлен, команды, которым он нужен, не падают со стеком, а объясняют, чего не хватает:

text
 | [!] The 'db' command needs the database layer, which is not installed.
| [i] Add it with:  composer require flytachi/winter-ppa

Что дальше — PPA, Redis, Экосистема.

Что ещё пригодится сразу

Автодополнение в терминале — подсказки по командам и их аргументам:

bash
php call cfg completion -i

Конфигурация Docker — Dockerfile, docker-compose.yml и каталог docker/ с точкой входа под Swoole:

bash
php call cfg docker

Режим выбирается переменной DEV, и по умолчанию она выключена:

bash
docker compose up            # рабочий режим
DEV=true docker compose up   # разработка: перезапуск при изменении файлов

Дальше