वनीला PHP में CQRS की शुरुआत: फ्रेमवर्क के बिना कमांड और रीड को अलग करें
हर जगह CQRS का ज़िक्र सुनते-सुनते थक गए हैं लेकिन सोचते हैं कि Symfony या Laravel उठाए बिना इसे कैसे लागू करें? अच्छी खबर यह है कि हम सिर्फ वनीला PHP में Command Query Responsibility Segregation को देख सकते हैं। ज़रूरत बस एक साफ-सुथरी संरचना और कुछ सोची-समझी क्लास की है। अपना एडिटर खोलिए, हम मिलकर नींव तैयार करते हैं।
पूर्वापेक्षाएँ: PHP 8.4 और न्यूनतम सेटअप
- PHP 8.4 इंस्टॉल हो (CLI या वेब सर्वर)।
php -vसे वर्ज़न जाँचें ताकिreadonlyप्रॉपर्टी, स्ट्रिक्ट टाइप्स और फर्स्ट-क्लास कॉलएबल का लाभ ले सकें। - Composer (ऑटोलोडिंग के लिए उपयोगी, हालांकि वैकल्पिक) और एक हल्का वेब सर्वर (
php -S 127.0.0.1:8000 -t publicप्रयोग के लिए पर्याप्त है)।
यदि आपको पुराने वर्ज़न पर रहना है तो सुनिश्चित करें कि यहाँ इस्तेमाल की गई सुविधाएँ (कंस्ट्रक्टर प्रमोशन, readonly प्रॉपर्टी आदि) उपलब्ध हों, या फिर स्निपेट्स को उसी अनुसार समायोजित करें।
1. दो मिनट में CQRS
CQRS का मतलब है रीड (Query) और राइट (Command) को अलग करना। इससे दो अनुकूलित मार्ग तैयार होते हैं:
- कमांड्स स्टेट बदलते हैं (खाता बनाना, लेख प्रकाशित करना) और एप्लिकेशन डेटा वापस नहीं करते।
- क्वेरीज़ स्टेट को पढ़ती हैं (लेख सूची, किसी खाते का विवरण) और कोई साइड इफ़ेक्ट नहीं होता।
यह विभाजन DDD की सोच से आता है, लेकिन बिना भारी-भरकम औपचारिकता के भी अपनाया जा सकता है। तुरंत मिलने वाले फायदे:
- टेस्ट आसान हो जाते हैं: हैंडलरों को अलग से यूनिट टेस्ट कर सकते हैं।
- कोड स्पष्ट रहता है: हर हैंडलर एक ही काम पर फोकस करता है।
- धीरे-धीरे स्केल कर सकते हैं: रीड और राइट साइड को अलग-अलग विकसित कर सकते हैं।
ध्यान रखें कि CQRS कुछ अतिरिक्त संरचनात्मक जटिलता लाता है। साधारण CRUD के लिए यह ज़रूरत से ज़्यादा हो सकता है। तब ही अपनाएँ जब बिज़नेस नियम या स्केलेबिलिटी की ज़रूरत इसे सही ठहराए।
2. PHP में न्यूनतम फोल्डर संरचना
एक साधारण पेड़-ढांचे से काम चल जाएगा:
src/
Domain/
Article.php
ArticleRepository.php
Application/
Command/
CreateArticle/
CreateArticleCommand.php
CreateArticleHandler.php
Query/
ListArticles/
ListArticlesQuery.php
ListArticlesHandler.php
Bus/
CommandBus.php
QueryBus.php
Infrastructure/
InMemoryArticleRepository.php
public/
index.php
यहाँ हम Domain (बिज़नेस नियम), Application (उपयोग केस) और Infrastructure (कंक्रीट इम्प्लीमेंटेशन) को साफ़ तौर पर अलग रखते हैं।
3. न्यूनतम डोमेन मॉडल
अब Article एग्रीगेट और उसका रिपॉज़िटरी बनाएँ:
php
php
4. कमांड साइड: लेख बनाना
कमांड इरादा लेकर आती है। हैंडलर बिज़नेस लॉजिक को व्यवस्थित करता है।
php
php
महत्वपूर्ण नोट: हैंडलर कुछ भी रिटर्न नहीं करता। लेख को दोबारा पढ़ना है तो Query का उपयोग करें।
5. क्वेरी साइड: लेख सूची दिखाना
php
php
हम ऐसा एरे लौटाते हैं जिसे सीधे सीरियलाइज़ किया जा सके, ताकि प्रेज़ेंटेशन लेयर डोमेन मॉडल पर निर्भर न हो।
6. शुरुआत के लिए इन-मेमोरी रिपॉज़िटरी
php
बाद में चाहें तो Doctrine, PDO या किसी बाहरी API से इसे बदल सकते हैं—हैंडलरों को छुए बिना।
7. अल्ट्रा-लाइट बस सेटअप करना
हैंडलर रिज़ॉल्यूशन को केंद्रीकृत करते ही CQRS का स्वाद आता है:
php
php
ये बस अभी साधारण हैं लेकिन अवधारणा समझने को पर्याप्त हैं। वास्तविक प्रोजेक्ट में इन्हें PHP-DI या Symfony DI जैसे डिपेंडेंसी इंजेक्शन कंटेनर से जोड़ सकते हैं।
8. public/index.php में बूटस्ट्रैप उदाहरण
php
(...) ऑपरेटर (first-class callable) PHP 8.1 से उपलब्ध है और PHP 8.4 में पूरी तरह समर्थित है। यदि आपको 8.0 या उससे नीचे को सपोर्ट करना है, तो इसे fn ($command) => $createHandler($command) से बदल दें।
9. क्रमशः आगे बढ़ें
जब नींव तैयार हो जाए तो समाधान को आगे बढ़ाएँ:
- मान्यकरण: Value Objects (Title, Content) जोड़ें या एग्रीगेट बनाने से पहले Symfony Validator का उपयोग करें।
- वास्तविक परसिस्टेंस: MySQL (PDO) या PostgreSQL रिपॉज़िटरी इम्प्लीमेंट करें बिना हैंडलरों को बदले।
- डोमेन इवेंट्स: कमांड सफल होने पर
ArticlePublishedइवेंट निकालें और दूसरे लेयर में हैंडल करें। - समर्पित प्रोजेक्शन: रीड-ऑप्टिमाइज़्ड टेबल बनाएं ताकि भारी क्वेरी (पेजिनेशन, फुल-टेक्स्ट सर्च) संभाली जा सके।
- टेस्टिंग: हर हैंडलर के यूनिट टेस्ट और बस के फंक्शनल टेस्ट लिखें।
10. पहली प्रोडक्शन रिलीज़ से पहले चेकलिस्ट
- हर कमांड का अपना समर्पित हैंडलर है जो कुछ वापस नहीं करता।
- हर क्वेरी अलग-थलग है और फ्रंटएंड के लिए डेटा तैयार करती है।
- तकनीकी निर्भरताएँ बाहरी स्रोत से इंजेक्ट होती हैं।
- बिज़नेस त्रुटियों को डोमेन में संभाला जाता है (विशेष अपवाद, Value Objects आदि)।
- टेस्ट कमांड, क्वेरी और बस—सभी को कवर करते हैं।
इस ढाँचे के साथ आप मौजूदा प्रोजेक्ट में धीरे-धीरे CQRS शामिल कर सकते हैं या बिना किसी फ्रेमवर्क के नया सर्विस शुरू कर सकते हैं। बस रीड और राइट की सीमा को स्पष्ट रखें और आर्किटेक्चर को चरण दर चरण विकसित करते रहें। सुखद प्रयोग की शुभकामनाएँ!