PHP: जब सरणियों का उपयोग करना है, और ज्यादातर डेटा-स्टोरिंग कोड के लिए वस्तुओं का उपयोग कब करना है?


37

PHP एक मिश्रित प्रतिमान भाषा है, जो गैर-ऑब्जेक्ट डेटा प्रकारों, जैसे सरणियों का उपयोग और वापस करने की अनुमति देती है। जब कोई प्रोग्रामिंग किसी विशेष स्थिति में उपयोग करने के लिए निर्माण का निर्णय लेती है, तो मैं एरे बनाम ऑब्जेक्ट्स के चयन के लिए कुछ दिशानिर्देशों को स्पष्ट करने का प्रयास करने के लिए एक प्रश्न खड़ा करता हूं।

यह वास्तव में PHP भाषा निर्माणों का उपयोग करके डेटा को एन्कोड करने के तरीकों के बारे में एक सवाल है और जब डेटा पासिंग उद्देश्यों (यानी सेवा-उन्मुख वास्तुकला या वेब सेवाओं) के लिए एक से अधिक तरीके से दूसरे को चुना जाना है।

उदाहरण

मान लें कि आपके पास {cost, name, part_number, item_count} से मिलकर एक आइटम प्रकार है। आपका प्रोग्राम कई ऐसे आइटम प्रकारों को प्रदर्शित करने के लिए कहता है, जहाँ आप प्रत्येक आइटम प्रकार को रखने के लिए बाहरी कंटेनर के रूप में एक सरणी का उपयोग करने का निर्णय लेते हैं। [आप ArrayObjectOO प्रतिमान के लिए PHP का भी उपयोग कर सकते हैं , लेकिन मेरा प्रश्न उस (बाहरी) सरणी के बारे में नहीं है ]। मेरा प्रश्न आइटम प्रकार के डेटा को कैसे एन्कोड करना है, और किस प्रतिमान का उपयोग करना है। PHP आपको उपयोग करने की अनुमति देता है PHP Native Arraysया PHP Objects

मैं इस तरह के डेटा को दो तरीकों से इनकोड कर सकता हूं, जैसे:

//PHP's associative arrays:
$ret = array(
    0 => array(
        'cost' => 10.00, 
        'name' => 'item1',
        'part_number' => 'zyz-100', 
        'item_count' => 15
        ),
    1 => array(
        'cost' => 34.00, 
        'name' => 'item2', 
        'part_number' => 'abc-230', 
        'item_count' => 42
        ),
  );

बनाम

//here ItemType is encapsulated into an object
$ret = array(
  0 => new ItemType(10.00, 'item1', 'zyz-100', 15),
  1 => new ItemType(34.00, 'item2', 'abc-230', 42),
);

class ItemType
{
    private $price;
    private $name;
    private $partNumber;
    private $itemCount;

    function __construct($price, $name, $partNumber, $itemCount) {..}
}

मैं क्या सोच रहा हूँ

ऐरे एन्कोडिंग हल्का-वजन है, और अधिक JSON- तैयार है, लेकिन गड़बड़ करने में आसान हो सकता है। साहचर्य सरणी कुंजियों में से एक गलत वर्तनी और आपके पास एक त्रुटि हो सकती है जिसे पकड़ना अधिक कठिन है। लेकिन फुसफुसाहट पर बदलना भी आसान है। कहो कि मैं item_countअब और स्टोर नहीं करना चाहता , मैं किसी भी टेक्स्ट-प्रोसेसिंग सॉफ्टवेयर का उपयोग करके आसानी item_countसे सरणी में सभी उदाहरणों को हटा सकता हूं और फिर अन्य कार्यों को अपडेट कर सकता हूं जो तदनुसार उपयोग करते हैं। यह एक अधिक थकाऊ प्रक्रिया हो सकती है, लेकिन यह सरल है।

ऑब्जेक्ट ओरिएंटेड एन्कोडिंग आईडीई और पीएचपी भाषा सुविधाओं पर कॉल करता है और पहले से किसी भी त्रुटि को पकड़ना आसान बनाता है, लेकिन पहले स्थान पर प्रोग्राम और कोड करना कठिन है। मैं मुश्किल से कहता हूं, क्योंकि आपको अपनी वस्तुओं के बारे में थोड़ा सोचना होगा, आगे की सोचना होगा, और OO कोडिंग सरणी संरचनाओं को टाइप करने की तुलना में थोड़ा अधिक संज्ञानात्मक भार लेता है। एक बार यह कोडित हो जाने के बाद, कुछ बदलावों को लागू करना आसान हो जाता है, एक अर्थ में, इसे हटाना item_count, उदाहरण के लिए, कोड की कम लाइनों को बदलने की आवश्यकता होगी। लेकिन खुद को बदलने के लिए अभी भी सरणी विधि की तुलना में एक उच्च संज्ञानात्मक भार की आवश्यकता हो सकती है, क्योंकि उच्च-स्तरीय ओओ सुविधाएं शामिल हैं।

सवाल

कुछ मामलों में यह स्पष्ट है, उन मामलों की तरह जहां मुझे डेटा पर हेरफेर करने की आवश्यकता होगी। लेकिन कुछ मामलों में, जहां मुझे "आइटम प्रकार" डेटा की कुछ पंक्तियों को संग्रहीत करने की आवश्यकता होती है, मेरे पास यह स्पष्ट दिशा-निर्देश या विचार नहीं हैं कि जब ऐरे का उपयोग करना है या क्या वस्तुओं का निर्माण करना है, यह तय करने का प्रयास करना है। ऐसा लगता है कि मैं सिर्फ एक सिक्का उछाल सकता हूं और एक चुन सकता हूं। क्या यहाँ भी ऐसा ही है?


2
ध्यान दें कि आप किसी ऑब्जेक्ट को किसी ऑब्जेक्ट को कास्टिंग करके एक हल्की वस्तु प्राप्त कर सकते हैं (object)['foo'=>'bar']:। परिणामी मूल्य में वर्ग है StdClass, JSON द्वारा पूरी तरह से एन्कोड किया json_encode()जाएगा और गुणों को आसानी से सरणी सूचकांकों के रूप में आसानी से बदला जा सकता है (जो हमेशा इतना आसान नहीं होता है, जब इसे एक चर के माध्यम से अप्रत्यक्ष रूप से एक्सेस किया जाता है)। हालांकि, ऐसे मूल्यों पर अलग-अलग संचालन हैं; उदाहरण के लिए, आपके पास ऑब्जेक्ट यूनियन्स नहीं हैं क्योंकि आपके पास सरणी यूनियन हैं, और आप सीधे array_*()फ़ंक्शन का उपयोग नहीं कर सकते हैं ।
आउट्स

3
: आप 3 विकल्प हैं 1: array , 2: User-defined Class , 3: stdClass । गति की तुलना में प्रदर्शन बहुत अधिक है arrayऔर तुलना करते समय User-defined class(जैसे कि आपके ItemType), लेकिन परिभाषित classएस का उपयोग करके कम मेमोरी का उपयोग करने की प्रवृत्ति है arraystdClassदूसरी ओर तीन विकल्पों में सबसे धीमा है और सबसे अधिक मेमोरी का भी उपयोग करता है।
एंडी

जवाबों:


33

जिस तरह से मैं इसे देखता हूं, यह इस बात पर निर्भर करता है कि आप डेटा के साथ क्या करना चाहते हैं। कुछ सरल जाँचों के आधार पर आप यह निर्धारित कर सकते हैं कि आपके लिए कौन सी दो डेटा संरचनाएँ बेहतर हैं:

  1. क्या इस डेटा से कोई तर्क जुड़ा है?

    उदाहरण के लिए, $priceएक पूर्णांक संख्या के रूप में संग्रहीत किया जाता है, इसलिए $ 9.99 की कीमत के साथ एक उत्पाद होगा price = 999और नहीं price = 9.99? (शायद, हाँ) या partNumberएक विशिष्ट regex से मेल खाने की आवश्यकता है? या, क्या आपको आसानी से जांचने में सक्षम होने की आवश्यकता है कि itemCountक्या आपकी इन्वेंट्री में उपलब्ध है? क्या आपको भविष्य में इन कार्यों को करने की आवश्यकता होगी? यदि हां, तो आपका सबसे अच्छा दांव अब एक क्लास बनाना है। इसका मतलब है कि आप की कमी और तर्क डेटा संरचना में निर्मित परिभाषित कर सकते हैं: private $myPriceकरने के लिए सेट कर दिया जाता 999है, लेकिन $item->getPriceString()रिटर्न $9.99और $item->inStock()अपने आवेदन में कहा जा करने के लिए उपलब्ध है।

  2. क्या आप इस डेटा को कई PHP फ़ंक्शंस में पास करने जा रहे हैं?

    यदि ऐसा है, तो एक वर्ग का उपयोग करें। यदि आप इस पर कुछ परिवर्तन करने के लिए एक बार यह डेटा उत्पन्न कर रहे हैं, या सिर्फ JSON डेटा के रूप में किसी अन्य एप्लिकेशन (जावास्क्रिप्ट या अन्यथा) को भेजने के लिए तो एक सरणी एक आसान विकल्प है। लेकिन अगर आपके पास दो से अधिक PHP फ़ंक्शन हैं जो इस डेटा को एक पैरामीटर के रूप में स्वीकार करते हैं, तो एक वर्ग का उपयोग करें। यदि और कुछ नहीं, जो आपको परिभाषित करता है someFunction(MyProductClass $product) {और यह बहुत स्पष्ट है कि इनपुट के रूप में आपके कार्यों की क्या अपेक्षा है। जैसा कि आप अपने कोड को मापते हैं और अधिक कार्य करते हैं, यह जानना बहुत आसान होगा कि प्रत्येक फ़ंक्शन किस प्रकार का डेटा स्वीकार करता है। देखना someFunction($someArrayData) {लगभग स्पष्ट नहीं है। इसके अलावा, यह प्रकार की स्थिरता को लागू नहीं करता है और इसका मतलब है कि (जैसा कि आपने कहा) सरणी की लचीली संरचना बाद में विकास दर्द का कारण बन सकती है

  3. क्या आप एक पुस्तकालय या साझा कोड आधार बना रहे हैं?

    यदि हां, तो एक वर्ग का उपयोग करें! कुछ नए डेवलपर के बारे में सोचें जो आपके पुस्तकालय का उपयोग कर रहा है, या किसी अन्य डेवलपर ने कंपनी में कहीं और किया है जिसने आपके कोड का पहले कभी उपयोग नहीं किया है। उनके लिए कक्षा की परिभाषा को देखना और समझना आसान हो जाएगा कि वह कक्षा क्या करती है, या अपनी लाइब्रेरी में कई कार्य देखती है जो एक निश्चित कक्षा की वस्तुओं को स्वीकार करते हैं, कोशिश करने और अनुमान लगाने की तुलना में कि उन्हें किस संरचना में उत्पन्न करने की आवश्यकता है सरणियों की संख्या। इसके अलावा, यह # 1 के साथ डेटा संगति के मुद्दों को छूता है: यदि आप एक पुस्तकालय या साझा कोड आधार विकसित कर रहे हैं, तो अपने उपयोगकर्ताओं के साथ अच्छा व्यवहार करें: उन्हें ऐसी कक्षाएं दें, जो डेटा संगति लागू करती हैं और अपने डेटा के डिज़ाइन के साथ त्रुटियां करने से बचाती हैं। ।

  4. क्या यह किसी एप्लिकेशन का छोटा सा हिस्सा है या सिर्फ डेटा का रूपांतरण है? क्या आप उपरोक्त में से किसी में फिट नहीं हैं?

    एक वर्ग बहुत अधिक हो सकता है; एक सरणी का उपयोग करें यदि यह आपको सूट करता है और आपको यह आसान लगता है। जैसा कि ऊपर उल्लेख किया गया है, यदि आप केवल JSON या YAML या XML या जो कुछ भी भेजने के लिए संरचित डेटा उत्पन्न कर रहे हैं, तब तक वर्ग के साथ परेशान न करें जब तक कि कोई आवश्यकता न हो। यदि आप एक बड़े एप्लिकेशन में एक छोटा मॉड्यूल लिख रहे हैं, और किसी अन्य मॉड्यूल / टीमों को आपके कोड के साथ इंटरफ़ेस करने की आवश्यकता नहीं है, तो शायद एक सरणी पर्याप्त है।

अंत में, अपने कोड की स्केलिंग जरूरतों पर विचार करें और संरचित सरणी की तुलना में विचार करना एक त्वरित समाधान हो सकता है, लेकिन एक वर्ग बहुत अधिक लचीला और स्केलेबल समाधान है।

इसके अलावा, निम्नलिखित पर विचार करें: यदि आपके पास एक वर्ग है, और आप JSON को आउटपुट करना चाहते हैं, तो कोई कारण नहीं है कि आप json_data()अपनी कक्षा की एक विधि को परिभाषित नहीं कर सकते हैं जो कक्षा में डेटा के JSON-ifiable सरणी देता है। यह मैंने अपने PHP अनुप्रयोगों में किया है जहां मुझे JSON के रूप में कक्षा डेटा भेजने की आवश्यकता है। उदहारण के लिए:

class Order {
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function forJSON() {
        $items_json = array();
        foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
        return array(
            'total' => $this->getTotal(),
            'items' => $items_json
        );
    }
}

$o = new Order();
// do some stuff with it
$json = json_encode($o->forJSON());

आप के तत्वों को नहीं बदल रहे हैं my_lineitems, इसलिए उन्हें संदर्भ द्वारा प्राप्त करना अनावश्यक है, खासकर क्योंकि चर केवल ऑब्जेक्ट के लिए एक पहचानकर्ता को पकड़ते हैं, न कि ऑब्जेक्ट को। php.net/manual/en/language.oop5.references.php
चिनोटो वोक्रो

माना। मुझे लगता है कि यह एक बहुत बड़े आवेदन का एक टुकड़ा था जिसे एक कारण, या कुछ और के लिए संदर्भ की आवश्यकता थी ...
जोश

2

आप JsonSerializable इंटरफ़ेस का उपयोग करके json संरचना को लागू कर सकते हैं और किसी भी तरह से नेस्टेड सरणी / वर्ग का उपयोग कर सकते हैं । क्लास तेजी से प्राप्त / सेट संचालन में और डीबग करने में आसान है। ऐरे के साथ आपको कोई घोषणा की आवश्यकता नहीं है।

class Order implements \JsonSerializable{
    private $my_total;
    private $my_lineitems;

    public function getItems() { return $this->my_lineitems; }
    public function addItem(Product $p) { $this->my_lineitems[] = $p; }
    public function getTotal() { return $this->my_total; }

    public function jsonSerialize(){
        return [
            'total'=>$this->my_total,
            'products'=>$this->my_lineitems;
        ];
    }
}

class Product implements \JsonSerializable{
    private $name;
    private $price;

    public function jsonSerialize(){ 
        return [
            'name'=>$this->name, 
            'price'=>$this->price
        ];
    }
}

$order = new Order();
$order->addProduct(new Product('Product1', 15));
$order->addProduct(new Product('Product2', 35));
$order->addProduct(new Product('Product3', 42));
$json = json_encode(['order'=>$order, 'username'=>'Eughen']);
/*
json = {
    order: {
        total: 92, 
        products: [
            {
                name: 'Product1',
                price: 15
            }, 
            {
                name: 'Product2',
                price: 35
            },
            {
                name: 'Product3',
                price: 42
            }
        ]
    }, 
    username: 'Eughen'
}
*/

यह प्रश्न क्या जोड़ता है कि मौजूदा स्वीकृत उत्तर?
esoterik

@esoterik नेस्टिंग। json_encode(['order'=>$o]);में मौजूद है स्वीकार जवाब खाली है {"order":{}}:। सुनिश्चित करें कि आप इसका उपयोग कर सकते हैं: $o->forJSON()हर बार हर स्तर पर हर वस्तु पर, लेकिन इसका वास्तविक डिजाइन अच्छा नहीं है। क्योंकि हर समय आपको कुछ लिखने की ज़रूरत होती है: $items_json = array(); foreach($this->my_lineitems as $item) $items_json[] = $item->forJSON();
एल '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.