Signal - це PHP-бібліотека від Стіва Макдугала, яка зчитує атрибути, розміщені на класах і методах, і генерує з них документацію. Ідея полягає в тому, щоб тримати API-довідку в тому самому місці, де знаходиться код, який вона описує. Так документація змінюється разом із кодом замість того, щоб застарівати в окремому файлі. Бібліотека вимагає PHP 8.5 та Symfony Console і розповсюджується під ліцензією MIT.
Бібліотека постачається з 24 атрибутами, розділеними на три групи: атрибути, що позначають тип класу, атрибути, які фіксують зв'язки та статус класу, та атрибути для документування окремих методів. Ви анотуєте свій код, запускаєте одну команду й отримуєте Markdown для людей та JSON для інструментів.
Позначення типу класу
Перша група атрибутів описує роль, яку клас виконує у вашому застосунку. Їх 13, і вони охоплюють поширені будівельні блоки: #[Module], #[Service], #[Repository], #[Action], #[Controller], #[Event], #[Listener], #[Middleware], #[Job], #[Command], #[Query], #[Aggregate] та #[ValueObject]. Кожен приймає необов'язковий опис і список тегів:
use JustSteveKing\Signal\Attributes\Service;
#[Service(
description: 'Issues and revokes API tokens for authenticated users',
tags: ['auth', 'tokens'],
)]
final class TokenService
{
// ...
}
Коли Signal генерує вихідні дані, він групує класи за цими типами, тому всі контролери потрапляють в один розділ, а всі сервіси - в інший.
Фіксація зв'язків і статусу
Друга група документує, як клас пов'язаний з рештою системи і на якому етапі життєвого циклу він знаходиться. #[DependsOn] фіксує співробітника (collaborator), #[ListensTo] прив'язує слухача до події, а #[Deprecated] і #[Internal] позначають класи, до яких викликачі повинні ставитись обережно:
use JustSteveKing\Signal\Attributes\Listener;
use JustSteveKing\Signal\Attributes\ListensTo;
use JustSteveKing\Signal\Attributes\DependsOn;
#[Listener(description: 'Sends a welcome email after registration')]
#[ListensTo(event: UserRegistered::class)]
#[DependsOn(class: MailService::class)]
final class SendWelcomeEmail
{
// ...
}
Ці зв'язки - той тип деталей, який зазвичай зберігається в чиїйсь голові або на діаграмі, яку ніхто не оновлює. Розміщення їх поруч із класом робить їх достовірними.
Документування методів
Третя група описує, що роблять окремі методи. #[Route] фіксує HTTP-метод і шлях, #[Authorize] вказує на здатність (ability), яка потрібна викликачу, #[Validates] захоплює правила валідації поле за полем, а #[Cached] записує TTL. Ще три атрибути документують поведінку, яку сама сигнатура методу не розкриває: #[Emits] для подій, які метод відправляє, #[Throws] для винятків, які він може викинути, та #[SideEffect] для помітної роботи на кшталт відправки пошти або запису в чергу.
use JustSteveKing\Signal\Attributes\Route;
use JustSteveKing\Signal\Attributes\Authorize;
use JustSteveKing\Signal\Attributes\Validates;
use JustSteveKing\Signal\Attributes\Emits;
use JustSteveKing\Signal\Attributes\Throws;
use JustSteveKing\Signal\Attributes\SideEffect;
#[Route(method: 'POST', path: '/api/subscriptions', description: 'Start a subscription')]
#[Authorize(ability: 'subscriptions.create')]
#[Validates(field: 'plan', rules: 'required|in:monthly,yearly')]
#[Emits(event: 'SubscriptionStarted')]
#[SideEffect(description: 'Charges the customer through the payment gateway', tags: ['billing'])]
#[Throws(exception: PaymentFailedException::class, description: 'If the gateway rejects the charge')]
public function store(Request $request): JsonResponse
{
// ...
}
Атрибути #[SideEffect] і #[Throws] варто виділити окремо, бо вони документують речі, які читач не може вивести з типу повернення. Знання про те, що метод списує кошти з картки або може викинути PaymentFailedException, - це той тип фактів, який інакше проявляється лише тоді, коли щось ламається.
Конфігурація та вихідні дані
Signal зчитує файл signal.json у корені вашого проекту. Він вказує генератору, яку директорію сканувати, які формати писати, куди їх розміщувати і які шляхи пропускати:
{
"input": "src/",
"output": {
"format": ["markdown", "json"],
"path": "docs/"
},
"exclude": [
"src/Attributes/"
]
}
Маючи це налаштування, одна команда генерує документацію:
php vendor/bin/signal generate
Вихідний Markdown організовано за типом класу зі змістом, а JSON містить ті самі метадані у формі, яку можуть читати інші інструменти. Це робить його відправною точкою для таких речей, як генерація OpenAPI-опису або живлення внутрішнього каталогу сервісів.
Встановлення
Встановіть бібліотеку через Composer:
composer require juststeveking/signal
Ви можете ознайомитись із вихідним кодом і повним списком атрибутів на GitHub.