जब आपका PHP मोनोलिथ जोड़ों से टूटने लगता है
\nक्या आप कभी ऐसी स्थिति में रहे हैं जहाँ MySQL से PostgreSQL में डेटाबेस बदलना एक सप्ताह के क्वेस्ट में बदल गया? या जब एक नया API क्लाइंट जोड़ना आवश्यक था, और कोड फ्रेमवर्क से इतना उलझा हुआ था कि सब कुछ शुरू से लिखना आसान था? परिचित लगता है?
\nअधिकांश PHP डेवलपर्स देर-सबेर कंट्रोलर और मॉडल में "लापशा" का सामना करते हैं। Laravel या Symfony जैसे फ्रेमवर्क सुविधाजनक उपकरण देते हैं, लेकिन वे अपने साथ एक मजबूत निर्भरता भी थोपते हैं। एक समाधान है — हेक्सागोनल आर्किटेक्चर (जिसे "पोर्ट और एडेप्टर" या हेक्सागोनल आर्किटेक्चर भी कहा जाता है)।
\nइस लेख में, हम PHP पर एक ऐसा एप्लिकेशन बनाने का तरीका समझेंगे जो फ्रेमवर्क, डेटाबेस या बाहरी सेवाओं पर निर्भर नहीं करता। आप कोड उदाहरण देखेंगे जिन्हें आप तुरंत अपने प्रोजेक्ट में लागू कर सकते हैं। चलिए शुरू करते हैं!
\n\nहेक्सागोनल आर्किटेक्चर क्या है और आपको इसकी आवश्यकता क्यों है?
\nएक षट्भुज की कल्पना करें। केंद्र में आपका व्यावसायिक तर्क (डोमेन) है। चारों ओर "पोर्ट" (इंटरफेस) हैं जिनके माध्यम से बाहरी दुनिया कोर के साथ संवाद करती है। और बाहर "एडेप्टर" हैं जो इन पोर्ट को लागू करते हैं: कंट्रोलर, रिपॉजिटरी, API क्लाइंट।
\nमुख्य विचार: एप्लिकेशन का कोर बाहरी दुनिया के बारे में कुछ नहीं जानता। यह Laravel को इम्पोर्ट नहीं करता, PDO के बारे में नहीं जानता, और curl को कॉल नहीं करता। सारी निर्भरता अंदर की ओर निर्देशित होती है — एडेप्टर पोर्ट पर निर्भर करते हैं, न कि इसके विपरीत।
\nइस दृष्टिकोण के लाभ स्पष्ट हैं:
\n- \n
- परीक्षण क्षमता: व्यावसायिक तर्क को डेटाबेस और HTTP अनुरोधों के बिना परीक्षण किया जा सकता है। \n
- लचीलापन: DB, कतार या फ्रेमवर्क को बदलना — बस एक नया एडेप्टर लिखना है। \n
- कोड की स्वच्छता: आप "क्या करना है" को "कैसे करना है" के साथ नहीं मिलाते। \n
जादू जैसा लगता है? आइए कोड देखें।
\n\nप्रोजेक्ट संरचना: बुनियादी ढाँचा
\nउदाहरण के लिए, एक सरल परिदृश्य लेते हैं: उपयोगकर्ता पंजीकरण। हमें उपयोगकर्ता को DB में सहेजना और एक स्वागत ईमेल भेजना है।
\nयहाँ एक विशिष्ट निर्देशिका संरचना होगी:
\nsrc/\n├── Domain/\n│ ├── Entity/\n│ │ └── User.php\n│ ├── Repository/\n│ │ └── UserRepositoryInterface.php\n│ ├── Service/\n│ │ └── UserRegistrationService.php\n│ └── Event/\n│ └── UserRegisteredEvent.php\n├── Infrastructure/\n│ ├── Persistence/\n│ │ └── DoctrineUserRepository.php\n│ ├── Mail/\n│ │ └── SymfonyMailerAdapter.php\n│ └── Controller/\n│ └── RegisterUserController.php\n└── Application/\n └── UseCase/\n └── RegisterUserUseCase.php\nध्यान दें: Domain — शुद्ध व्यावसायिक तर्क है। Infrastructure — एडेप्टर हैं। Application — उपयोग के मामले (use cases) हैं।
चरण 1: कोर — डोमेन और पोर्ट
\nएंटिटी (Entity)
\nसबसे सरल से शुरू करते हैं — उपयोगकर्ता। यह बिना किसी निर्भरता के डेटा वाला एक क्लास है।
\n<?php\nnamespace App\\Domain\\Entity;\n\nclass User\n{\n public function __construct(\n private readonly string $id,\n private string $name,\n private string $email\n ) {}\n\n public function getId(): string\n {\n return $this->id;\n }\n\n public function getName(): string\n {\n return $this->name;\n }\n\n public function getEmail(): string\n {\n return $this->email;\n }\n}\n\nपोर्ट — रिपॉजिटरी इंटरफ़ेस
\nअब हम परिभाषित करते हैं कि हम उपयोगकर्ता को कैसे सहेजेंगे। यह एक पोर्ट है — एक इंटरफ़ेस जिसे एडेप्टर द्वारा लागू किया जाएगा।
\n<?php\nnamespace App\\Domain\\Repository;\n\nuse App\\Domain\\Entity\\User;\n\ninterface UserRepositoryInterface\n{\n public function save(User $user): void;\n public function findByEmail(string $email): ?User;\n}\n\nपोर्ट — मेल सेवा इंटरफ़ेस
\nईमेल भेजने के लिए इसी तरह:
\n<?php\nnamespace App\\Domain\\Service;\n\nuse App\\