परिचय: PHP डेवलपर्स जेनेरिक्स का सपना क्यों देखते हैं
\n\nयदि आपने कभी Java, C# या TypeScript में लिखा है और फिर PHP पर वापस आए हैं, तो आपने निश्चित रूप से हल्की निराशा महसूस की होगी। उन भाषाओं में सामान्यीकृत प्रकारों (Generics) की एक सुंदर प्रणाली है, जो लचीली लेकिन प्रकारों की दृष्टि से सुरक्षित डेटा संरचनाएँ बनाने की अनुमति देती है। PHP में लंबे समय तक "टाइपिज़ेशन अराजकता" का राज था: ऐरे में कुछ भी हो सकता था, और IDE केवल सबसे स्पष्ट त्रुटियों को ही हाइलाइट करता था।
\n\nलेकिन समय बदल रहा है। PHP 7.0 से शुरू होकर और विशेष रूप से PHP 8.0/8.1/8.2 के युग में, समुदाय ने PHP में Generics का उपयोग करने का एक तरीका खोज लिया है। हाँ, भाषा के सिंटैक्स स्तर पर वे अभी भी मौजूद नहीं हैं (और संभवतः आने वाले वर्षों में नहीं होंगे), लेकिन इसका मतलब यह नहीं है कि आप आज ही सामान्यीकृत प्रोग्रामिंग के सभी लाभों का उपयोग नहीं कर सकते।
\n\nइस लेख में, हम देखेंगे कि Generics के साथ PHP में टाइपिज़ेशन कैसे काम करता है, इसके लिए कौन से उपकरण मौजूद हैं (PHPStan, Psalm), और ऐसा कोड कैसे लिखें जो एक साथ लचीला और सुरक्षित हो। तैयार हो जाइए — यह गर्म होने वाला है!
\n\nGenerics क्या हैं और PHP में उनकी आवश्यकता क्यों है?
\n\nGenerics (सामान्यीकृत प्रकार) एक तंत्र है जो कक्षाओं, इंटरफेस और फ़ंक्शन को प्रकारों के साथ पैरामीटराइज़ करने की अनुमति देता है। प्रत्येक डेटा प्रकार के लिए अलग-अलग कार्यान्वयन लिखने के बजाय, आप एक सार्वभौमिक कार्यान्वयन बनाते हैं, और उपयोग करते समय विशिष्ट प्रकार को प्रतिस्थापित करते हैं।
\n\nकल्पना करें कि आप एक कतार (Queue) के लिए एक क्लास लिख रहे हैं। जेनेरिक्स के बिना, आप इसमें केवल एक डेटा प्रकार संग्रहीत कर सकते हैं या mixed का उपयोग कर सकते हैं (जो सभी टाइपिज़ेशन को नष्ट कर देता है)। Generics के साथ, आप कह सकते हैं: "यह पूर्णांकों की कतार है" या "यह User ऑब्जेक्ट्स की कतार है"।
"कच्चे" टाइपिज़ेशन की समस्या
\n\nइस विशिष्ट PHP कोड को देखें:
\n\n<?php\n\nclass Collection {\n private array $items = [];\n\n public function add($item): void {\n $this->items[] = $item;\n }\n\n public function get(int $index) {\n return $this->items[$index] ?? null;\n }\n}\n\n$users = new Collection();\n$users->add(new User('Alice'));\n$users->add(new User('Bob'));\n$users->add('यह एक स्ट्रिंग है, उपयोगकर्ता नहीं'); // त्रुटि! लेकिन PHP चुप रहेगा\n\n$user = $users->get(2); // स्ट्रिंग लौटाएगा, IDE को कुछ संदेह नहीं होगा\n$user->getName(); // रनटाइम पर घातक त्रुटि\n\n\nयह PHP डेवलपर की एक क्लासिक समस्या है: कोड लिखने के चरण में प्रकार नियंत्रण का अभाव। आपको त्रुटि के बारे में केवल रनटाइम पर पता चलता है, जब उपयोगकर्ता पहले ही बटन दबा चुका होता है। Generics इस समस्या को जड़ से हल करते हैं।
\n\nPHP में Generics: यह व्यवहार में कैसे काम करता है
\n\nचूँकि PHP में Generics का मूल सिंटैक्स मौजूद नहीं है, हम PHPDoc में एनोटेशन का उपयोग करते हैं, जिन्हें स्थैतिक विश्लेषकों — PHPStan और Psalm द्वारा संसाधित किया जाता है। ये उपकरण घोषित प्रकारों के अनुपालन के लिए कोड की जाँच करते हैं, वास्तव में जेनेरिक्स के काम का अनुकरण करते हैं।
\n\nमूल सिंटैक्स: टेम्पलेट प्रकार
\n\nमान लीजिए कि हम अपने संग्रह को टाइप-सुरक्षित बनाना चाहते हैं। PHPDoc के माध्यम से Generics का उपयोग करके यह इस प्रकार दिखता है:
\n\n<?php\n\n/**\n * @template T\n */\nclass GenericCollection {\n /** @var array<int, T> */\n private array $items = [];\n\n /**\n * @param T $item\n */\n public function add($item): void {\n $this->items[] = $item;\n }\n\n /**\n * @param int $index\n * @return T|null\n */\n public function get(int $index) {\n return $this->items[$index] ?? null;\n }\n}\n\n// अब उपयोग करें:\n/** @var GenericCollection<User> $users */\n$users = new GenericCollection();\n$users->add(new User('Alice'));\n$users->add('स्ट्रिंग'); // PHPStan त्रुटि देगा: Expected type User, got string\n\n$user = $users->get(0); // PHPStan जानता है कि यह User है\necho $user->getName(); //