# معماری — تسک ۰۸: ماژول دسته‌بندی‌ها ## ساختار فایل‌ها ``` src/Module/Category/ ├── Controller/ │ └── CategoryController.php ← همه endpoint ها ├── Service/ │ └── CategoryService.php ├── Repository/ │ └── CategoryRepository.php ├── Entity/ │ └── Category.php ├── DTO/ │ ├── Request/ │ │ ├── CreateCategoryRequest.php │ │ └── UpdateCategoryRequest.php │ └── Response/ │ └── CategoryResponse.php └── DataFixtures/ └── CategoryFixtures.php ← داده‌های اولیه (استان، شهر، تخصص، ...) ``` ## Entity: Category ```php #[ORM\Entity] #[ORM\Table(name: 'categories')] class Category { #[ORM\Id, ORM\GeneratedValue, ORM\Column] private int $id; #[ORM\Column(length: 200)] private string $name; #[ORM\Column(length: 100, nullable: true)] private ?string $code; // کد انگلیسی برای فیلتر // نوع دسته: tag, supplementary_insurance, insurance_type, // state, city, specially_doctor, doctor_services #[ORM\Column(length: 50)] private string $type; #[ORM\ManyToOne(targetEntity: self::class)] #[ORM\JoinColumn(nullable: true)] private ?Category $parent; // برای رابطه استان-شهر #[ORM\Column(type: 'integer', default: 0)] private int $sortOrder = 0; // TimestampableTrait } ``` ## Routing نمونه ```php // GET /api/v1/categorys/{type} #[Route('/api/v1/categorys/{type}', methods: ['GET'])] public function listByType(string $type): Response { $allowed = ['tag', 'supplementary_insurance', 'insurance_type', 'state', 'city', 'specially_doctor', 'doctor_services']; if (!in_array($type, $allowed)) { return $this->notFound(); } return $this->json($this->categoryService->findByType($type)); } ```