2015-02-25 6 views
8

मेरे पास एक कक्षा है जो कुछ बुनियादी HTML5 लेती है और कुछ डोम जादू के साथ इसे एक कक्षा में बदल देती है जो एक एक्सटेंशन simpleXMLElement है। यह सब एक "कारखाने" से शुरू होता है (मैं उस शब्द को थोड़ा दुरुपयोग कर सकता हूं) क्लास को XPage कहा जाता है।मैं PHP में रूट ऑब्जेक्ट के लिए एक पुनरावृत्ति ऑब्जेक्ट संदर्भ कैसे प्राप्त करूं?

इस प्रकार हम

<?php 
$MyPage = new XPage($HTML); 

अब तक तो अच्छा हो सकता है। क्या मैं अब क्या करने की जरूरत एक्सएमएल दस्तावेज़ के कुछ भागों का चयन इतना है कि वे "बुकमार्क किए गए" किया जा सकता है (मुझे यकीन है कि इसके लिए एक बेहतर नाम नहीं है कि कर रहा हूँ) तो भी इस

$MyPage->ThatBit("foo")->addChild('p',$MyParagraph); 

आदर्श रूप में मैं की तरह जा सकते हैं

$MyPage->page()->body->header->RememberThisBitAs("foo"); 

या कुछ सहज रूप से समान करने में सक्षम होना चाहते हैं। तब क्या होना चाहिए कि ऑब्जेक्ट $ MyPage (प्रकार XPage) को संदर्भित किया जाना चाहिए, इस मामले में एचटीएमएल/बॉडी/हेडर (शायद यह सही नहीं है XPath नोटेशन लेकिन उम्मीद है कि आप अनुसरण कर सकते हैं)।

विचार यह है कि सबसे अधिक पहुंच वाले क्षेत्रों को अधिक आसानी से प्राप्त किया जा सकता है। यह वह जगह है जहां सिंपलएक्सएमएल क्लास (मेरे एक्सटेंशन के साथ भी) किसी अन्य फैक्ट्री के बिना ऐसा नहीं कर सकती है और एक्सपीज को सिंगलटन भी बना सकती है।

हालांकि यह XPage क्लास ($ MyPage) है जिसमें "बुकमार्क" की सरणी है। जहां तक ​​मुझे पता है कि SimpleXML के पुनरावृत्तियों को संदर्भित करने का कोई तरीका नहीं है ताकि बच्चे का बच्चा या बच्चा फैक्ट्री को "कृपया मुझे बुकमार्क करें" नहीं बता सके।

यह मुझे छोड़ तरह बुरा काम करने होंगे:

$MyPage->addBookmark("foo", 
$MyPage->page()->body->header->getChildren()); 

कौन सा ही सही प्रतीत नहीं होता।

या

$MyPage->page()->body->header->RememberThisBitAs("foo",$MyPage); 

जो इतना बुरा नहीं है, लेकिन अभी भी "लगता है" गलत।

अत्यधिक ऑब्जेक्ट युग्मन या बदसूरत आत्म संदर्भ के बिना मैं इसका कैसे उपयोग करूं?

अद्यतन

मैंने सोचा अगर यह संभव हो गया था debug_backtrace का उपयोग कर एक वर्ग पार उल्टा करने के लिए, लेकिन जवाब नहीं प्रतीत होता है।

In PHP is it possible to reverse traverse a Traversable class to find the root object?

अन्य समान परीक्षण मुझे पता चला है कि एक तत्व पर एक वर्ग चर के मूल्य की स्थापना traversable ढेर में किसी भी अन्य तत्व में सुलभ नहीं है।

मैं रैपर सुझाव पर ध्यान केंद्रित करने जा रहा हूं।

अद्यतन

SimpleXML वास्तव में एक सच्चे वस्तु लेकिन एक सिस्टम संसाधन नहीं है। यह समझा सकता है कि मेरा दर्द कहां से आ रहा था।नोट्स कहें: http://php.net/manual/en/class.simplexmlelement.php

तो सभी वस्तुओं के लिए एक-दूसरे को बुलाते हुए वस्तुओं की एक श्रृंखला की तरह लग रहा है, यह वास्तव में मामला नहीं है।

+0

मुझे लगता है कि मैंने इस प्रश्न के साथ कुछ गलत किया है? मैं तब तक नहीं सीख सकता जब तक मुझे निर्देश नहीं दिया जाता है। –

+1

बस प्रतीक्षा करें और आपको शायद उत्तर मिल जाएगा। – ForceBru

+0

ठीक है, मैं चिंता करना शुरू कर रहा था मैंने एक बुरा सवाल पूछा था। धन्यवाद। –

उत्तर

4

विकल्प 1: रूट के लिए संदर्भ

आप XPage simpleXMLElements के बजाय वस्तुओं वापस जाने के लिए अपने XPage वर्ग के तरीकों को संशोधित कर सकता है (या किसी अन्य वर्ग simpleXMLElement विस्तार)। उस वर्ग में "रूट" तत्व के संदर्भ में एक अतिरिक्त संपत्ति हो सकती है।

तो मूल रूप से अपने "आवरण वर्ग" कुछ इस तरह दिखेगा (छद्म कोड आगे!):

class Wrap extends simpleXMLElement 
{ 
    private $root = null; 
    private $refs = array(); 

    public function addReference($name, $element = null) { 
     if($element === null) { 
      $element = $this; 
     } 
     if($this->root === null) { 
      $this->refs[$name] = $this; 
     } else { 
      $this->root->addReference($name, $this); 
     } 
    } 

    public function getReference($name) { 
     if($this->root === null) { 
      return $this->refs[$name]; 
     } else { 
      return $this->root->getReference($name); 
     } 
    } 
} 

तो ऊपर से अपने यूज-केस इस प्रकार दिखाई देगा:

$MyPage->page()->body->header->addReference("foo"); 

$MyPage->getReference("foo")->addChild('p',$MyParagraph); 

विकल्प 2: एक आईडी

वैकल्पिक रूप से, आप तत्व में केवल एक आईडी विशेषता जोड़ सकते हैं और इसे पुनर्प्राप्त कर सकते हैं:

$MyPage->page()->body->header->addAttribute("id", "foo"); 

$MyPage->xpath("//*[@id='foo']")->addChild('p',$MyParagraph); 
+0

विकल्प के साथ हम समस्या में भाग लेते हैं, मैंने सोचा कि हम शायद - मुझे यकीन नहीं है कि एक विस्तारित सरल एक्सएमएल ऑब्जेक्ट को पुनरावृत्ति श्रृंखला के नीचे पैरेंट संदर्भ पास करने के लिए कैसे प्राप्त किया जाए और यह सुनिश्चित न हो कि प्रत्येक सरल एक्सएमएल विधि को लपेटना ठीक है। मुझे लगता है कि मैं __call() का उपयोग कर सकता हूं - मुझे बस कोशिश करना और देखना होगा। –

+0

ऐसा लगता है कि मुझे वास्तव में क्या करने की ज़रूरत है, केवल सरलXMLElement (जो मैंने किया है लेकिन वास्तव में एक प्रतिनिधिमंडल वर्ग बनाते हैं, जो मुझे लगता है, आप सभी के साथ कह रहे हैं। Http://stackoverflow.com/questions/4347510/विस्तार-वर्ग-साथ फाइनल-निर्माता-ऑन-php –

0

लार्स एबर्ट द्वारा उत्तर द्वारा भारी धक्का को देखते हुए और कई पागल (और अनावश्यक) विचारों पर विचार करने से पहले नहीं, मैं Extend Class with Final Constructor on PHP पर आया जिसने मुझे यह समझने के लिए प्रेरित किया कि मुझे जिस डिजाइन पैटर्न की आवश्यकता है वह प्रतिनिधिमंडल वर्ग की थी।

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

इसके लिए कुछ इंटरफ़ेस तत्वों को लागू करने के लिए XPage ऑब्जेक्ट की आवश्यकता होती है (मैं शायद एक इंटरफ़ेस को परिभाषित करता हूं) और यह मेरे एक्सटेंशन और पॉइंटर को अपने प्रतिनिधिमंडल रैपर में स्वयं से सरल करता है जो SimpleXML की तरह व्यवहार करता है लेकिन वास्तव में ऑब्जेक्ट और XP संदेश पर वापस डीबग संदेश और आत्म संदर्भ पास कर सकते हैं।

<?php 

/** 
* A Delegation extension of SimpleXMLElement 
* 
* Designed to act like SimpleXML but builds a back traceable tree that expects 
* XPage (or some other parent factory) to catch references and debug messages. 
* 
* @author Lord Matt 
* 
* @license 
* Copyright (C) 2015 Matthew Brown 
* This program is free software; you can redistribute it and/or modify 
* it under the terms of the GNU General Public License as published by 
* the Free Software Foundation; either version 2 of the License, or 
* (at your option) any later version. 
* This program is distributed in the hope that it will be useful, 
* but WITHOUT ANY WARRANTY; without even the implied warranty of 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
* GNU General Public License for more details. 
* You should have received a copy of the GNU General Public License along 
* with this program; if not, write to the Free Software Foundation, Inc., 
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
*/ 

class AEWrapper { 

    protected $mother = null; 
    protected $MyAE = null; 

    public function __construct($MyAE,$mother) { 
     $this->MyAE = $MyAE; 
     $this->mother = $mother; 
     return $this; 
    } 

    public function __call($name, $arguments) { 
     try { 
      $result = call_user_method_array($name, $this->MyAE, $arguments); 
     } catch (Exception $e) { 
      $this->log_error('AEWrapper caught exception: ', $e->getMessage()); 
      return FALSE; 
     } 
     if(is_object($result)){ 
      return new AEWrapper($result,$this); 
     } 
     return $result; 
    } 

    public function __get($name) { 
     try { 
      $result = $this->MyAE->{$name}; 
     } catch (Exception $e) { 
      $this->log_error('AEWrapper caught exception: ', $e->getMessage()); 
      return FALSE; 
     } 
     if(is_object($result)){ 
      return new AEWrapper($result,$this); 
     } 
     return $result; 
    } 

    public function &actual_simpleXML_obj_please(){ 
     return $this->MyAE; 
    } 

    // methods exists in XPage 
    public function register_as($name,$what=null){ 
     if($what===null){ 
      $what = $this; 
     } 
     $this->mother->register_as($name,$what); 
    } 

    // [SNIP] 
    // Other project specific stuff here 
    // [/SNIP] 

    // methods exists in XPage  
    protected function log_error($error){ 
     $this->mother->log_error('/'.$error); 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे