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

Быстрый старт

Соберём первый маршрут от начала до видимого результата: создадим проект, добавим контроллер, поднимем сервер и получим JSON-ответ. Займёт пять минут.

1. Проект

bash
composer create-project flytachi/winter my-app
cd my-app

Composer сам создаст каталоги и .env. Требования и сборка вручную — на странице Установка.

2. Контроллер

Сгенерируем контроллер командой make. Точка перед именем обязательна, суффикс Controller генератор добавит сам:

bash
php call make -c .Greet   # → main/GreetController.php

Файл появится и сразу подключится к автозагрузке. Приведём его к такому виду — маршрут GET /api/hello/{name}, возвращающий JSON:

main/GreetController.php
<?php

namespace Main;

use Flytachi\Winter\Kernel\Http\Request\Annotation\PathVariable;
use Flytachi\Winter\Kernel\Http\Response\ResponseEntity;
use Flytachi\Winter\Kernel\Http\Stereotype\Controller;
use Flytachi\Winter\Kernel\Route\Annotation\GetMapping;
use Flytachi\Winter\Kernel\Route\Annotation\RequestMapping;

#[RequestMapping('api')]
class GreetController extends Controller
{
  #[GetMapping('hello/{name}')]
  public function hello(#[PathVariable] string $name): ResponseEntity
  {
      return ResponseEntity::ok(['message' => "Hello, {$name}"]);
  }
}

Что здесь происходит:

  • #[RequestMapping('api')] на классе — общий префикс /api для всех методов.
  • #[GetMapping('hello/{name}')] — маршрут GET /api/hello/{name}.
  • #[PathVariable] привязывает сегмент {name} к аргументу $name.
  • ResponseEntity::ok([...]) отдаёт 200 с телом в JSON.

Регистрировать маршрут нигде не нужно — сканер найдёт его сам.

3. Запуск

bash
php call run dev

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

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

4. Результат

bash
curl http://localhost:8000/api/hello/Winter
json
{"message":"Hello, Winter"}

Тот же адрес можно открыть в браузере — увидите тот же JSON.

Маршрут не найден?

Посмотрите, что зарегистрировалось:

php call mapping show

Если вашего маршрута в списке нет — контроллер не попал в скан. Проверьте, что файл лежит не в resources/ и не в storage/ (эти каталоги исключены), класс не абстрактный, а метод объявлен public.

5. Чуть больше: параметр запроса

Добавим необязательный ?shout=true:

main/GreetController.php
#[GetMapping('hello/{name}')]
public function hello(
  #[PathVariable] string $name,
  #[RequestParam]  bool  $shout = false,
): ResponseEntity {
  $message = "Hello, {$name}";

  return ResponseEntity::ok(['message' => $shout ? strtoupper($message) : $message]);
}
bash
curl 'http://localhost:8000/api/hello/Winter?shout=true'
json
{"message":"HELLO, WINTER"}

Не забудьте импорт: use Flytachi\Winter\Kernel\Http\Request\Annotation\RequestParam;

Значение по умолчанию делает параметр необязательным — без него запрос без ?shout вернул бы 400.

`#[RequestParam]`, а не `#[RequestQuery]`

Для одного значения из строки запроса нужен #[RequestParam]. Похожий по имени #[RequestQuery] собирает всю строку запроса в объект или массив, и на скаляре он даёт 500, а не 400 — ошибку конфигурации, а не данных.

Оба разобраны на странице Запросы и привязка параметров.

Весь код целиком

main/GreetController.php
<?php

namespace Main;

use Flytachi\Winter\Kernel\Http\Request\Annotation\PathVariable;
use Flytachi\Winter\Kernel\Http\Request\Annotation\RequestParam;
use Flytachi\Winter\Kernel\Http\Response\ResponseEntity;
use Flytachi\Winter\Kernel\Http\Stereotype\Controller;
use Flytachi\Winter\Kernel\Route\Annotation\GetMapping;
use Flytachi\Winter\Kernel\Route\Annotation\RequestMapping;

#[RequestMapping('api')]
class GreetController extends Controller
{
  #[GetMapping('hello/{name}')]
  public function hello(
      #[PathVariable] string $name,
      #[RequestParam]  bool  $shout = false,
  ): ResponseEntity {
      $message = "Hello, {$name}";

      return ResponseEntity::ok(['message' => $shout ? strtoupper($message) : $message]);
  }
}

Дальше

Отсюда есть два пути — вглубь практики или вширь по устройству.

Строить дальше:

Разобраться в устройстве: