Signal: از اتریبیوتهای PHP مستند بساز
خلاصهٔ کاملتر
Signal یه کتابخونهٔ PHP از استیو مکداگال ـه که اتریبیوتهایی که روی کلاسها و متدهات میذاری رو میخونه و ازشون مستندات تولید میکنه. به گفتهٔ نویسندهٔ مقاله، ایدهٔ اصلی اینه که مرجع API دقیقاً کنار کدی بمونه که توصیفش میکنه؛ اینطوری مستند همراه کد تغییر میکنه و توی یه فایل جدا بیات نمیشه. برای اجرا به PHP 8.5 و Symfony Console نیاز داره و با لایسنس MIT منتشر شده.
درمجموع ۲۴ اتریبیوت داره که تو سه گروه تقسیم شدن: اونایی که میگن کلاس چیه، اونایی که رابطه و وضعیت کلاس رو ثبت میکنن، و اونایی که تکتک متدها رو مستند میکنن. کارت اینه که کد رو annotate کنی، یه دستور بزنی و خروجی Markdown (برای آدم) و JSON (برای ابزار) تحویل بگیری.
گروه اول ۱۳ اتریبیوته که نقش کلاس رو تو معماری اپ مشخص میکنه: #[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] یه همکار (dependency) رو ثبت میکنه، #[ListensTo] یه listener رو به ایونتش گره میزنه، و #[Deprecated] و #[Internal] هم کلاسهایی رو علامت میزنن که مصرفکننده باید باهاشون محتاط باشه. نکتهٔ مقاله اینه که این روابط معمولاً یا تو ذهن یه نفره یا تو نموداری که هیچوقت آپدیت نمیشه؛ گذاشتنشون کنار کلاس، صادق نگهشون میداره.
گروه سوم سراغ متدها میره: #[Route] متد و مسیر HTTP رو ثبت میکنه، #[Authorize] دسترسی لازم رو، #[Validates] قوانین اعتبارسنجی رو فیلد به فیلد، و #[Cached] هم TTL رو. سهتای دیگه چیزهایی رو مستند میکنن که از امضای متد پیدا نیست: #[Emits] برای ایونتهایی که متد dispatch میکنه، #[Throws] برای استثناهایی که ممکنه پرتاب کنه، و #[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.json تو ریشهٔ پروژه خونده میشه: کدوم دایرکتوری اسکن بشه، چه فرمتهایی نوشته بشه (markdown و json)، خروجی کجا بره و چه مسیرهایی نادیده گرفته بشه. بعدش دستور php vendor/bin/signal generate مستندات رو میسازه و با composer require juststeveking/signal هم نصب میشه. خروجی Markdown با فهرست مطالب و بر اساس نوع کلاس مرتب میشه و خروجی JSON همون متادیتا رو به شکلی میده که ابزارهای دیگه بخونن — نقطهٔ شروع خوبی برای ساختن توضیح OpenAPI یا یه کاتالوگ سرویس داخلی.
نکات کلیدی:
- Signal اتریبیوتهای PHP رو میخونه و ازشون مستند تولید میکنه؛ مستند کنار کد میمونه و بیات نمیشه
- ۲۴ اتریبیوت در سه گروه: نقش کلاس، رابطه/وضعیت، و مستندسازی متد
- #[SideEffect]، #[Throws] و #[Emits] چیزهایی رو ثبت میکنن که از امضای متد پیدا نیست
- تنظیمات از signal.json خونده میشه و خروجی هم Markdown هم JSON ـه
- نیازمندی: PHP 8.5 و Symfony Console؛ لایسنس MIT




