Add seed script for populating database with initial data

- Implemented a comprehensive PHP script to seed the database with test data for users, doctors, clinics, appointments, payments, ratings, comments, and blogs.
- Included functions for generating random data such as UUIDs, mobile numbers, and images.
- Downloaded and stored images for doctors and clinics using parallel curl requests.
- Inserted static data for insurances, patients, and doctors with various attributes including specialties and services.
- Ensured data integrity by disabling foreign key checks during the seeding process and re-enabling them afterward.
- Provided a summary of the total records inserted into each table at the end of the script.
This commit is contained in:
hamed
2026-06-10 15:06:37 +03:30
parent de702d78bd
commit 28dbfa67e2
3 changed files with 1316 additions and 0 deletions
+482
View File
@@ -0,0 +1,482 @@
<?php
declare(strict_types=1);
$pdo = new PDO('mysql:host=db;dbname=db;charset=utf8mb4', 'db', 'db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES utf8mb4');
$pdo->exec('SET FOREIGN_KEY_CHECKS = 0');
$now = time();
// ── Helpers ───────────────────────────────────────────────────────────────────
function uuid(): string {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff));
}
function rand_item(array $arr) { return $arr[array_rand($arr)]; }
function rand_items(array $arr, int $min, int $max): array {
$count = rand($min, $max);
$keys = (array) array_rand($arr, min($count, count($arr)));
return array_map(fn($k) => $arr[$k], $keys);
}
function mobile(): string {
$prefix = rand_item(['0910','0911','0912','0913','0914','0915','0916','0917','0918','0919',
'0930','0933','0935','0936','0937','0938','0939','0901','0902','0903',
'0920','0921','0922','0991','0992','0993','0994']);
return $prefix . str_pad((string)rand(1000000, 9999999), 7, '0', STR_PAD_LEFT);
}
function nationalCode(): string {
return str_pad((string)rand(1000000000, 9999999999), 10, '0', STR_PAD_LEFT);
}
function medicalCode(): string {
return (string)rand(10000000, 99999999);
}
function passwordHash(): string {
return '$2y$13$' . substr(base64_encode(random_bytes(32)), 0, 53);
}
// ── Static data ───────────────────────────────────────────────────────────────
$maleNames = ['علی','محمد','حسین','احمد','رضا','مهدی','حسن','اکبر','ابراهیم','کریم',
'جواد','امیر','سعید','مجید','فرید','کامران','سیاوش','داریوش','پرویز','شهرام',
'بهرام','فرهاد','نادر','مسعود','وحید','یاسر','حامد','سجاد','ایمان','میثم',
'آرش','آرمان','آرمین','پدرام','پویا','کیان','سیروس','بابک','فریبرز','هوشنگ'];
$femaleNames = ['فاطمه','زهرا','مریم','سارا','نرگس','لیلا','نازنین','مهناز','شیرین','پروین',
'ملیحه','الناز','آتنا','باران','ترانه','دلارام','رویا','شادی','گلناز','ماهرخ',
'ندا','نیلوفر','هانیه','یاسمن','زینب','حدیثه','سمیه','طاهره','عاطفه','منیژه'];
$lastNames = ['احمدی','محمدی','رضایی','حسینی','موسوی','جعفری','کریمی','نوری','صادقی','قاسمی',
'عباسی','میرزایی','رحیمی','اکبری','یوسفی','حیدری','طاهری','نصیری','سلیمانی','زارعی',
'مرادی','شریفی','منصوری','ذبیحی','تهرانی','اصفهانی','مشهدی','شیرازی','تبریزی','همدانی',
'ملکی','درویشی','امیری','نجفی','شاهی','بهرامی','خسروی','گلمحمدی','فدایی','ولیپور',
'نظری','فروزان','پورعلی','دهقانی','صالحی','ربیعی','مجیدی','سبحانی','زمانی','بهشتی'];
$degrees = ['متخصص','فوق تخصص','دکترای عمومی','فلوشیپ','استادیار','دانشیار','پروفسور'];
$genders = ['male','female'];
$bios = [
'دارای بیش از ۱۵ سال سابقه در حوزه تخصصی خود، عضو انجمن پزشکی ایران.',
'فارغ‌التحصیل دانشگاه علوم پزشکی تهران، دارای تجربه کار در بیمارستان‌های معتبر.',
'متخصص با سابقه درخشان در درمان بیماران، ارائه خدمات با بالاترین کیفیت.',
'عضو هیئت علمی دانشگاه و مشاور پزشکی با بیش از ۱۰ سال تجربه بالینی.',
'دارای گواهینامه‌های تخصصی از مراکز بین‌المللی، آشنا با جدیدترین روش‌های درمانی.',
'پزشک باتجربه با رویکرد جامع در درمان، اعتقاد به طب پیشگیری و توانبخشی.',
'متعهد به ارائه بهترین مراقبت‌های پزشکی با رعایت اصول اخلاق پزشکی.',
'دارای مدرک تخصصی از اروپا، تجربه کار در مراکز درمانی پیشرفته.',
];
$clinicNames = ['کلینیک تخصصی','مرکز درمانی','بیمارستان','کلینیک جامع','مرکز مشاوره پزشکی',
'مطب دکتر','کلینیک ویژه','مرکز پزشکی','درمانگاه','کلینیک سلامت'];
$clinicSuffixes = ['امید','نوین','رازی','ابن سینا','سینا','شفا','سلامت','آریا','پارس','ایران','مهر','صبا'];
$appointmentStatuses = ['reserved','visited','completed','cancelled_by_user','cancelled_by_doctor','no_show'];
$appointmentStatusWeights = [30,25,25,10,5,5]; // percent chance
$paymentStatuses = ['paid','pending','failed'];
$commentTexts = [
'دکتر بسیار خوب و دلسوزی هستند. توضیحات کاملی دادند.',
'معاینه دقیق بود و تشخیص درست. ممنونم.',
'وقت انتظار کمی داشتم، دکتر سر وقت حاضر بود.',
'بسیار متبحر و با حوصله. مشکلم کاملاً حل شد.',
'توصیه می‌کنم. رفتار بسیار حرفه‌ای دارند.',
'دکتر خوبی هستند ولی وقت ویزیت کمی کوتاه بود.',
'راضی بودم از ویزیت. درمان موثر بود.',
'یکی از بهترین دکترهایی که به آنها مراجعه کرده‌ام.',
'کمی منتظر ماندم ولی ارزشش را داشت.',
'متخصص واقعی در حوزه کارشان. توصیه می‌کنم.',
];
$blogTitles = [
'راهنمای جامع برای پیشگیری از بیماری‌های قلبی',
'تغذیه سالم برای کودکان در سنین رشد',
'اهمیت چکاپ منظم سالانه',
'راهکارهای مقابله با استرس و اضطراب',
'علائم هشداردهنده دیابت نوع ۲',
'ورزش و تأثیر آن بر سلامت قلب و عروق',
'خواب کافی و نقش آن در سلامت جسم و روان',
'راهنمای مراقبت از پوست در فصول مختلف',
'پیشگیری از پوکی استخوان با تغذیه مناسب',
'نکات مهم برای مراقبت از بینایی',
'سرطان پستان؛ تشخیص زودهنگام نجات‌بخش است',
'بهداشت دهان و دندان در کودکان',
'فشار خون بالا و روش‌های کنترل آن',
'نقش واکسیناسیون در پیشگیری از بیماری‌ها',
'آرتروز زانو؛ علائم، پیشگیری و درمان',
];
$blogBodies = [
'بیماری‌های قلبی از مهم‌ترین علل مرگ در ایران و جهان هستند. با رعایت سبک زندگی سالم، ترک دخانیات و فعالیت بدنی منظم می‌توان خطر آن را کاهش داد.',
'تغذیه متعادل و سرشار از ویتامین‌ها برای رشد کودکان ضروری است. مصرف میوه، سبزیجات، پروتئین و لبنیات را در برنامه غذایی کودک خود بگنجانید.',
'انجام آزمایش‌های منظم، بررسی فشار خون، قند خون و چکاپ کلی هر سال توصیه می‌شود. تشخیص زودهنگام بیماری‌ها درمان را آسان‌تر می‌کند.',
'مدیریت استرس با تکنیک‌های تنفس عمیق، مدیتیشن و فعالیت بدنی امکان‌پذیر است. در صورت نیاز از مشاور یا روانپزشک کمک بگیرید.',
'دیابت نوع ۲ با علائمی مانند تشنگی زیاد، ادرار مکرر و خستگی مزمن همراه است. کنترل وزن و رژیم غذایی مناسب در پیشگیری از آن نقش دارد.',
];
// ── Load existing data ────────────────────────────────────────────────────────
$provinces = $pdo->query('SELECT id FROM provinces')->fetchAll(PDO::FETCH_COLUMN);
$cities = $pdo->query('SELECT id, province_id FROM cities WHERE id != 600')->fetchAll(PDO::FETCH_ASSOC);
$cityIds = array_column($cities, 'id');
$specialtyParents = $pdo->query('SELECT id FROM specialties WHERE parent_id IS NULL')->fetchAll(PDO::FETCH_COLUMN);
$allSpecialties = $pdo->query('SELECT id FROM specialties')->fetchAll(PDO::FETCH_COLUMN);
$allServices = $pdo->query('SELECT id, specialty_id FROM doctor_services')->fetchAll(PDO::FETCH_ASSOC);
$serviceIds = array_column($allServices, 'id');
// Build specialty->services map
$specialtyServicesMap = [];
foreach ($allServices as $svc) {
if ($svc['specialty_id']) {
$specialtyServicesMap[$svc['specialty_id']][] = $svc['id'];
}
}
$count = 0;
// ── 1. Insurances ─────────────────────────────────────────────────────────────
echo "Inserting insurances...\n";
$basicInsurances = [
['تأمین اجتماعی','basic'],['خدمات درمانی','basic'],['نیروهای مسلح','basic'],
['کمیته امداد','basic'],['بهزیستی','basic'],['روستایی','basic'],
];
$suppInsurances = [
['ایران','supplementary'],['آسیا','supplementary'],['البرز','supplementary'],
['پارسیان','supplementary'],['سامان','supplementary'],['میهن','supplementary'],
['دانا','supplementary'],['رازی','supplementary'],['کوثر','supplementary'],['معلم','supplementary'],
];
$insStmt = $pdo->prepare('INSERT IGNORE INTO insurances (uuid,name,type,status) VALUES (?,?,?,1)');
$insIds = [];
foreach (array_merge($basicInsurances, $suppInsurances) as $ins) {
$insStmt->execute([uuid(), $ins[0], $ins[1]]);
$insIds[] = $pdo->lastInsertId();
$count++;
}
$insIds = array_filter($insIds); // remove zeros from IGNORE
if (empty($insIds)) {
$insIds = $pdo->query('SELECT id FROM insurances')->fetchAll(PDO::FETCH_COLUMN);
}
echo " Insurances: " . count($insIds) . "\n";
// ── 2. Users (patients) ───────────────────────────────────────────────────────
echo "Inserting users (patients)...\n";
$usedMobiles = [];
$patientIds = [];
$uStmt = $pdo->prepare(
'INSERT INTO users (uuid,mobile_number,password_hash,email,real_name,roles,status,created_at,updated_at)
VALUES (?,?,?,?,?,?,1,?,?)'
);
for ($i = 0; $i < 200; $i++) {
$gender = rand_item($genders);
$firstName = $gender === 'male' ? rand_item($maleNames) : rand_item($femaleNames);
$lastName = rand_item($lastNames);
$name = $firstName . ' ' . $lastName;
do { $mobile = mobile(); } while (isset($usedMobiles[$mobile]));
$usedMobiles[$mobile] = true;
$email = strtolower(rand_item(['user','p','pt','patient'])) . $i . '@example.ir';
$ts = $now - rand(86400, 86400 * 365);
$uStmt->execute([uuid(), $mobile, passwordHash(), $email, $name, '["ROLE_USER"]', $ts, $ts]);
$patientIds[] = (int)$pdo->lastInsertId();
$count++;
}
echo " Patients: " . count($patientIds) . "\n";
// ── 3. Doctor users ───────────────────────────────────────────────────────────
echo "Inserting doctors...\n";
$doctorUserIds = [];
$doctorIds = [];
$duStmt = $pdo->prepare(
'INSERT INTO users (uuid,mobile_number,password_hash,email,real_name,roles,status,created_at,updated_at)
VALUES (?,?,?,?,?,?,1,?,?)'
);
$dStmt = $pdo->prepare(
'INSERT INTO doctors (uuid,name,gender,medical_system_code,mobile_number,activity_time,degree,info,
images,doctor_rate,doctor_rate_percentage,active_doctor_appointment,created_at,updated_at,user_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)'
);
for ($i = 0; $i < 60; $i++) {
$gender = $i % 4 === 0 ? 'female' : 'male';
$firstName = $gender === 'male' ? rand_item($maleNames) : rand_item($femaleNames);
$lastName = rand_item($lastNames);
$name = 'دکتر ' . $firstName . ' ' . $lastName;
do { $mobile = mobile(); } while (isset($usedMobiles[$mobile]));
$usedMobiles[$mobile] = true;
$email = 'dr' . $i . '@clinic-pro.ir';
$ts = $now - rand(86400 * 30, 86400 * 730);
$duStmt->execute([uuid(), $mobile, passwordHash(), $email, $name, '["ROLE_USER","ROLE_DOCTOR"]', $ts, $ts]);
$userId = (int)$pdo->lastInsertId();
$doctorUserIds[] = $userId;
$rate = round(rand(35, 50) / 10, 1);
$ratePct = rand(72, 98);
$dStmt->execute([
uuid(), $name, $gender, medicalCode(), $mobile,
rand(5, 25), rand_item($degrees), rand_item($bios),
json_encode([]), $rate, $ratePct, $ts, $ts, $userId
]);
$doctorIds[] = (int)$pdo->lastInsertId();
$count += 2;
}
echo " Doctors: " . count($doctorIds) . "\n";
// ── 4. Doctor specialties & services ─────────────────────────────────────────
echo "Linking doctor specialties/services...\n";
$dsStmt = $pdo->prepare('INSERT IGNORE INTO doctor_specialties (doctor_id,specialty_id) VALUES (?,?)');
$deStmt = $pdo->prepare('INSERT IGNORE INTO doctor_expertise (doctor_id,service_id) VALUES (?,?)');
$dpStmt = $pdo->prepare('INSERT IGNORE INTO doctor_provinces (doctor_id,province_id) VALUES (?,?)');
$dcStmt = $pdo->prepare('INSERT IGNORE INTO doctor_cities (doctor_id,city_id) VALUES (?,?)');
$daStmt = $pdo->prepare(
'INSERT INTO doctor_addresses (uuid,name,address,telephone,latitude,longitude,created_at,updated_at,doctor_id,city_id,province_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?)'
);
$cityProvinceMap = array_column($cities, 'province_id', 'id');
$streetNames = ['خیابان ولیعصر','خیابان انقلاب','خیابان آزادی','بلوار کشاورز','خیابان شریعتی',
'خیابان مطهری','خیابان فردوسی','خیابان پاسداران','خیابان جمهوری','خیابان امام خمینی'];
$buildingDescs = ['ساختمان پزشکان','برج طبی','مجتمع پزشکی','کلینیک ویژه','مطب','مرکز درمانی'];
foreach ($doctorIds as $idx => $doctorId) {
// 1-2 specialties per doctor
$numSpec = rand(1, 2);
$chosenParents = (array)array_rand(array_flip($specialtyParents), min($numSpec, count($specialtyParents)));
foreach ($chosenParents as $specId) {
$dsStmt->execute([$doctorId, $specId]);
$count++;
// Add 2-5 child specialties under same parent if exist
$children = array_values(array_filter($allSpecialties, fn($s) => !in_array($s, $specialtyParents)));
foreach (array_slice($children, 0, rand(2, 5)) as $cs) {
$dsStmt->execute([$doctorId, $cs]);
$count++;
}
// Services for this specialty
$svcPool = $specialtyServicesMap[$specId] ?? array_slice($serviceIds, 0, 10);
foreach (rand_items($svcPool, 3, 8) as $svcId) {
$deStmt->execute([$doctorId, $svcId]);
$count++;
}
}
// 1-3 cities per doctor
$chosenCities = rand_items($cityIds, 1, 3);
foreach ($chosenCities as $cityId) {
$provId = $cityProvinceMap[$cityId] ?? null;
$dcStmt->execute([$doctorId, $cityId]);
if ($provId) $dpStmt->execute([$doctorId, $provId]);
$count += $provId ? 2 : 1;
// Doctor address for each city
$street = rand_item($streetNames);
$building = rand_item($buildingDescs);
$no = rand(1, 200);
$address = 'تهران، ' . $street . '، پلاک ' . $no . '، ' . $building;
$lat = 33.0 + (rand(0, 700) / 100);
$lon = 48.0 + (rand(0, 1500) / 100);
$tel = '0' . rand_item(['21','511','411','31','71','81','351','44']) . rand(10000000, 99999999);
$ts = $now - rand(86400, 86400 * 180);
$daStmt->execute([uuid(), 'مطب شماره ' . ($idx+1), $address, $tel, $lat, $lon, $ts, $ts, $doctorId, $cityId, $provId]);
$count++;
}
}
// ── 5. Clinics ────────────────────────────────────────────────────────────────
echo "Inserting clinics...\n";
$clinicIds = [];
$clStmt = $pdo->prepare(
'INSERT INTO clinics (uuid,name,info,address,telephone,is_24_7,working_days,latitude,longitude,
city_id,province_id,images_clinic,clinic_logo,created_at,updated_at,user_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'
);
$clDStmt = $pdo->prepare('INSERT IGNORE INTO clinic_doctors (clinic_id,doctor_id) VALUES (?,?)');
$clSpStmt = $pdo->prepare('INSERT IGNORE INTO clinic_specialties (clinic_id,specialty_id) VALUES (?,?)');
$clSvStmt = $pdo->prepare('INSERT IGNORE INTO clinic_services (clinic_id,service_id) VALUES (?,?)');
$clInStmt = $pdo->prepare('INSERT IGNORE INTO clinic_insurances (clinic_id,insurance_id) VALUES (?,?)');
$workingDays = ['شنبه تا چهارشنبه ۸ تا ۲۰','شنبه تا پنجشنبه ۸ تا ۱۸','یک‌شنبه تا پنجشنبه ۹ تا ۱۷',
'شنبه تا سه‌شنبه ۷ تا ۱۹','همه روزه ۸ تا ۲۲','شنبه تا چهارشنبه ۹ تا ۲۰'];
$shuffledDoctors = $doctorIds;
shuffle($shuffledDoctors);
for ($i = 0; $i < 30; $i++) {
$cityRow = rand_item($cities);
$cityId = (int)$cityRow['id'];
$provId = (int)$cityRow['province_id'];
$lat = 33.0 + (rand(0, 700) / 100);
$lon = 48.0 + (rand(0, 1500) / 100);
$is247 = rand(0, 5) === 0 ? 1 : 0;
$name = rand_item($clinicNames) . ' ' . rand_item($clinicSuffixes);
$ts = $now - rand(86400 * 30, 86400 * 365);
$tel = '0' . rand_item(['21','511','411','31','71','81','351','44']) . rand(10000000, 99999999);
$address = rand_item($streetNames) . '، پلاک ' . rand(1,300);
$ownerId = $doctorUserIds[array_rand($doctorUserIds)];
$clStmt->execute([
uuid(), $name, 'ارائه خدمات تخصصی پزشکی با استفاده از جدیدترین تجهیزات.',
$address, $tel, $is247, rand_item($workingDays), $lat, $lon,
$cityId, $provId, json_encode([]), json_encode([]), $ts, $ts, $ownerId
]);
$clinicId = (int)$pdo->lastInsertId();
$clinicIds[] = $clinicId;
$count++;
// 2-4 doctors per clinic
$cDocs = array_splice($shuffledDoctors, 0, rand(2, 4));
if (empty($cDocs)) $cDocs = rand_items($doctorIds, 2, 3);
foreach ($cDocs as $dId) {
$clDStmt->execute([$clinicId, $dId]); $count++;
}
// 2-4 specialties
foreach (rand_items($specialtyParents, 2, 4) as $spId) {
$clSpStmt->execute([$clinicId, $spId]); $count++;
}
// 3-6 services
foreach (rand_items($serviceIds, 3, 6) as $svId) {
$clSvStmt->execute([$clinicId, $svId]); $count++;
}
// 3-6 insurances
foreach (rand_items($insIds, 3, 6) as $inId) {
$clInStmt->execute([$clinicId, $inId]); $count++;
}
}
echo " Clinics: " . count($clinicIds) . "\n";
// ── 6. Appointments ───────────────────────────────────────────────────────────
echo "Inserting appointments...\n";
$apptStmt = $pdo->prepare(
'INSERT INTO appointments (uuid,slot_start,slot_end,status,note,created_at,updated_at,doctor_id,user_id)
VALUES (?,?,?,?,?,?,?,?,?)'
);
$apptIds = [];
$apptStatusFinal = [];
// weighted random status
function weightedStatus(array $statuses, array $weights): string {
$total = array_sum($weights);
$r = rand(1, $total);
$cum = 0;
foreach ($statuses as $i => $status) {
$cum += $weights[$i];
if ($r <= $cum) return $status;
}
return $statuses[0];
}
$appointmentStatuses = ['reserved','visited','completed','cancelled_by_user','cancelled_by_doctor','no_show'];
$apptWeights = [20, 25, 30, 10, 8, 7];
for ($i = 0; $i < 500; $i++) {
$doctorId = rand_item($doctorIds);
$userId = rand_item($patientIds);
$status = weightedStatus($appointmentStatuses, $apptWeights);
// Past appointments: visited/completed/cancelled, Future: reserved
if (in_array($status, ['visited','completed','no_show','cancelled_by_user','cancelled_by_doctor'])) {
$slotStart = $now - rand(3600, 86400 * 180);
} else {
$slotStart = $now + rand(3600, 86400 * 30);
}
$slotEnd = $slotStart + 1800; // 30 min
$ts = $slotStart - rand(3600, 86400 * 7);
$notes = ['','مراجعه اول','پیگیری','نوبت اضطراری','مشاوره','کنترل دوره‌ای'];
$apptStmt->execute([uuid(), $slotStart, $slotEnd, $status, rand_item($notes), $ts, $ts, $doctorId, $userId]);
$apptId = (int)$pdo->lastInsertId();
$apptIds[] = $apptId;
$apptStatusFinal[] = $status;
$count++;
}
echo " Appointments: " . count($apptIds) . "\n";
// ── 7. Payments ───────────────────────────────────────────────────────────────
echo "Inserting payments...\n";
$payStmt = $pdo->prepare(
'INSERT INTO payments (uuid,order_id,amount_rials,status,gateway,type,reference_id,created_at,updated_at,user_id,appointment_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?)'
);
$gateways = ['mellat','sep','zarinpal','parsian'];
// Only completed/visited appointments get paid
$paidApptIds = [];
foreach ($apptIds as $k => $apptId) {
if (in_array($apptStatusFinal[$k], ['visited','completed','reserved'])) {
$paidApptIds[] = [$apptId, $k];
}
}
shuffle($paidApptIds);
$paidApptIds = array_slice($paidApptIds, 0, 380);
foreach ($paidApptIds as [$apptId, $k]) {
$status = in_array($apptStatusFinal[$k], ['visited','completed']) ? 'paid' : rand_item(['paid','pending']);
$amount = rand_item([1500000,2000000,2500000,3000000,3500000,4000000,4500000,5000000]);
$userId = rand_item($patientIds);
$ts = $now - rand(3600, 86400 * 180);
$refId = $status === 'paid' ? (string)rand(100000000, 999999999) : null;
$payStmt->execute([
uuid(), 'ORD-' . strtoupper(substr(uuid(), 0, 8)), $amount, $status,
rand_item($gateways), 'appointment', $refId, $ts, $ts, $userId, $apptId
]);
$count++;
}
echo " Payments: " . count($paidApptIds) . "\n";
// ── 8. Rates ──────────────────────────────────────────────────────────────────
echo "Inserting rates...\n";
$rateStmt = $pdo->prepare('INSERT INTO rates (uuid,score,created_at,updated_at,user_id,doctor_id) VALUES (?,?,?,?,?,?)');
$usedRatePairs = [];
$rateCount = 0;
$i = 0;
while ($rateCount < 200 && $i < 1000) {
$i++;
$doctorId = rand_item($doctorIds);
$userId = rand_item($patientIds);
$key = "$userId-$doctorId";
if (isset($usedRatePairs[$key])) continue;
$usedRatePairs[$key] = true;
$score = rand_item([1,2,3,3,4,4,4,5,5,5]);
$ts = $now - rand(3600, 86400 * 300);
$rateStmt->execute([uuid(), $score, $ts, $ts, $userId, $doctorId]);
$rateCount++;
$count++;
}
echo " Rates: $rateCount\n";
// ── 9. Comments ───────────────────────────────────────────────────────────────
echo "Inserting comments...\n";
$comStmt = $pdo->prepare('INSERT INTO comments (uuid,body,status,created_at,updated_at,user_id,doctor_id) VALUES (?,?,?,?,?,?,?)');
$comStatuses = ['approved','approved','approved','pending','rejected'];
for ($i = 0; $i < 150; $i++) {
$doctorId = rand_item($doctorIds);
$userId = rand_item($patientIds);
$ts = $now - rand(3600, 86400 * 300);
$comStmt->execute([uuid(), rand_item($commentTexts), rand_item($comStatuses), $ts, $ts, $userId, $doctorId]);
$count++;
}
echo " Comments: 150\n";
// ── 10. Blogs ─────────────────────────────────────────────────────────────────
echo "Inserting blogs...\n";
$blogStmt = $pdo->prepare(
'INSERT INTO blogs (uuid,title,slug,body,summary,tags,status,created_at,updated_at,author_id)
VALUES (?,?,?,?,?,?,?,?,?,?)'
);
$adminUserId = null;
$adminRow = $pdo->query("SELECT id FROM users WHERE roles LIKE '%ROLE_ADMIN%' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
if ($adminRow) $adminUserId = $adminRow['id'];
$blogTags = [['سلامت','قلب'],['کودکان','تغذیه'],['پیشگیری','چکاپ'],['روانشناسی','استرس'],
['دیابت','تغذیه'],['ورزش','قلب'],['خواب','سلامت'],['پوست','مراقبت'],
['استخوان','تغذیه'],['چشم','بینایی'],['سرطان','پیشگیری'],['دندان','بهداشت'],
['فشار خون','قلب'],['واکسن','پیشگیری'],['مفصل','ارتوپدی']];
$usedSlugs = [];
for ($i = 0; $i < min(count($blogTitles), 15); $i++) {
$title = $blogTitles[$i];
$slug = 'blog-post-' . ($i + 1) . '-' . rand(1000, 9999);
$body = rand_item($blogBodies) . ' ' . rand_item($blogBodies);
$tags = json_encode($blogTags[$i] ?? ['سلامت'], JSON_UNESCAPED_UNICODE);
$status = $i < 12 ? 'published' : 'draft';
$ts = $now - rand(86400, 86400 * 200);
$authorId = $adminUserId ?? rand_item($doctorUserIds);
$blogStmt->execute([uuid(), $title, $slug, $body, mb_substr($body, 0, 150), $tags, $status, $ts, $ts, $authorId]);
$count++;
}
echo " Blogs: 15\n";
$pdo->exec('SET FOREIGN_KEY_CHECKS = 1');
echo "\n=== Seed Complete ===\n";
$tables = ['users','doctors','clinics','clinic_doctors','doctor_specialties','doctor_expertise',
'doctor_provinces','doctor_cities','doctor_addresses','appointments','payments',
'rates','comments','blogs','insurances'];
$total = 0;
foreach ($tables as $t) {
$c = (int)$pdo->query("SELECT COUNT(*) FROM `$t`")->fetchColumn();
echo " $t: $c\n";
$total += $c;
}
echo "\nTotal records across tables: $total\n";
+126
View File
@@ -0,0 +1,126 @@
<?php
declare(strict_types=1);
set_time_limit(0);
$pdo = new PDO('mysql:host=db;dbname=db;charset=utf8mb4', 'db', 'db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES utf8mb4');
$now = time();
function uuid(): string {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff),
mt_rand(0,0x0fff)|0x4000,mt_rand(0,0x3fff)|0x8000,
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff));
}
function ri(array $a) { return $a[array_rand($a)]; }
function wRand(array $items, array $weights): mixed {
$total = array_sum($weights); $r = rand(1, $total); $c = 0;
foreach ($items as $k => $v) { $c += $weights[$k]; if ($r <= $c) return $v; }
return $items[0];
}
// Load existing IDs
$doctorIds = $pdo->query('SELECT id FROM doctors')->fetchAll(PDO::FETCH_COLUMN);
$patientIds = $pdo->query("SELECT id FROM users WHERE roles NOT LIKE '%ROLE_DOCTOR%' AND roles NOT LIKE '%ROLE_ADMIN%'")->fetchAll(PDO::FETCH_COLUMN);
echo 'Doctors: ' . count($doctorIds) . ', Patients: ' . count($patientIds) . "\n";
// ── Ratings ───────────────────────────────────────────────────────────────────
echo "Inserting ratings...\n";
$rateStmt = $pdo->prepare('INSERT INTO rates (uuid,score,created_at,updated_at,user_id,doctor_id) VALUES (?,?,?,?,?,?)');
$usedPairs = [];
$rateCount = 0;
$pdo->beginTransaction();
$tries = 0;
while ($rateCount < 3000 && $tries < 30000) {
$tries++;
$doctorId = ri($doctorIds);
$userId = ri($patientIds);
$key = $userId . '-' . $doctorId;
if (isset($usedPairs[$key])) continue;
$usedPairs[$key] = true;
$score = wRand([1,2,3,4,5], [3,5,15,35,42]);
$ts = $now - rand(3600, 86400 * 400);
$rateStmt->execute([uuid(), $score, $ts, $ts, $userId, $doctorId]);
$rateCount++;
if ($rateCount % 1000 === 0) { $pdo->commit(); $pdo->beginTransaction(); echo " $rateCount\n"; }
}
$pdo->commit();
echo "Ratings: $rateCount\n";
// ── Comments ──────────────────────────────────────────────────────────────────
echo "Inserting comments...\n";
$comTexts = [
'دکتر بسیار دلسوز و با حوصله هستند. توضیحات کامل دادند.',
'معاینه دقیق بود. تشخیص درست و درمان موثر. ممنونم.',
'وقت انتظار کم بود و کیفیت ویزیت عالی.',
'بسیار متبحر و باتجربه. مشکلم حل شد.',
'رفتار حرفه‌ای و انسانی. مطب تمیز و منظم. توصیه می‌کنم.',
'ویزیت خوبی داشتم. دارو‌ها موثر بود.',
'یکی از بهترین پزشکانی که دیده‌ام. صبور و دقیق.',
'کمی صبر کردم ولی ارزشش داشت. وقت کافی گذاشت.',
'متخصص واقعی. همه سوالات را صادقانه جواب داد.',
'رزرو آسان و ویزیت به موقع. کاملاً راضی هستم.',
'برخورد محترمانه و تخصص بالا. حتماً دوباره مراجعه می‌کنم.',
'اطلاعات دقیق و مشاوره عالی. بهترین انتخاب بود.',
];
$comStmt = $pdo->prepare('INSERT INTO comments (uuid,body,status,created_at,updated_at,user_id,doctor_id) VALUES (?,?,?,?,?,?,?)');
$comStatuses = ['approved','approved','approved','approved','pending','rejected'];
$pdo->beginTransaction();
for ($i = 0; $i < 2000; $i++) {
$ts = $now - rand(3600, 86400 * 400);
$comStmt->execute([uuid(), ri($comTexts), ri($comStatuses), $ts, $ts, ri($patientIds), ri($doctorIds)]);
if (($i+1) % 500 === 0) { $pdo->commit(); $pdo->beginTransaction(); echo " Comments: " . ($i+1) . "\n"; }
}
$pdo->commit();
echo "Comments: 2000\n";
// ── Blogs ─────────────────────────────────────────────────────────────────────
echo "Inserting blogs...\n";
$blogStmt = $pdo->prepare('INSERT INTO blogs (uuid,title,slug,body,summary,tags,status,created_at,updated_at,author_id) VALUES (?,?,?,?,?,?,?,?,?,?)');
$blogData = [
['راهنمای جامع پیشگیری از بیماری‌های قلبی','heart-disease-prevention','بیماری‌های قلبی از علل اصلی مرگ هستند. با تغذیه سالم، ورزش منظم، ترک سیگار و کنترل فشار خون می‌توان خطر ابتلا را کاهش داد.',['قلب','پیشگیری','سلامت'],'published'],
['تغذیه سالم برای کودکان در سنین رشد','healthy-nutrition-children','مصرف متعادل پروتئین، لبنیات، میوه و سبزیجات برای رشد کودکان ضروری است.',['کودکان','تغذیه','رشد'],'published'],
['اهمیت چکاپ منظم سالانه','annual-checkup','آزمایش خون، فشار خون و غربالگری سرطان باید سالانه انجام شوند. تشخیص زودهنگام درمان را ساده‌تر می‌کند.',['چکاپ','پیشگیری'],'published'],
['مدیریت استرس در زندگی مدرن','stress-management','تنفس عمیق، مدیتیشن، ورزش و ارتباط اجتماعی سالم از راهکارهای موثر مدیریت استرس هستند.',['استرس','سلامت روان'],'published'],
['دیابت نوع ۲: علائم و کنترل','diabetes-type2','تشنگی زیاد، ادرار مکرر و خستگی از علائم دیابت هستند. رژیم مناسب و ورزش در مدیریت آن حیاتی است.',['دیابت','قند خون'],'published'],
['نقش ورزش در سلامت قلب','exercise-cardiovascular','۱۵۰ دقیقه فعالیت هوازی در هفته برای سلامت قلب ضروری است.',['ورزش','قلب'],'published'],
['خواب کافی و سلامت روان','sleep-health','بزرگسالان به ۷-۹ ساعت خواب نیاز دارند. کمبود خواب با بیماری‌های مزمن ارتباط دارد.',['خواب','سلامت'],'published'],
['مراقبت از پوست در برابر آفتاب','skin-care-sun','استفاده از کرم ضدآفتاب SPF 30+ و پوشش مناسب از پوست محافظت می‌کند.',['پوست','ضدآفتاب'],'published'],
['پیشگیری از پوکی استخوان','osteoporosis','مصرف کلسیم، ویتامین D و ورزش منظم از پوکی استخوان جلوگیری می‌کنند.',['استخوان','کلسیم'],'published'],
['مراقبت از بینایی','eye-care','معاینه سالانه چشم و رعایت قانون ۲۰-۲۰-۲۰ برای سلامت چشم ضروری است.',['چشم','بینایی'],'published'],
['سرطان پستان؛ تشخیص زودهنگام','breast-cancer','معاینه خودآزمایی ماهانه و ماموگرافی سالانه از ابزارهای تشخیص زودهنگام هستند.',['سرطان','پستان'],'published'],
['بهداشت دهان و دندان','dental-hygiene','مسواک زدن دو بار در روز و مراجعه به دندانپزشک هر ۶ ماه توصیه می‌شود.',['دندان','بهداشت'],'published'],
['کنترل فشار خون بالا','blood-pressure','کاهش نمک، ورزش منظم و مصرف داروها در کنترل فشار خون موثر هستند.',['فشار خون','قلب'],'published'],
['واکسیناسیون بزرگسالان','adult-vaccination','آنفلوانزا، هپاتیت B و واکسن HPV از واکسن‌های مهم بزرگسالی هستند.',['واکسن','پیشگیری'],'published'],
['آرتروز زانو: درمان و بازتوانی','knee-arthritis','فیزیوتراپی، ورزش‌های تقویتی و کاهش وزن در درمان آرتروز زانو موثر هستند.',['آرتروز','ارتوپدی'],'published'],
['تغذیه در بیماری‌های کلیوی','renal-diet','رژیم کم‌پتاسیم و کم‌فسفر برای بیماران کلیوی ضروری است.',['کلیه','تغذیه'],'draft'],
['سلامت روان در محیط کار','workplace-mental-health','تعادل کار و زندگی و ارتباط موثر با همکاران از عوامل سلامت روان در کار هستند.',['سلامت روان','کار'],'published'],
['آلرژی فصلی','seasonal-allergy','اجتناب از محرک‌ها و استفاده از آنتی‌هیستامین از روش‌های اصلی مقابله با آلرژی هستند.',['آلرژی','تنفس'],'published'],
['ورزش در دوران بارداری','pregnancy-exercise','پیاده‌روی و یوگای بارداری با نظر پزشک برای مادر و جنین مفید است.',['بارداری','ورزش'],'published'],
['پیشگیری از سرطان روده','colorectal-cancer','کولونوسکوپی از سن ۴۵ سالگی و رژیم پرفیبر خطر را کاهش می‌دهند.',['سرطان','روده'],'published'],
];
$adminRow = $pdo->query("SELECT id FROM users WHERE roles LIKE '%ROLE_ADMIN%' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
$adminId = $adminRow ? $adminRow['id'] : ri($doctorIds);
foreach ($blogData as $b) {
$ts = $now - rand(86400, 86400 * 300);
$blogStmt->execute([
uuid(), $b[0], $b[1] . '-' . rand(100,999), $b[2],
mb_substr($b[2], 0, 200), json_encode($b[3], JSON_UNESCAPED_UNICODE),
$b[4], $ts, $ts, $adminId
]);
}
echo 'Blogs: ' . count($blogData) . "\n";
// ── Summary ───────────────────────────────────────────────────────────────────
echo "\n=== Final counts ===\n";
$tables = ['users','doctors','clinics','clinic_doctors','clinic_specialties','clinic_services','clinic_insurances',
'doctor_specialties','doctor_expertise','doctor_provinces','doctor_cities','doctor_addresses',
'appointments','payments','rates','comments','blogs','insurances','profiles'];
$total = 0;
foreach ($tables as $t) {
$c = (int)$pdo->query("SELECT COUNT(*) FROM `$t`")->fetchColumn();
printf(" %-30s %d\n", $t . ':', $c);
$total += $c;
}
echo "\nTotal records: $total\n";
+708
View File
@@ -0,0 +1,708 @@
<?php
declare(strict_types=1);
set_time_limit(0);
ini_set('memory_limit', '512M');
$pdo = new PDO('mysql:host=db;dbname=db;charset=utf8mb4', 'db', 'db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec('SET NAMES utf8mb4');
$pdo->exec('SET FOREIGN_KEY_CHECKS = 0');
$pdo->exec("SET SESSION sql_mode = ''");
$now = time();
$BASE_DIR = '/var/www/html/public';
$BASE_URL = '';
// ── Helpers ───────────────────────────────────────────────────────────────────
function uuid(): string {
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff),
mt_rand(0,0x0fff)|0x4000,mt_rand(0,0x3fff)|0x8000,
mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff));
}
function ri(array $a) { return $a[array_rand($a)]; }
function ris(array $a, int $min, int $max): array {
$n = rand($min, min($max, count($a)));
shuffle($a);
return array_slice($a, 0, $n);
}
function mobile(array &$used): string {
$prefixes = ['0910','0911','0912','0913','0914','0915','0916','0917','0918','0919',
'0930','0933','0935','0936','0937','0938','0901','0902','0920','0921',
'0991','0992','0993','0994'];
do {
$m = ri($prefixes) . str_pad((string)rand(1000000,9999999),7,'0',STR_PAD_LEFT);
} while (isset($used[$m]));
$used[$m] = true;
return $m;
}
function pw(): string { return '$2y$13$fakehash' . substr(str_replace(['+','/','='],'',base64_encode(random_bytes(24))),0,44); }
// ── Download images with parallel curl ───────────────────────────────────────
function downloadParallel(array $urls, array $paths, int $batchSize = 20): void {
$total = count($urls);
for ($offset = 0; $offset < $total; $offset += $batchSize) {
$batch = array_slice($urls, $offset, $batchSize, true);
$batchPath = array_slice($paths, $offset, $batchSize, true);
$mh = curl_multi_init();
$handles = [];
foreach ($batch as $i => $url) {
if (file_exists($batchPath[$i])) continue;
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => 'Mozilla/5.0',
]);
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
}
$running = null;
do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0);
foreach ($handles as $i => $ch) {
$data = curl_multi_getcontent($ch);
if ($data && strlen($data) > 1000) {
@mkdir(dirname($batchPath[$i]), 0755, true);
file_put_contents($batchPath[$i], $data);
}
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
echo '.';
}
echo "\n";
}
function imgJson(string $url, string $filename, int $filesize = 0): string {
return json_encode([[
'fid' => rand(10000, 999999),
'uuid' => uuid(),
'url' => $url,
'filename' => $filename,
'filemime' => 'image/jpeg',
'filesize' => $filesize > 0 ? $filesize : rand(25000, 90000),
]], JSON_UNESCAPED_UNICODE);
}
// ── STEP 1 — Download doctor photos ──────────────────────────────────────────
echo "=== Downloading doctor photos ===\n";
$doctorPhotoDir = $BASE_DIR . '/uploads/doctors/2026-06';
@mkdir($doctorPhotoDir, 0755, true);
$photoUrls = [];
$photoPaths = [];
$doctorPhotos = ['male' => [], 'female' => []];
// 99 male portraits
for ($n = 1; $n <= 99; $n++) {
$url = "https://randomuser.me/api/portraits/men/$n.jpg";
$path = "$doctorPhotoDir/m-$n.jpg";
$photoUrls[] = $url;
$photoPaths[] = $path;
$doctorPhotos['male'][] = [
'url' => "/uploads/doctors/2026-06/m-$n.jpg",
'file' => "m-$n.jpg",
'path' => $path,
];
}
// 99 female portraits
for ($n = 1; $n <= 99; $n++) {
$url = "https://randomuser.me/api/portraits/women/$n.jpg";
$path = "$doctorPhotoDir/f-$n.jpg";
$photoUrls[] = $url;
$photoPaths[] = $path;
$doctorPhotos['female'][] = [
'url' => "/uploads/doctors/2026-06/f-$n.jpg",
'file' => "f-$n.jpg",
'path' => $path,
];
}
echo "Downloading 198 doctor portraits ";
downloadParallel($photoUrls, $photoPaths, 25);
// ── STEP 2 — Download clinic gallery & logos ──────────────────────────────────
echo "=== Downloading clinic images ===\n";
$galleryDir = $BASE_DIR . '/uploads/clinics/gallery/2026-06';
$logoDir = $BASE_DIR . '/uploads/clinics/logo/2026-06';
@mkdir($galleryDir, 0755, true);
@mkdir($logoDir, 0755, true);
$clinicPhotoUrls = [];
$clinicPhotoPaths = [];
$clinicGalleryPhotos = [];
$clinicLogoPhotos = [];
// 60 clinic gallery photos (medical/building themed via picsum seeds)
$clinicSeeds = [100,200,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,
1600,1700,1800,1900,2000,2100,2200,2300,2400,2500,2600,2700,2800,
2900,3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,4000,
4100,4200,4300,4400,4500,4600,4700,4800,4900,5000,5100,5200,5300,5400,5500,5600,5700,5800,5900,6000];
foreach ($clinicSeeds as $seed) {
$url = "https://picsum.photos/seed/$seed/640/480";
$path = "$galleryDir/c-$seed.jpg";
$clinicPhotoUrls[] = $url;
$clinicPhotoPaths[] = $path;
$clinicGalleryPhotos[] = ['url' => "/uploads/clinics/gallery/2026-06/c-$seed.jpg", 'file' => "c-$seed.jpg"];
}
// 40 clinic logos (smaller)
$logoSeeds = [10,20,30,40,50,60,70,80,90,110,120,130,140,150,160,170,180,190,210,220,
230,240,250,260,270,280,290,310,320,330,340,350,360,370,380,390,410,420,430,440];
foreach ($logoSeeds as $seed) {
$url = "https://picsum.photos/seed/logo$seed/200/200";
$path = "$logoDir/logo-$seed.jpg";
$clinicPhotoUrls[] = $url;
$clinicPhotoPaths[] = $path;
$clinicLogoPhotos[] = ['url' => "/uploads/clinics/logo/2026-06/logo-$seed.jpg", 'file' => "logo-$seed.jpg"];
}
echo "Downloading 100 clinic images ";
downloadParallel($clinicPhotoUrls, $clinicPhotoPaths, 25);
// ── STEP 3 — Download insurance logos ─────────────────────────────────────────
echo "=== Downloading insurance logos ===\n";
$insLogoDir = $BASE_DIR . '/uploads/insurances/logo/2026-06';
@mkdir($insLogoDir, 0755, true);
$insLogoUrls = [];
$insLogoPaths = [];
$insLogoFiles = [];
for ($n = 1; $n <= 20; $n++) {
$seed = $n * 50;
$url = "https://picsum.photos/seed/ins$seed/200/200";
$path = "$insLogoDir/ins-$n.jpg";
$insLogoUrls[] = $url;
$insLogoPaths[] = $path;
$insLogoFiles[] = "/uploads/insurances/logo/2026-06/ins-$n.jpg";
}
echo "Downloading 20 insurance logos ";
downloadParallel($insLogoUrls, $insLogoPaths, 20);
// ── Load DB data ──────────────────────────────────────────────────────────────
$provinces = $pdo->query('SELECT id FROM provinces')->fetchAll(PDO::FETCH_COLUMN);
$cities = $pdo->query('SELECT id, province_id FROM cities WHERE id != 600')->fetchAll(PDO::FETCH_ASSOC);
$cityIds = array_column($cities, 'id');
$cityProvMap = array_column($cities, 'province_id', 'id');
$specParents = $pdo->query('SELECT id FROM specialties WHERE parent_id IS NULL')->fetchAll(PDO::FETCH_COLUMN);
$specChildren = $pdo->query('SELECT id, parent_id FROM specialties WHERE parent_id IS NOT NULL')->fetchAll(PDO::FETCH_ASSOC);
$allServiceRows = $pdo->query('SELECT id, specialty_id FROM doctor_services')->fetchAll(PDO::FETCH_ASSOC);
$serviceIds = array_column($allServiceRows, 'id');
$specSvcMap = [];
foreach ($allServiceRows as $r) {
if ($r['specialty_id']) $specSvcMap[$r['specialty_id']][] = $r['id'];
}
$specChildMap = [];
foreach ($specChildren as $r) {
$specChildMap[$r['parent_id']][] = $r['id'];
}
// ── Static data ───────────────────────────────────────────────────────────────
$maleNames = ['علی','محمد','حسین','احمد','رضا','مهدی','حسن','اکبر','ابراهیم','کریم','جواد','امیر',
'سعید','مجید','فرید','کامران','سیاوش','داریوش','پرویز','شهرام','بهرام','فرهاد','نادر',
'مسعود','وحید','یاسر','حامد','سجاد','ایمان','میثم','آرش','آرمان','پدرام','پویا','کیان',
'سیروس','بابک','فریبرز','هوشنگ','نیما','شاهین','کاوه','آریا','پارسا','دانیال','سینا',
'رامین','کورش','منوچهر','فرامرز','بهزاد','پیمان','امین','اشکان','شایان','آیدین','ارسلان'];
$femaleNames = ['فاطمه','زهرا','مریم','سارا','نرگس','لیلا','نازنین','مهناز','شیرین','پروین','ملیحه',
'الناز','آتنا','باران','ترانه','دلارام','رویا','شادی','گلناز','ماهرخ','ندا','نیلوفر',
'هانیه','یاسمن','زینب','حدیثه','سمیه','طاهره','عاطفه','منیژه','سوده','ریحانه','فرزانه',
'نسرین','ناهید','مینا','گیتی','آذر','پرستو','ژیلا','شکوفه','آفرین','بهناز','مهسا','رها'];
$lastNames = ['احمدی','محمدی','رضایی','حسینی','موسوی','جعفری','کریمی','نوری','صادقی','قاسمی',
'عباسی','میرزایی','رحیمی','اکبری','یوسفی','حیدری','طاهری','نصیری','سلیمانی','زارعی',
'مرادی','شریفی','منصوری','ذبیحی','تهرانی','اصفهانی','مشهدی','شیرازی','تبریزی','همدانی',
'ملکی','درویشی','امیری','نجفی','شاهی','بهرامی','خسروی','گلمحمدی','فدایی','ولیپور',
'نظری','فروزان','پورعلی','دهقانی','صالحی','ربیعی','مجیدی','سبحانی','زمانی','بهشتی',
'عزیزی','خلیلی','رستمی','پورحسین','نظام‌الدینی','میرمحمدی','سیدی','سلطانی','نادری','ابراهیمی'];
$degrees = ['متخصص','فوق تخصص','دکترای عمومی','فلوشیپ','استادیار','دانشیار','پروفسور','رزیدنت'];
$bios = [
'دارای بیش از ۱۵ سال سابقه در حوزه تخصصی، عضو انجمن پزشکی ایران و سازمان نظام پزشکی.',
'فارغ‌التحصیل دانشگاه علوم پزشکی تهران با تجربه کار در بیمارستان‌های معتبر کشور.',
'متخصص با سابقه درخشان، ارائه خدمات با بالاترین کیفیت با استفاده از جدیدترین تجهیزات.',
'عضو هیئت علمی دانشگاه با بیش از ۱۰ سال تجربه بالینی و پژوهشی.',
'دارای گواهینامه‌های تخصصی از مراکز بین‌المللی، آشنا با جدیدترین روش‌های درمانی.',
'پزشک باتجربه با رویکرد جامع در درمان و اعتقاد راسخ به طب پیشگیری.',
'متعهد به ارائه بهترین مراقبت‌های پزشکی با رعایت کامل اصول اخلاق پزشکی.',
'دارای مدرک تخصصی از اروپا و تجربه کار در مراکز درمانی پیشرفته اروپا و آمریکا.',
'فارغ‌التحصیل ممتاز دانشگاه علوم پزشکی مشهد، برنده جایزه پزشک نمونه سال.',
'متخصص با سابقه بیش از ۲۰ سال در درمان بیماری‌های مزمن و پیچیده.',
'عضو چندین انجمن علمی تخصصی، دارای مقالات متعدد در مجلات معتبر.',
'پزشک متخصص با رویکرد بیمار‌محور و استفاده از روش‌های نوین تشخیص و درمان.',
];
$clinicNames = ['کلینیک تخصصی','مرکز درمانی','بیمارستان','کلینیک جامع','مرکز مشاوره پزشکی',
'مطب','کلینیک ویژه','مرکز پزشکی','درمانگاه','کلینیک سلامت','مجتمع پزشکی'];
$clinicSuffixes = ['امید','نوین','رازی','ابن سینا','سینا','شفا','سلامت','آریا','پارس','ایران',
'مهر','صبا','فجر','بهار','شهید بهشتی','حضرت علی','امام رضا','گلستان','نور','طلوع'];
$streets = ['خیابان ولیعصر','خیابان انقلاب','خیابان آزادی','بلوار کشاورز','خیابان شریعتی',
'خیابان مطهری','خیابان فردوسی','خیابان پاسداران','خیابان جمهوری','خیابان طالقانی',
'بلوار سعادت‌آباد','خیابان وزرا','خیابان بهشتی','خیابان میرداماد','خیابان حقانی',
'خیابان دکتر چمران','بزرگراه شهید همت','خیابان ملاصدرا','خیابان زرتشت','بلوار اشرفی'];
$buildings = ['ساختمان پزشکان','برج طبی','مجتمع پزشکی','پلاک','مطب طبقه','واحد'];
$workingDaysList = [
'شنبه تا چهارشنبه ۸ تا ۲۰', 'شنبه تا پنجشنبه ۸ تا ۱۸',
'یک‌شنبه تا پنجشنبه ۹ تا ۱۷', 'شنبه تا سه‌شنبه ۷ تا ۱۹',
'همه روزه ۸ تا ۲۲', 'شنبه تا چهارشنبه ۹ تا ۲۰',
'دوشنبه تا جمعه ۱۰ تا ۱۸', 'شنبه تا پنجشنبه ۷ تا ۱۳ و ۱۶ تا ۲۰',
];
$apptStatuses = ['reserved','visited','completed','cancelled_by_user','cancelled_by_doctor','no_show','waiting','checked_in'];
$apptWeights = [15, 25, 30, 10, 5, 5, 5, 5];
$commentTexts = [
'دکتر بسیار دلسوز و با حوصله هستند. توضیحات کاملی دادند و از معاینه راضی بودم.',
'معاینه بسیار دقیق بود. تشخیص درست و درمان موثر. ممنونم از دکتر عزیز.',
'وقت انتظار کمی داشتم و دکتر سر وقت حاضر بودند. کیفیت ویزیت بالا بود.',
'بسیار متبحر و با تجربه. مشکلم کاملاً حل شد و از نتیجه درمان راضی هستم.',
'توصیه می‌کنم به همه. رفتار حرفه‌ای و انسانی. مطب تمیز و منظم.',
'دکتر خوبی هستند ولی وقت ویزیت کمی کوتاه بود. در کل تجربه خوبی داشتم.',
'از ویزیت کاملاً راضی بودم. درمان موثر و پیگیری خوب.',
'یکی از بهترین پزشکانی که تاکنون به آنها مراجعه کرده‌ام. بسیار ماهر و دلسوز.',
'کمی منتظر ماندم اما ارزشش را داشت. دکتر وقت کافی برای بیمار می‌گذارند.',
'متخصص واقعی در حوزه کار خود. با صبر و حوصله همه سوالات را جواب دادند.',
'رزرو آنلاین خیلی راحت بود. دکتر به موقع ویزیت کردند و مشکلم برطرف شد.',
'برخورد محترمانه و صادقانه. داروها اثر کردند. حتماً دوباره مراجعه خواهم کرد.',
];
// ── STEP 4 — Insurances ───────────────────────────────────────────────────────
echo "\n=== Inserting insurances ===\n";
$insData = [
['تأمین اجتماعی','basic'],['خدمات درمانی','basic'],['نیروهای مسلح','basic'],
['کمیته امداد امام خمینی','basic'],['سازمان بهزیستی','basic'],['بیمه روستایی','basic'],
['ایران','supplementary'],['آسیا','supplementary'],['البرز','supplementary'],
['پارسیان','supplementary'],['سامان','supplementary'],['میهن','supplementary'],
['دانا','supplementary'],['رازی','supplementary'],['کوثر','supplementary'],
['معلم','supplementary'],['ملت','supplementary'],['حافظ','supplementary'],
['اتکا','supplementary'],['توسعه','supplementary'],
];
$insStmt = $pdo->prepare('INSERT INTO insurances (uuid,name,type,logo_url,status) VALUES (?,?,?,?,1)');
$insIds = [];
foreach ($insData as $i => $ins) {
$logo = isset($insLogoFiles[$i]) ? $insLogoFiles[$i] : null;
$insStmt->execute([uuid(), $ins[0], $ins[1], $logo]);
$insIds[] = (int)$pdo->lastInsertId();
}
echo 'Insurances: ' . count($insIds) . "\n";
// ── STEP 5 — Patients ─────────────────────────────────────────────────────────
echo "=== Inserting patients (3000) ===\n";
$usedMobiles = [];
// Reserve admin mobile
$usedMobiles['09120671713'] = true;
$patientIds = [];
$uStmt = $pdo->prepare(
'INSERT INTO users (uuid,mobile_number,password_hash,email,real_name,roles,status,created_at,updated_at)
VALUES (?,?,?,?,?,?,1,?,?)'
);
$pStmt = $pdo->prepare(
'INSERT INTO profiles (uuid,label,family,gender,blood_type,marital_status,sharing_with_user,
basic_insurance_id,supplementary_insurance_id,created_at,updated_at,user_id)
VALUES (?,?,?,?,?,?,1,?,?,?,?,?)'
);
$bloodTypes = ['A+','A-','B+','B-','O+','O-','AB+','AB-'];
$marital = ['single','married','divorced','widowed'];
$pdo->beginTransaction();
$batchCount = 0;
for ($i = 0; $i < 3000; $i++) {
$gender = rand(0,2) === 0 ? 'female' : 'male';
$firstName = $gender === 'female' ? ri($femaleNames) : ri($maleNames);
$lastName = ri($lastNames);
$name = $firstName . ' ' . $lastName;
$mob = mobile($usedMobiles);
$email = 'patient' . $i . '@mail.ir';
$ts = $now - rand(86400, 86400 * 730);
$uStmt->execute([uuid(), $mob, pw(), $email, $name, '["ROLE_USER"]', $ts, $ts]);
$userId = (int)$pdo->lastInsertId();
$patientIds[] = $userId;
// Profile for some patients
if ($i % 3 === 0) {
$basicIns = ri(array_slice($insIds, 0, 6));
$suppIns = rand(0,1) ? ri(array_slice($insIds, 6)) : null;
$pStmt->execute([
uuid(), $firstName, $lastName, $gender, ri($bloodTypes), ri($marital),
$basicIns, $suppIns, $ts, $ts, $userId
]);
}
$batchCount++;
if ($batchCount % 500 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Patients: $batchCount\n";
}
}
$pdo->commit();
echo 'Total patients: ' . count($patientIds) . "\n";
// ── STEP 6 — Doctors (1000) ───────────────────────────────────────────────────
echo "=== Inserting doctors (1000) ===\n";
$doctorIds = [];
$doctorUserIds = [];
$doctorGenderMap = [];
$duStmt = $pdo->prepare(
'INSERT INTO users (uuid,mobile_number,password_hash,email,real_name,roles,status,created_at,updated_at)
VALUES (?,?,?,?,?,?,1,?,?)'
);
$dStmt = $pdo->prepare(
'INSERT INTO doctors (uuid,name,gender,medical_system_code,mobile_number,activity_time,degree,info,
images,doctor_rate,doctor_rate_percentage,active_doctor_appointment,created_at,updated_at,user_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)'
);
$dsStmt = $pdo->prepare('INSERT IGNORE INTO doctor_specialties (doctor_id,specialty_id) VALUES (?,?)');
$deStmt = $pdo->prepare('INSERT IGNORE INTO doctor_expertise (doctor_id,service_id) VALUES (?,?)');
$dpStmt = $pdo->prepare('INSERT IGNORE INTO doctor_provinces (doctor_id,province_id) VALUES (?,?)');
$dcStmt = $pdo->prepare('INSERT IGNORE INTO doctor_cities (doctor_id,city_id) VALUES (?,?)');
$daStmt = $pdo->prepare(
'INSERT INTO doctor_addresses (uuid,name,address,telephone,latitude,longitude,created_at,updated_at,doctor_id,city_id,province_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?)'
);
$malePhotos = $doctorPhotos['male'];
$femalePhotos = $doctorPhotos['female'];
$pdo->beginTransaction();
for ($i = 0; $i < 1000; $i++) {
$gender = $i % 4 === 0 ? 'female' : 'male';
$firstName = $gender === 'female' ? ri($femaleNames) : ri($maleNames);
$lastName = ri($lastNames);
$name = 'دکتر ' . $firstName . ' ' . $lastName;
$mob = mobile($usedMobiles);
$email = 'doctor' . $i . '@clinic-pro.ir';
$ts = $now - rand(86400 * 60, 86400 * 1000);
// User
$duStmt->execute([uuid(), $mob, pw(), $email, $name, '["ROLE_USER","ROLE_DOCTOR"]', $ts, $ts]);
$userId = (int)$pdo->lastInsertId();
$doctorUserIds[] = $userId;
// Pick photo
$photoPool = $gender === 'female' ? $femalePhotos : $malePhotos;
$photo = $photoPool[$i % count($photoPool)];
$imgJson = json_encode([[
'fid' => rand(10000,999999),
'uuid' => uuid(),
'url' => $photo['url'],
'filename' => $photo['file'],
'filemime' => 'image/jpeg',
'filesize' => rand(30000, 80000),
]], JSON_UNESCAPED_UNICODE);
$rate = round(rand(32, 50) / 10, 1);
$ratePct = rand(68, 98);
$dStmt->execute([
uuid(), $name, $gender,
(string)rand(10000000, 99999999), $mob,
rand(3, 30), ri($degrees), ri($bios),
$imgJson, $rate, $ratePct, $ts, $ts, $userId
]);
$doctorId = (int)$pdo->lastInsertId();
$doctorIds[] = $doctorId;
$doctorGenderMap[$doctorId] = $gender;
// 1-3 parent specialties
$chosenParents = ris($specParents, 1, 2);
foreach ($chosenParents as $spId) {
$dsStmt->execute([$doctorId, $spId]);
// 1-3 child specialties under same parent
$kids = $specChildMap[$spId] ?? [];
foreach (ris($kids, 1, 3) as $kid) {
$dsStmt->execute([$doctorId, $kid]);
}
// 3-8 services
$svcPool = $specSvcMap[$spId] ?? array_slice($serviceIds, 0, 15);
foreach (ris($svcPool, 3, 8) as $svcId) {
$deStmt->execute([$doctorId, $svcId]);
}
}
// 1-3 cities
$chosenCities = ris($cityIds, 1, 3);
foreach ($chosenCities as $cid) {
$provId = $cityProvMap[$cid] ?? null;
$dcStmt->execute([$doctorId, $cid]);
if ($provId) $dpStmt->execute([$doctorId, $provId]);
// Address
$street = ri($streets);
$bld = ri($buildings);
$no = rand(1, 300);
$addr = $street . '، ' . $bld . ' ' . $no;
$lat = 33.0 + rand(0, 700) / 100;
$lon = 48.0 + rand(0, 1500) / 100;
$tel = '0' . ri(['21','511','411','31','71','81','351','441','131','3411']) . rand(10000000, 99999999);
$ts2 = $now - rand(86400, 86400 * 200);
$daStmt->execute([uuid(), 'مطب ' . $firstName . ' ' . $lastName, $addr, $tel, $lat, $lon, $ts2, $ts2, $doctorId, $cid, $provId]);
}
if (($i + 1) % 100 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Doctors: " . ($i + 1) . "\n";
}
}
$pdo->commit();
echo 'Total doctors: ' . count($doctorIds) . "\n";
// ── STEP 7 — Clinics (200) ────────────────────────────────────────────────────
echo "=== Inserting clinics (200) ===\n";
$clinicIds = [];
$clStmt = $pdo->prepare(
'INSERT INTO clinics (uuid,name,info,address,telephone,is_24_7,working_days,latitude,longitude,
city_id,province_id,images_clinic,clinic_logo,created_at,updated_at,user_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'
);
$clDStmt = $pdo->prepare('INSERT IGNORE INTO clinic_doctors (clinic_id,doctor_id) VALUES (?,?)');
$clSpStmt = $pdo->prepare('INSERT IGNORE INTO clinic_specialties (clinic_id,specialty_id) VALUES (?,?)');
$clSvStmt = $pdo->prepare('INSERT IGNORE INTO clinic_services (clinic_id,service_id) VALUES (?,?)');
$clInStmt = $pdo->prepare('INSERT IGNORE INTO clinic_insurances (clinic_id,insurance_id) VALUES (?,?)');
// 60% of doctors go into clinics
$clinicDoctorPool = array_slice($doctorIds, 0, 600);
shuffle($clinicDoctorPool);
$poolIdx = 0;
$pdo->beginTransaction();
for ($i = 0; $i < 200; $i++) {
$cityRow = ri($cities);
$cityId = (int)$cityRow['id'];
$provId = (int)($cityRow['province_id'] ?? 0);
$name = ri($clinicNames) . ' ' . ri($clinicSuffixes);
$is247 = rand(0, 7) === 0 ? 1 : 0;
$ts = $now - rand(86400 * 60, 86400 * 730);
$street = ri($streets);
$no = rand(1, 300);
$addr = $street . '، پلاک ' . $no;
$tel = '0' . ri(['21','511','411','31','71','81','351','441']) . rand(10000000, 99999999);
$lat = 33.0 + rand(0, 700) / 100;
$lon = 48.0 + rand(0, 1500) / 100;
$ownerId = $doctorUserIds[array_rand($doctorUserIds)];
// Clinic photos (1-3 gallery + 1 logo)
$galleryCount = rand(1, 3);
$galleryArr = [];
for ($g = 0; $g < $galleryCount; $g++) {
$photo = $clinicGalleryPhotos[($i * 3 + $g) % count($clinicGalleryPhotos)];
$galleryArr[] = ['fid'=>rand(10000,999999),'uuid'=>uuid(),'url'=>$photo['url'],
'filename'=>$photo['file'],'filemime'=>'image/jpeg','filesize'=>rand(60000,200000)];
}
$logoPhoto = $clinicLogoPhotos[$i % count($clinicLogoPhotos)];
$logoArr = [['fid'=>rand(10000,999999),'uuid'=>uuid(),'url'=>$logoPhoto['url'],
'filename'=>$logoPhoto['file'],'filemime'=>'image/jpeg','filesize'=>rand(20000,50000)]];
$clStmt->execute([
uuid(), $name,
'ارائه خدمات تخصصی پزشکی با استفاده از جدیدترین تجهیزات و کادر درمانی مجرب.',
$addr, $tel, $is247, ri($workingDaysList), $lat, $lon,
$cityId, $provId > 0 ? $provId : null,
json_encode($galleryArr, JSON_UNESCAPED_UNICODE),
json_encode($logoArr, JSON_UNESCAPED_UNICODE),
$ts, $ts, $ownerId
]);
$clinicId = (int)$pdo->lastInsertId();
$clinicIds[] = $clinicId;
// 3-6 doctors per clinic
$numDocs = rand(3, 6);
$addedDocs = 0;
while ($addedDocs < $numDocs && $poolIdx < count($clinicDoctorPool)) {
$clDStmt->execute([$clinicId, $clinicDoctorPool[$poolIdx++]]);
$addedDocs++;
}
// 2-4 specialties
foreach (ris($specParents, 2, 4) as $spId) {
$clSpStmt->execute([$clinicId, $spId]);
}
// 3-6 services
foreach (ris($serviceIds, 3, 6) as $svId) {
$clSvStmt->execute([$clinicId, $svId]);
}
// 3-6 insurances
foreach (ris($insIds, 3, 6) as $inId) {
$clInStmt->execute([$clinicId, $inId]);
}
if (($i + 1) % 50 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Clinics: " . ($i + 1) . "\n";
}
}
$pdo->commit();
echo 'Total clinics: ' . count($clinicIds) . "\n";
// ── STEP 8 — Appointments (8000) ──────────────────────────────────────────────
echo "=== Inserting appointments (8000) ===\n";
$apptStmt = $pdo->prepare(
'INSERT INTO appointments (uuid,slot_start,slot_end,status,note,created_at,updated_at,doctor_id,user_id)
VALUES (?,?,?,?,?,?,?,?,?)'
);
$apptIds = [];
$apptStatusArr = [];
$notes = ['','مراجعه اول','پیگیری','نوبت اضطراری','مشاوره','کنترل دوره‌ای','آزمایش تکمیلی','چکاپ سالانه'];
function wRand(array $items, array $weights): mixed {
$total = array_sum($weights); $r = rand(1, $total); $c = 0;
foreach ($items as $k => $item) { $c += $weights[$k]; if ($r <= $c) return $item; }
return $items[0];
}
$pdo->beginTransaction();
for ($i = 0; $i < 8000; $i++) {
$doctorId = ri($doctorIds);
$userId = ri($patientIds);
$status = wRand($apptStatuses, $apptWeights);
if (in_array($status, ['visited','completed','no_show','cancelled_by_user','cancelled_by_doctor','checked_in'])) {
$slotStart = $now - rand(3600, 86400 * 365);
} else {
$slotStart = $now + rand(3600, 86400 * 45);
}
$slotEnd = $slotStart + 1800;
$ts = $slotStart - rand(3600, 86400 * 14);
$apptStmt->execute([uuid(), $slotStart, $slotEnd, $status, ri($notes), $ts, $ts, $doctorId, $userId]);
$apptId = (int)$pdo->lastInsertId();
$apptIds[] = $apptId;
$apptStatusArr[] = $status;
if (($i + 1) % 1000 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Appointments: " . ($i + 1) . "\n";
}
}
$pdo->commit();
// ── STEP 9 — Payments ─────────────────────────────────────────────────────────
echo "=== Inserting payments ===\n";
$payStmt = $pdo->prepare(
'INSERT INTO payments (uuid,order_id,amount_rials,status,gateway,type,reference_id,created_at,updated_at,user_id,appointment_id)
VALUES (?,?,?,?,?,?,?,?,?,?,?)'
);
$gateways = ['mellat','sep','zarinpal','parsian','sadad'];
$amounts = [1500000,2000000,2500000,3000000,3500000,4000000,4500000,5000000,5500000,6000000,7000000,8000000];
$pdo->beginTransaction();
$payCount = 0;
foreach ($apptIds as $k => $apptId) {
$st = $apptStatusArr[$k];
if (!in_array($st, ['visited','completed','reserved','waiting','checked_in'])) continue;
$payStatus = in_array($st, ['visited','completed','checked_in']) ? 'paid' : ri(['paid','pending']);
$userId = ri($patientIds);
$ts = $now - rand(3600, 86400 * 365);
$refId = $payStatus === 'paid' ? (string)rand(100000000, 999999999) : null;
$payStmt->execute([
uuid(), 'ORD-' . strtoupper(substr(uuid(), 0, 8)), ri($amounts),
$payStatus, ri($gateways), 'appointment', $refId, $ts, $ts, $userId, $apptId
]);
$payCount++;
if ($payCount % 1000 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Payments: $payCount\n";
}
}
$pdo->commit();
echo "Total payments: $payCount\n";
// ── STEP 10 — Ratings ─────────────────────────────────────────────────────────
echo "=== Inserting ratings (3000) ===\n";
$rateStmt = $pdo->prepare('INSERT INTO rates (uuid,score,created_at,updated_at,user_id,doctor_id) VALUES (?,?,?,?,?,?)');
$usedPairs = [];
$rateCount = 0;
$pdo->beginTransaction();
$tries = 0;
while ($rateCount < 3000 && $tries < 20000) {
$tries++;
$doctorId = ri($doctorIds);
$userId = ri($patientIds);
$key = $userId . '-' . $doctorId;
if (isset($usedPairs[$key])) continue;
$usedPairs[$key] = true;
$score = wRand([1,2,3,4,5], [3,5,15,35,42]);
$ts = $now - rand(3600, 86400 * 400);
$rateStmt->execute([uuid(), $score, $ts, $ts, $userId, $doctorId]);
$rateCount++;
if ($rateCount % 1000 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Ratings: $rateCount\n";
}
}
$pdo->commit();
echo "Total ratings: $rateCount\n";
// ── STEP 11 — Comments ────────────────────────────────────────────────────────
echo "=== Inserting comments (2000) ===\n";
$comStmt = $pdo->prepare('INSERT INTO comments (uuid,body,status,created_at,updated_at,user_id,doctor_id) VALUES (?,?,?,?,?,?,?)');
$comStatuses = ['approved','approved','approved','approved','pending','rejected'];
$pdo->beginTransaction();
for ($i = 0; $i < 2000; $i++) {
$ts = $now - rand(3600, 86400 * 400);
$comStmt->execute([uuid(), ri($commentTexts), ri($comStatuses), $ts, $ts, ri($patientIds), ri($doctorIds)]);
if (($i + 1) % 500 === 0) {
$pdo->commit();
$pdo->beginTransaction();
echo " Comments: " . ($i + 1) . "\n";
}
}
$pdo->commit();
// ── STEP 12 — Blogs ───────────────────────────────────────────────────────────
echo "=== Inserting blogs ===\n";
$blogStmt = $pdo->prepare(
'INSERT INTO blogs (uuid,title,slug,body,summary,tags,status,created_at,updated_at,author_id)
VALUES (?,?,?,?,?,?,?,?,?,?)'
);
$blogData = [
['راهنمای جامع پیشگیری از بیماری‌های قلبی','heart-disease-prevention','بیماری‌های قلبی از مهم‌ترین علل مرگ هستند. با تغذیه سالم، ورزش منظم، ترک سیگار و کنترل فشار خون می‌توان خطر ابتلا را به شدت کاهش داد. چکاپ سالیانه و مشاوره با متخصص قلب توصیه می‌شود.',['قلب','پیشگیری','سلامت']],
['تغذیه سالم برای کودکان در سنین رشد','healthy-nutrition-children','مصرف متعادل پروتئین، لبنیات، میوه و سبزیجات برای رشد کودکان ضروری است. از مصرف قند و چربی اشباع بپرهیزید و آب کافی بنوشید.',['کودکان','تغذیه','رشد']],
['اهمیت چکاپ منظم سالانه برای همه سنین','annual-checkup-importance','آزمایش خون، فشار خون، قند خون و تست‌های غربالگری سرطان باید سالانه انجام شوند. تشخیص زودهنگام درمان را ساده‌تر می‌کند.',['چکاپ','پیشگیری','غربالگری']],
['مدیریت استرس و اضطراب در زندگی مدرن','stress-management','تکنیک‌های تنفس عمیق، مدیتیشن، ورزش منظم و ارتباط اجتماعی سالم از راهکارهای موثر مدیریت استرس هستند.',['استرس','سلامت روان','مدیتیشن']],
['دیابت نوع ۲: علائم، پیشگیری و کنترل','diabetes-type2','تشنگی زیاد، ادرار مکرر، خستگی و تاری دید از علائم دیابت هستند. رژیم غذایی مناسب، ورزش و کنترل وزن در پیشگیری و مدیریت آن حیاتی است.',['دیابت','قند خون','پیشگیری']],
['نقش ورزش در سلامت قلب و عروق','exercise-cardiovascular-health','۱۵۰ دقیقه فعالیت هوازی متوسط در هفته برای سلامت قلب توصیه می‌شود. پیاده‌روی، شنا و دوچرخه‌سواری گزینه‌های عالی هستند.',['ورزش','قلب','سلامت']],
['خواب کافی و تاثیر آن بر سلامت جسم و روان','sleep-health','بزرگسالان به ۷-۹ ساعت خواب شبانه نیاز دارند. کمبود خواب با دیابت، چاقی، افسردگی و بیماری قلبی ارتباط دارد.',['خواب','سلامت','استراحت']],
['مراقبت از پوست در برابر آفتاب و آلودگی','skin-care-sun-pollution','استفاده از کرم ضدآفتاب با SPF 30+، پوشش مناسب و آنتی‌اکسیدان‌ها به محافظت از پوست کمک می‌کنند.',['پوست','ضدآفتاب','آلودگی']],
['پیشگیری از پوکی استخوان با تغذیه مناسب','osteoporosis-prevention','مصرف کافی کلسیم، ویتامین D، ورزش با وزن بدن و پرهیز از سیگار و الکل از مهم‌ترین راهکارهای پیشگیری از پوکی استخوان هستند.',['استخوان','کلسیم','پیشگیری']],
['راهنمای کامل مراقبت از بینایی','eye-care-guide','معاینه سالانه چشم، استفاده از عینک آفتابی مناسب، رعایت قانون ۲۰-۲۰-۲۰ هنگام کار با صفحه نمایش و تغذیه سرشار از لوتئین برای سلامت چشم ضروری است.',['چشم','بینایی','سلامت']],
['سرطان پستان: تشخیص زودهنگام نجات‌بخش است','breast-cancer-early-detection','معاینه خودآزمایی ماهانه، ماموگرافی سالانه برای زنان بالای ۴۰ سال و مراجعه به پزشک در صورت تغییرات مشکوک توصیه می‌شود.',['سرطان','پستان','غربالگری']],
['بهداشت دهان و دندان در همه سنین','dental-hygiene','مسواک زدن دو بار در روز، استفاده از نخ دندان و مراجعه به دندانپزشک هر ۶ ماه یک‌بار از اساسی‌ترین اصول بهداشت دهان است.',['دندان','بهداشت','پیشگیری']],
['کنترل فشار خون بالا با تغییر سبک زندگی','high-blood-pressure-control','کاهش مصرف نمک، کنترل وزن، ورزش منظم، پرهیز از استرس و مصرف منظم داروها در کنترل فشار خون ضروری هستند.',['فشار خون','قلب','سبک زندگی']],
['واکسیناسیون بزرگسالان؛ آنچه باید بدانید','adult-vaccination-guide','آنفلوانزا، کزاز، هپاتیت B، آبله مرغان و واکسن HPV از واکسن‌های مهم بزرگسالی هستند. برنامه واکسیناسیون را با پزشک خود مشورت کنید.',['واکسن','پیشگیری','بیماری']],
['آرتروز زانو: درمان و بازتوانی','knee-osteoarthritis-treatment','فیزیوتراپی، ورزش‌های تقویتی، کاهش وزن و در موارد پیشرفته جراحی از روش‌های درمان آرتروز زانو هستند.',['آرتروز','زانو','ارتوپدی']],
['تغذیه درمانی در بیماری‌های کلیوی','renal-diet','رژیم کم‌پتاسیم، کم‌فسفر و کم‌سدیم برای بیماران کلیوی ضروری است. مقدار پروتئین مصرفی باید با پزشک هماهنگ شود.',['کلیه','تغذیه','رژیم']],
['سلامت روان در محیط کار','workplace-mental-health','تعادل کار و زندگی، ارتباط موثر با همکاران، مدیریت زمان و استراحت کافی از عوامل مهم سلامت روان در محیط کار هستند.',['سلامت روان','کار','استرس']],
['آلرژی فصلی و راهکارهای مقابله','seasonal-allergy-management','اجتناب از محرک‌ها، استفاده از داروهای آنتی‌هیستامین، شستن منظم دست و چشم و مشاوره با متخصص آلرژی از راهکارهای اصلی هستند.',['آلرژی','تنفس','بهار']],
['اهمیت ورزش در دوران بارداری','pregnancy-exercise','پیاده‌روی، شنا و یوگای بارداری با نظر پزشک برای سلامت مادر و جنین مفید هستند. از ورزش‌های پرضربه پرهیز کنید.',['بارداری','ورزش','سلامت']],
['پیشگیری از سرطان روده بزرگ','colorectal-cancer-prevention','غربالگری با کولونوسکوپی از سن ۴۵ سالگی، رژیم پرفیبر، کاهش مصرف گوشت قرمز و ورزش منظم خطر را کاهش می‌دهند.',['سرطان','روده','غربالگری']],
];
$adminRow = $pdo->query("SELECT id FROM users WHERE roles LIKE '%ROLE_ADMIN%' LIMIT 1")->fetch(PDO::FETCH_ASSOC);
$adminId = $adminRow ? $adminRow['id'] : $doctorUserIds[0];
$statuses = ['published','published','published','published','published','draft'];
foreach ($blogData as $idx => $b) {
$ts = $now - rand(86400, 86400 * 300);
$blogStmt->execute([
uuid(), $b[0], $b[1] . '-' . rand(100,999), $b[2],
mb_substr($b[2], 0, 200), json_encode($b[3], JSON_UNESCAPED_UNICODE),
ri($statuses), $ts, $ts, $adminId
]);
}
echo 'Blogs: ' . count($blogData) . "\n";
$pdo->exec('SET FOREIGN_KEY_CHECKS = 1');
// ── Summary ───────────────────────────────────────────────────────────────────
echo "\n=== COMPLETE — Record counts ===\n";
$tables = ['users','doctors','clinics','clinic_doctors','clinic_specialties','clinic_services','clinic_insurances',
'doctor_specialties','doctor_expertise','doctor_provinces','doctor_cities','doctor_addresses',
'appointments','payments','rates','comments','blogs','insurances','profiles'];
$total = 0;
foreach ($tables as $t) {
$c = (int)$pdo->query("SELECT COUNT(*) FROM `$t`")->fetchColumn();
printf(" %-30s %d\n", $t . ':', $c);
$total += $c;
}
echo "\nTotal records: $total\n";