# افزودن فیلد شبکه‌های اجتماعی به Doctor ## پروژه `clinicpro` (Backend) — این تغییر پیش‌نیاز پرامپت همتا در frontend است: `nobat724_front/.claude/prompt/doctor-seo-schema-knowledge-panel.md`. آن پرامپت برای Knowledge Panel گوگل به `sameAs` در JSON-LD نیاز دارد که باید از همین فیلد جدید پر شود. ## زمینه برای فعال‌سازی Knowledge Panel گوگل برای صفحه‌ی هر پزشک (هدف نهایی در `nobat724_front`)، schema.org نیاز به آرایه‌ی `sameAs` دارد که لینک پروفایل‌های شبکه‌های اجتماعی پزشک (اینستاگرام، تلگرام، آپارات، یوتیوب، لینکدین) را به گوگل معرفی می‌کند. بررسی `src/Doctor/Entity/Doctor.php` و `docs/api/doctor.md` نشان داد این داده هیچ‌جا در API موجود نیست — نه در پاسخ `GET /api/v1/doctor/{uuid}` و نه در فرم ادمین (`assets/admin/pages/DoctorFormPage.tsx`). نکته‌ی مهم: برخلاف انتظار اولیه، `DoctorAddress` (`src/Doctor/Entity/DoctorAddress.php`) از قبل `latitude`/`longitude` دارد و در `toArray()` به‌صورت `map: { latitude, longitude }` برمی‌گرداند — یعنی GeoCoordinates برای LocalBusiness schema نیازی به تغییر backend ندارد. فقط شبکه‌های اجتماعی پزشک باقی می‌ماند. ## مشکل / هدف به `Doctor` entity یک فیلد JSON برای ذخیره‌ی لینک شبکه‌های اجتماعی (اینستاگرام، تلگرام، آپارات، یوتیوب، لینکدین، توییتر/X) اضافه شود، در پاسخ API برگردانده شود، و در فرم ادمین برای ویرایش در دسترس باشد. ## فایل‌های مرتبط | فایل | نقش | |------|-----| | `src/Doctor/Entity/Doctor.php` | باید فیلد `socialMedia` (JSON nullable) اضافه شود | | `src/Doctor/Controller/DoctorController.php` | پاسخ `GET /api/v1/doctor/{uuid}` باید `social_media` را برگرداند؛ متد update باید آن را بپذیرد | | `migrations/` | migration جدید برای ستون `social_media` روی جدول `doctors` | | `assets/admin/pages/DoctorFormPage.tsx` | فیلدهای ورودی لینک‌های اجتماعی به فرم اضافه شود | | `assets/admin/types/index.ts` | type پزشک باید `socialMedia` را شامل شود | | `docs/api/doctor.md` | باید فیلد جدید مستند شود | ## وضعیت فعلی `src/Doctor/Entity/Doctor.php` فیلدهای پایه دارد (نام، تخصص، آدرس‌ها) اما هیچ فیلد JSON برای داده‌ی نیمه‌ساخت‌یافته ندارد. الگوی مشابه را می‌توان از `DoctorAddress::toArray()` که `map` را به‌صورت nested object برمی‌گرداند الگو گرفت: ```php // src/Doctor/Entity/DoctorAddress.php — الگوی موجود برای nested object در toArray() 'map' => [ 'latitude' => $this->latitude !== null ? (string) $this->latitude : null, 'longitude' => $this->longitude !== null ? (string) $this->longitude : null, ], ``` ## وظایف ### ۱. افزودن فیلد `socialMedia` به `Doctor` entity ```php // src/Doctor/Entity/Doctor.php #[ORM\Column(name: 'social_media', type: 'json', nullable: true)] private ?array $socialMedia = null; public function getSocialMedia(): ?array { return $this->socialMedia; } public function setSocialMedia(?array $v): self { $this->socialMedia = $v; $this->touch(); return $this; } ``` ساختار JSON ذخیره‌شده: ```json { "instagram": "https://instagram.com/dr.example", "telegram": "https://t.me/dr_example", "aparat": "https://aparat.com/dr.example", "youtube": "https://youtube.com/@dr.example", "linkedin": "https://linkedin.com/in/dr-example" } ``` هر کلید nullable است — پزشک ممکن است فقط بعضی شبکه‌ها را داشته باشد. کلیدهای خالی/null باید در پاسخ API هم `null` بمانند (نه حذف شوند) تا frontend به‌سادگی چک کند. ### ۲. Migration ```bash ddev exec php bin/console doctrine:migrations:diff --no-interaction ddev exec php bin/console doctrine:migrations:migrate --no-interaction ``` ### ۳. بازگرداندن فیلد در پاسخ API در `src/Doctor/Controller/DoctorController.php`، هرجا `toArray()`-مانند برای پزشک ساخته می‌شود (GET تکی، GET لیست)، کلید `social_media` اضافه شود: ```php 'social_media' => $doctor->getSocialMedia(), ``` و در متد update، فیلد جدید از request body خوانده و validate شود (فقط باید URL معتبر یا null باشد برای هر کلید — از `InputValidator` یا یک Assert ساده استفاده کن، الگوی موجود validation در همان کنترلر را دنبال کن). ### ۴. فرم ادمین در `assets/admin/pages/DoctorFormPage.tsx`، یک بخش جدید «شبکه‌های اجتماعی» با ۵ فیلد متنی (اینستاگرام، تلگرام، آپارات، یوتیوب، لینکدین) اضافه شود. الگوی `Field()` موجود در همین فایل (خط ۵۲) را برای ساخت input استفاده کن. مقدار اولیه از `doctor.socialMedia` پر شود، در submit به همان شکل JSON ارسال شود. در `assets/admin/types/index.ts`، interface پزشک باید شامل شود: ```ts socialMedia?: { instagram?: string | null; telegram?: string | null; aparat?: string | null; youtube?: string | null; linkedin?: string | null; } | null; ``` ## نکات مهم - این فیلد باید **nullable** کامل باشد — پزشکانی که شبکه اجتماعی ندارند نباید خطا بگیرند. - مقادیر باید URL کامل (با `https://`) ذخیره شوند، نه فقط username — frontend مستقیماً این مقدار را در `sameAs` آرایه‌ی JSON-LD قرار می‌دهد بدون پردازش اضافی. - بعد از این تغییر، `docs/api/doctor.md` را طبق قانون پروژه (به‌روزرسانی مستندات هم‌زمان با تغییر API) ویرایش کن — هم در نمونه‌ی JSON پاسخ `GET /api/v1/doctor/{uuid}` و هم در بخش فیلدهای قابل ویرایش. - migration را قبل از merge باید روی دیتابیس dev واقعی تست کنی (`ddev exec php bin/console doctrine:migrations:migrate --no-interaction`).