PHP के लिए LINQ। भाग 1. मैंने उसे आँख बंद कर दी थी, और फिर जो था, फिर मुझे उससे प्यार हो गया

LINQ को PHP में कैसे पोर्ट किया गया इसकी एक कहानी। टैबलेट के साथ मौजूदा पुस्तकालयों की तुलना, लेकिन बिना ग्राफ़ के, संलग्न है।

चित्र कोड ध्यान आकर्षित करने के लिए (आप चित्रों के लिए इंतजार नहीं कर सकते!)
echo Phinq::create($people) ->groupBy(function($person) { return $person->residence->region; }) ->select(function($grouping) { $obj = new stdClass(); $obj->people = $grouping; $obj->region = $grouping->getKey(); return $obj; })->orderBy(function($obj) { return $obj->people->count(); }, true) ->aggregate(function($current, $next) { $count = $next->people->count(); return $current . sprintf( "%d %s (%s) live in the %s region\n", $count, $count === 1 ? 'person' : 'people', $next->people->aggregate(function($current, $next) { if ($current !== null) { $current .= ', '; } return $current . sprintf('%s [%s]', $next->name, $next->residence->code); }), $next->region ); }); 
किसने C # या किसी भी कार्यात्मक भाषा को देखा - इस कृति की दृष्टि से यह अपनी आँखों को रोल करेगा (यदि वे पहले कक्षाओं से बाहर नहीं निकलते हैं)। और, शायद, वह सही होगा। लेकिन आप अभी भी इसे पसंद कर सकते हैं:
 $lowNums = from('$n')->in($numbers)-> where('$n < 5')-> store($digits)->into('digits')-> select('$digits[$n]'); 
आपने सिर्फ LINQ को PHP में पोर्ट करने वाले चिड़ियाघर के पुस्तकालयों से दो जानवरों को देखा। LINQ वास्तव में Language Integrated Query है, यानी SQL- जैसे क्वेरीज़ भाषा में एकीकृत है। C # में, LINQ वाक्यात्मक पेड़ों पर निर्भर करता है और इसमें लेखन के दो रूप हैं, लेकिन चूंकि हमें अगली सहस्राब्दी के लिए PHP में ऐसे बाउबल्स के लिए इंतजार नहीं करना पड़ता है, इसलिए हम मानते हैं कि LINQ विशेष रूप से SQL जैसी विधियों वाला एक पुस्तकालय है।

LINQ को PHP में porting करने वाले बहुत सारे पुस्तकालय हैं। यदि केवल एक ही वास्तव में इसे चित्रित करता है ... लेकिन उस पर और बाद में, लेकिन अब के लिए, वर्णमाला के क्रम में, हम सभी उपलब्ध विकल्पों पर विचार करते हैं। पढ़ना या तो अनुक्रमिक या अंत से माना जाता है।

PHP के लिए LINQ

यह एक व्यक्ति द्वारा लिखा गया था, जो किसी भी भाषा को अपने पसंदीदा में रीमेक करने के लिए तैयार है (ऐसा इसलिए हुआ कि उसके लिए - सी #), फिर चाहे उसका कोड कितना भी अजीब क्यों न हो। LinqSamples.php को देखते हुए आत्मा में पहला संदेह
 class Console { public static function WriteLine() { $args = func_get_args(); $string = array_shift($args); foreach ($args as $i => $value) { if (is_bool($value)) { $value = $value ? 'True' : 'False'; } $string = str_replace('{'.$i.'}', $value, $string); } echo $string.'<br />'; } ... 
आप मानते हैं कि इस दृष्टिकोण के साथ, LINQ को पोर्ट किया जाना मूल से अलग करना मुश्किल होगा? और आप सही होंगे। यह था (C #):
 from n in new int[] { 1, 2, 3 } where n % 2 == 0 select n * 2; 
बन गए (PHP):
 from('$n')->in(array(1,2,3))->where('$n % 2 == 0')->select('$n *2'); 
यह सुंदर लग रहा है।

गीतात्मक विषयांतर। क्यों लाइनें? <मेरे पसंदीदा IDE> में उनका कोड समान नहीं है! लेकिन क्या refactoring के बारे में? लेकिन चश्मे के बारे में क्या? लेकिन कोई रास्ता नहीं। कोई हाइलाइटिंग नहीं है, कोई रिफैक्टरिंग नहीं है, छोटे लोग दावत पर राज करते हैं। PHP का क्लोजर सिंटैक्स इतना वर्बोज़ है ( function ($x) { return $x + 1; } साथ x => x + 1 ( x => x + 1 तुलना करें function ($x) { return $x + 1; } )) जो लगभग सभी LINQ पोर्ट डेवलपर्स अपने "लाइन लैम्ब्डा" का आविष्कार करते हैं। कहीं आप क्लोजर का उपयोग कर सकते हैं, कहीं - कहीं फंकी "फंक्शन पॉइंटर्स" (स्ट्रिंग्स 'strlen' और 'strlen' एरे array($object, 'methodName') ), कहीं - कहीं लंबोदर, कहीं - और वह, दोनों दूसरे और तीसरे। PHP के लिए LINQ में सभी विकल्प उपलब्ध हैं।

चलो पुस्तकालय प्रकार देखें। LinqForPhp_Objects_Sequence :: doIteration पद्धति में "मांस" छिपा हुआ है: जब getIterator () कहा जाता है, तो ऑपरेशन सरणी में टाइप किए गए सभी ऑपरेशन क्रमिक रूप से निष्पादित किए जाते हैं। परिचालन क्रमिक रूप से किया जाता है, बिना श्रृंखला "आलस्य" के साथ, अर्थात, जहां () -> कोई भी () पूरे क्रम को फ़िल्टर करेगा। पहली कॉल के बाद, परिणाम कैश किया जाता है।

लेखक से PHPDoc में टिप्पणियां जोड़ने का आग्रह किया गया था, लेकिन लंबे समय तक यह पर्याप्त नहीं था: कोड का पांचवां हिस्सा सबसे अच्छे रूप में प्रलेखित है। हां, और PHPDoc के सिंटैक्स को लेखक द्वारा नहीं लिखा गया था - एक परम का तर्क नाम नहीं है।

मानक विधियाँ कार्यान्वित की जाती हैं: एग्रीगेट, ऑल, कास्ट, डिफॉल्ट इम्प्टी, को छोड़कर, फ़र्स्टऑडफॉल्ट, ग्रुपबी, ऑर्डरबी, रिवर्स, सिंगल, टेक, आदि। कुल लगभग 50 टुकड़े। पूर्व-संग्रह संग्रहों के सूची, शब्दकोश - बंदरगाहों में रूपांतरण है, जिसमें कुछ अज्ञात कारण के तरीकों का हिस्सा NotImplementedException फेंकता है, और ऑफसेट एक्सपिस्ट्स array_key_exists($index) (इसे पढ़ें array_key_exists($index) रूप में कार्यान्वित किया जाता है। मैं सवाल का जवाब छोड़ देता हूं, इन संग्रह की आवश्यकता क्यों है?

आईडीई के पास क्या नहीं था, यह बहुत अच्छा लगता है - PhpStorm तुरन्त स्पष्ट बग प्रदर्शित करता है। टुकड़ों में परीक्षण: शून्य बिंदु शून्य।

नीचे पंक्ति: एक जिज्ञासु वाक्यविन्यास, कोई आलसी गणना नहीं है, कोई परीक्षण नहीं है, कोई प्रलेखन नहीं है, कमबख्त संग्रह हैं, बगों का एक गुच्छा है। यह उपयोग के लिए अनुशंसित नहीं है।

Phinq

यह एक ऐसे व्यक्ति द्वारा लिखा गया था जो एक अजीब उज्ज्वल भविष्य में विश्वास करता है। कार्यों को स्वीकार करने वाले सभी तर्कों को क्लोजर प्रकार पर प्रतिबंध है; तुलनित्र (तुलनाकर्ता) - EqualityComparer इंटरफेस, आदि; संग्रह में एक सरणी है। यह कुछ इस तरह दिखता है:
  public function groupJoin(array $collectionToJoinOn, Closure $innerKeySelector, Closure $outerKeySelector, Closure $resultSelector, EqualityComparer $comparer = null) 
पहली नज़र में यह तर्कसंगत है, लेकिन यहाँ आपको याद है कि ... बंद होने के अलावा, मूल पंजे की तरह "फंक्शन पॉइंटर्स" होते हैं जो स्ट्रिंग्स और सरणियों के रूप में होते हैं [ऑब्जेक्ट, मेथड नेम], और वे अचानक जंगल से गुजरते हैं। EqualityComparer इंटरफ़ेस में केवल एक समान विधि है (हैश पाने का कोई तरीका नहीं है: यह देशी पोकेशेश एसोसिएटिव सरणियों के आंतरिक की देखभाल है)। और प्रत्येक तुलना के लिए, कृपया एक नया वर्ग बनाएं, आप फ़ंक्शन पास नहीं करेंगे। GroupJoin में, Phinq क्वेरी निष्पादन के परिणामों को पास करना तर्कसंगत है, और उनका प्रकार एक सरणी नहीं है। और SPL इंटरफेस जैसे Iterator और IteratorAggregate अचानक या तो सरणियाँ नहीं हैं। जब तक आप संख्याओं के उदाहरणों के ढांचे के भीतर रहते हैं और जहां-जहां से चयन करते हैं - सब ठीक है। जैसा कि आप कठोर वास्तविकता का सामना करते हैं - यह कठिन हो जाता है।

सभी तरीके PHPDoc प्रलेखन का पता लगाते हैं। ईमानदारी से प्रत्येक विधि के लिए स्वतंत्र रूप से लिखा गया है। खैर, लगभग ईमानदारी से - कुछ जगहों पर आप कॉपी-पेस्ट महसूस कर सकते हैं, जो झूठ की ओर जाता है:
 /** * Correlates elements into groupings of the two collections based on matching keys * * This is basically an outer join. * * @param array $collectionToJoinOn * @param Closure $innerKeySelector Takes one argument, the element's value, and returns the join key for that object * @param Closure $outerKeySelector Takes one argument, the element's value, and returns the join key for that object * @param Closure $resultSelector Takes two arguments, the matching elements from each collection, and returns a single value * @param EqualityComparer $comparer * @return Phinq */ public function groupJoin(... 
क्या आप समझते हैं कि एक फ़ंक्शन क्या करता है? और क्या स्वीकार करता है और परिणाम लौटाता है? यदि आप समझते हैं, तो आपने ऊपर दस्तावेजी टिप्पणी नहीं पढ़ी है, आपने सिर्फ C # में एक बार GroupJoin का उपयोग किया है।

कार्यान्वित मानक विधियाँ, कुल 50 टुकड़े, लेकिन किसी भी तरह से आलस्य को लागू किया गया। किसी कारण से एकल अपवाद को फेंकता है यदि संग्रह में एकमात्र तत्व शून्य है। किसी कारण से एरर्स को चाबियों के बारे में जानकारी दी जाती है। Iterators को तुरंत Phinq ऑब्जेक्ट बनाते समय सरणियों में परिवर्तित किया जाता है (कुंजी के बारे में जानकारी के बिना भी, निश्चित रूप से)। आउटपुट में कुंजियों के साथ कुछ प्राप्त करने का एकमात्र तरीका इसे शब्दकोश संग्रह में बदलना है, जिसमें ओ (एन) मूल्य के साथ ऑफसेटगेट और ऑफसेटसेट कार्यान्वयन है। पिछले पुस्तकालय के विपरीत, देवताओं का धन्यवाद, कम से कम सूची को लागू नहीं किया गया है (क्रमशः विधि, क्रमशः, नहीं)।

गणना के सभी आलस्य, जैसा कि पिछले पुस्तकालय के मामले में है, परिणाम को कैशिंग करने के लिए नीचे आता है।

पुस्तकालय में क्या अच्छा है? परीक्षण हैं। उर। सतही, बिल्कुल। सबसे अच्छे मामले में, प्रति विधि टुकड़ों की एक जोड़ी। बिना किसी सीमा के मामले। लेकिन परीक्षण हैं। यह अच्छा है।

परिणाम: तर्कों के प्रकारों पर क्रूर प्रतिबंध हैं, कोई कुंजी नहीं है, सतह परीक्षण हैं, सतह प्रलेखन है, कुछ कीड़े हैं, एक कमबख्त संग्रह है। यह उपयोग के लिए अनुशंसित नहीं है।

Phinq 2.0

यह एक ऐसे व्यक्ति द्वारा लिखा गया था जो उज्ज्वल भविष्य से मोहभंग हो गया था: हेलो टू स्ट्रिंग लंबोदा, अब तक फ़ंक्शन तर्कों पर प्रतिबंध। हालांकि एकमात्र विधि के साथ EqualityComparer अभी भी हमारे साथ है। SQL क्वेरी बनाने के लिए SQL में सीज़निंग के साथ शीर्ष। PHP के रूप में PHP द्वारा पार्सिंग के अपवाद के साथ "Phinq के लिए ऊनी बूलियन ऑपरेटर की आवश्यकता होती है ('!') कोष्ठक में संलग्न अभिव्यक्ति द्वारा पालन किया जाना चाहिए।" हम लंबे समय तक लिखेंगे ...

... और, ज़ाहिर है, हम नहीं जोड़ेंगे। एक नए तरीके से पुराने फिन्क को फिर से लिखने के लिए, लेखक ने एक कील लगाई। एक दूरस्थ सर्वर पर SVN में शाखा / शाखा / 2.0 एक उज्ज्वल शुरुआत और एक दुखद अंत का एकमात्र उल्लेख है।

नीचे पंक्ति: कुछ भी नहीं है, हम पास से गुजरते हैं। यह उपयोग के लिए अनुशंसित नहीं है।

PHPLinq

यह एक ऐसे व्यक्ति द्वारा लिखा गया था जो मानता है कि किसी को एक और डीएएल की आवश्यकता है, और जिसके पास मूल LINQ की क्षमताओं का अस्पष्ट विचार है। उनकी समझ में, जहां कार्य, आदेश, चयन, स्किप, टेक और बाकी को किसी भी क्रम में बुलाया जा सकता है जो कोई फर्क नहीं पड़ता, क्योंकि उनके आवेदन का क्रम कसकर सेट किया गया है (और, वैसे, कहीं भी प्रलेखित नहीं है)। उनकी समझ में, बंद करने के लिए किसी को भी एक अनावश्यक newfangled बाउबल हैं। उनकी समझ में, सिंगल और फर्स्ट एक ही चीज हैं। उनकी समझ में, परीक्षण PHP स्क्रिप्ट हैं जो print_r कह रहे हैं। उनकी समझ में, दस्तावेजी टिप्पणियां एक कॉपी की गई विधि का नाम और तर्क प्रकारों की गणना है। उनकी समझ में, प्रोजेक्ट प्रलेखन VisualStudio के लिए एक प्रारूप में एक वर्ग आरेख है।

बेशक, मैं LINQ से ऑब्जेक्ट्स, LINQ to ZendDb, LINQ to Azure, LINQ to MS SQL, LINQ to MySQL, LINQ to SQLite को सपोर्ट के बारे में बात कर सकता हूं। लेकिन अगर इस लाइब्रेरी को कम-कोड कोड की आवश्यकता है, जो सभी को विविधता की आवश्यकता है, जिसका सामान्य रूप से कार्यात्मक प्रोग्रामिंग से कोई लेना-देना नहीं है, या LINQ विशेष रूप से, प्रलेखन के बिना, परीक्षणों के बिना?

नीचे पंक्ति: LINQ * की महाकाव्य राशि, बाकी सब की महाकाव्य कमी। यह उपयोग के लिए अनुशंसित नहीं है।

(चौकस पाठक शायद पहले से ही आश्चर्यचकित होना शुरू कर रहा है: कब कुछ सिफारिश की जाएगी? कब? हम इंतजार कर रहे हैं, हम ... हम विश्वास करते हैं। और हम आगे पढ़ते हैं।)

Plinq

यह एक न्यूनतम व्यक्ति द्वारा लिखा गया था जो वास्तव में PHP में LINQ करना चाहता था, लेकिन जो कोड के लिए बहुत आलसी था। इसलिए, 20 से अधिक तरीकों का समर्थन किया जाता है, जिनके बीच न तो थेनबी है और न ही एग्रीगेट। आलसी कंप्यूटिंग बिल्कुल नहीं है। कोई लाइन "लंबदा" नहीं हैं - केवल क्लोजर, केवल हार्डकोर (PHP में तर्कों के प्रकार और वर्तमान बग पर प्रतिबंधों की अनुपस्थिति को देखते हुए, लाइन "पॉइंटर्स टू फ़ंक्शन" भी काम करना चाहिए)। एग्रीगेटर कार्यों के लिए पासिंग अनिवार्य है। अधिकांश भाग के लिए, प्लिनक विधि मानक कार्यों पर आवरण हैं, और आगे और पीछे चलने वालों के बीच रूपांतरण।

पुस्तकालय कितना अच्छा है? परीक्षणों की एक झलक है - प्रति फ़ंक्शन assert'ov की एक जोड़ी। यह कुछ इस तरह दिखता है:
 function TestOrderBy(&$testArray) { $p = new Plinq($testArray); $result = $p->OrderByDescending(function($k, $v){ return $v['int']; }); assert('key($result) == "key_999"'); $p = new Plinq($testArray); $result = $p->OrderByDescending(function($k, $v){ return $v['date']; }); assert('key($result) == "key_999"'); $p = new Plinq($testArray); $result = $p->OrderBy(function($k, $v){ return $v['string']; }); assert('key($result) == "key_0"'); } 
($ TestArray के बारे में न पूछें - मैंने इसे यहां नहीं दिया है। मैं सिर्फ इतना कहूंगा कि यह 138057 वर्णों की एक-पंक्ति वाली अंजीर-स्ट्रिंग है, जो मेरी IDE को गियर से मुक्त कर देती है। मैंने सरणी की प्रकृति का अध्ययन नहीं किया है।)

डॉक्यूमेंट्री टिप्पणियों से दूर से कुछ मिलता है। उनसे आप पता लगा सकते हैं कि डिफ फ़ंक्शन "विभिन्न मदों को ढूँढता है" (और आप यह नहीं कह सकते कि आपने झूठ बोला था)।

निचला रेखा: कोई खनिज नहीं है, कोई पानी नहीं है, कोई वनस्पति नहीं है, यह आबादी है ... लेकिन यह किसी भी चीज से आबाद नहीं है। यह उपयोग के लिए अनुशंसित नहीं है।

वह सब है। सिनेमा खत्म हो गया। PHP में LINQ पोर्ट खत्म हो गए हैं।

... ठीक है, ठीक है, इसलिए इस तरह के एक उदास नोट पर समाप्त नहीं होने के लिए, हम लाइब्रेरी का उल्लेख करते हैं, जो कि एक LINQ पोर्ट नहीं है। लेकिन मछलीहीनता और पाईक मछली हैं।

Underscore.php

यह एक व्यक्ति द्वारा लिखा गया था जो वास्तव में अंडरस्कोर को पसंद करता था। जेएस (धन्यवाद, आपका केओ)।

अंडरस्कोर.जे क्या है? यह एक पुस्तकालय है जो जावास्क्रिप्ट में सभी कार्यक्षमता को लागू करता है। क्या नाम, मानचित्र, फ़िल्टर, कम, समतल, समय आपको कुछ बताते हैं? यदि नहीं, तो आपको यह याद रखना होगा कि मानचित्र का चयन करना है, कम करना समग्र है, समय दोहराना है, आदि। सामान्य तौर पर, LINQ को दृढ़ता से याद दिलाता है, लेकिन ऐसा नहीं है। कोई आलसी गणना नहीं है।

Underscore.php, तदनुसार, PHP में Underscore.js पोर्ट है। पुस्तकालय इतने संबंधित हैं कि यहां तक ​​कि संस्करण संख्याएं भी सिंक्रनाइज़ हैं।

कोई दस्तावेजी टिप्पणी नहीं है। प्रत्येक विधि पर नियमित, संक्षिप्त, हाथ पर हैं। असुविधाजनक, निश्चित रूप से, लेकिन आप रह सकते हैं। साइट पर अभी भी प्रलेखन है, काफी अधिक समझदार।

परीक्षण हैं: दोनों Underscore.js से कॉपी किए गए हैं, और अतिरिक्त हैं।

कोड की गुणवत्ता लंगड़ी है। स्थैतिक कार्यों को स्थैतिक के रूप में चिह्नित नहीं किया जाता है। कॉलबैक को $ f () कहा जाता है, यानी आप फ़ंक्शन पॉइंटर एरेज़ के बारे में भूल सकते हैं (PHP में ऐसी कोई खराबी है)। लंबोदर समर्थित नहीं हैं।

आपका कोड कुछ इस तरह दिखाई देगा:
 $numbers = __($numbers)->chain() ->select(function($n) { return $n % 2 === 0; }) ->reject(function($n) { return $n % 4 === 0; }) ->sortBy(function($n) { return -$n; }) ->value(); 

नीचे पंक्ति: अन्य विधियों के नाम हैं, कोई दस्तावेजी टिप्पणियां नहीं हैं, परीक्षण हैं, कोई लंबदा नहीं हैं। उपयोग के लिए अनुशंसित है, लेकिन केवल कार्यात्मक प्रोग्रामिंग के लिए तीव्र आग्रह के साथ।

अंतिम परिणाम

थाली:



नीचे पंक्ति: लेख के दूसरे भाग की प्रतीक्षा करें, "खुद को मूंछों के साथ।"

कीड़े

जबकि सार और बिंदु, आप बग और सुविधाओं के लिए वोट कर सकते हैं जो ऐसे पुस्तकालयों में थोड़ा कम दुःस्वप्न में विकास करेंगे।

पीएचपी

  1. Iterator :: key () को केवल संख्या और स्ट्रिंग्स को वापस करने की अनुमति है।
    1. 45684 कुंजी-प्रकार के अज्ञेय होने के लिए फोरचेक के लिए एक अनुरोध
  2. क्लोजर के सिंटैक्स को छोटा करने के साथ एक विशेषता थी, और पैच, विश्लेषण, आदि संलग्न थे - डेवलपर जिसने सुविधा को डिजाइन किया था उसने अपना सर्वश्रेष्ठ प्रदर्शन किया। लेकिन परिणाम "नेफिग नीड" के साथ बंद कर दिया गया था। :-(

PHPStorm IDE

  1. लाइनों के अंदर PHP कोड
    • WI-3477 मुखर ('शाब्दिक') के अंदर PHP भाषा को बाहर निकालना, समान और समान
    • WI-2377 इंजेक्शन भाषा के साथ स्ट्रिंग के अंदर php चर के लिए कोई स्वत: पूर्णता नहीं है
  2. PHP कोड विश्लेषण
    • WI-11110 अनिर्धारित विधि: बंद का उपयोग करते समय गलत तरीके से अपरिभाषित विधि
  3. PHPDoc टिप्पणियाँ
    • WI-8270 PhpDoc त्वरित प्रलेखन में त्रुटि अगर {लिंक} एक लाइन में दो बार उपयोग की जाती है

संदर्भ


PS मुझे बताएं, कृपया, जहां आप अंग्रेजी में एक समान लेख पोस्ट कर सकते हैं।

Source: https://habr.com/ru/post/In147612/


All Articles