- Add SendSmsMessage class for encapsulating SMS message data. - Create KavehNegarProvider and RanginehProvider classes implementing SmsProviderInterface for sending SMS. - Implement SmsLogRepository and SmsTemplateRepository for managing SMS logs and templates. - Develop SendSmsHandler for handling SMS sending messages. - Create SmsService to manage SMS dispatching and logging. - Add UserProfileController for managing user profiles with CRUD operations. - Implement UserProfile entity and repository for user profile data management. - Update symfony.lock and bootstrap.php for project dependencies and environment setup.
4.6 KiB
4.6 KiB
نکات پیادهسازی — تسک ۰۴: ماژول بلاگ
نگاشت فیلدهای Request → Response (مهم!)
در Drupal نام فیلدهای ارسالی با نام فیلدهای دریافتی متفاوت است:
| فیلد در Request | فیلد در Response | توضیح |
|---|---|---|
label |
title |
عنوان مقاله |
description (string) |
body: {value, format} |
متن مقاله — در response به object تبدیل میشود |
field_image: [{target_id}] |
images: [{url, fid, filename, filemime, filesize}] |
تصاویر — ID ارسال، object دریافت |
| — | author |
نام نویسنده (computed از realname کاربر) |
| — | uuid |
شناسه یکتا |
| — | status |
وضعیت انتشار (string: "1") |
| — | created / changed |
Unix timestamp به صورت string |
فرمت واقعی Response بلاگ (از سرور Drupal — endpoint 93)
{
"uuid": "95f6acb0-3331-4141-801e-004e8460edac",
"title": "روش های خانگی محافظت از پوست در تابستان",
"status": "1",
"body": {
"value": "متن کامل مقاله...",
"format": "full_html"
},
"created": "1763536163",
"changed": "1763537699",
"author": "single doctor",
"images": [
{
"url": "https://domain.com/sites/default/files/blog/image.png",
"fid": "97",
"filename": "image.png",
"filemime": "image/png",
"filesize": 320787
}
],
"tag": [
{
"uuid": "24926497-fc2d-47d7-82ae-26cbbc4d6468",
"id": "2501",
"name": "مجله"
},
{
"uuid": "6c6a488b-1051-43a2-887b-0ec7a05e52d5",
"id": "2500",
"name": "سلامتی"
}
]
}
نکات مهم response:
bodyیک object است با کلیدهایvalueوformat— نه string ساده!formatمعمولاً"full_html"یا"basic_html"استauthorازrealnameکاربر نویسنده computed میشودcreatedوchangedبه صورت string برگردانده میشوند (نه integer)statusبه صورت string"1"برگردانده میشود (نه boolean)imagesوtagممکن است آرایه خالی[]باشند- response دارای
idنیست — فقطuuid
فرمت Request ایجاد/ویرایش بلاگ
POST /api/v1/blog/
{
"label": "عنوان مقاله",
"description": "متن کامل مقاله...",
"field_image": [
{ "target_id": 97 },
{ "target_id": 98 }
]
}
PATCH /api/v1/blog/{uuid}
{
"label": "عنوان ویرایششده",
"description": "متن ویرایششده"
}
آپلود تصویر بلاگ (endpoint 99)
قبل از ایجاد بلاگ، تصویر باید آپلود شود و fid آن در field_image استفاده شود:
POST /file/upload/blog/blog/field_image
Headers:
Content-Type: application/octet-stream
Content-Disposition: file; filename="image.png"
X-CSRF-Token: {token}
Authorization: Bearer {token}
Response → fid که در field_image استفاده میشود
تولید Slug
- از عنوان فارسی slug تولید کن
- پکیج
cocur/slugifyرا نصب کن:ddev composer require cocur/slugify - اگر slug تکراری بود، عدد به انتهای آن اضافه کن:
rahnamai-diabet-2
بلاگهای برتر (Top Blogs)
- endpoint:
GET /api/v1/blogs/top(نیاز به auth دارد) - پاسخ: آرایه مستقیم (نه object با pagination) از بلاگهایی که
is_top = 1هستند - فرمت هر آیتم دقیقاً مشابه response معمولی بلاگ است
لیست بلاگها با فیلتر
GET /api/v1/blogs?page=1&limit=10&title=نشانه&tag=3637
title: جستجو در عنوانtag: فیلتر بر اساس ID تگ
Pagination
$offset = ($page - 1) * $limit;
// در Repository با limit/offset
مجوزها
POST → احراز هویت الزامی (ROLE_DOCTOR یا ROLE_ADMIN)
PATCH → احراز هویت الزامی (owner یا ROLE_ADMIN)
DELETE → احراز هویت الزامی (owner یا ROLE_ADMIN)
GET → عمومی (بدون auth)
GET /api/v1/blogs/top → احراز هویت الزامی
بهینهسازی
- view_count با یک query atomic آپدیت کن تا race condition نباشد:
$this->em->createQuery('UPDATE Blog b SET b.viewCount = b.viewCount + 1 WHERE b.id = :id') ->setParameter('id', $blog->getId()) ->execute();