2012-05-01 19 views
5

मैं PHP, DOM, और PHP DOM कार्यान्वयन के लिए काफी नया हूं। मैं जो करने की कोशिश कर रहा हूं वह के रूट तत्व को $_SESSION चर में सहेज रहा है, इसलिए मैं इसे एक्सेस कर सकता हूं और इसे बाद के पृष्ठ लोड पर संशोधित कर सकता हूं। DOMElement

लाया जा सका:) DOMNode :: appendChild ([domnode.appendchild]:

चेतावनी:

लेकिन मैं PHP में एक त्रुटि जब $_SESSION का उपयोग कर DOMElement के राज्य को बचाने के लिए मिलता है

मैंने पढ़ा है कि एक PHP DOMDocument ऑब्जेक्ट को $_SESSION पर मूल रूप से सहेजा नहीं जा सकता है। हालांकि इसे DOMDocument के क्रमिकरण को सहेजकर सहेजा जा सकता है (उदा। $_SESSION['dom'] = $dom->saveXML())।

मुझे नहीं पता कि DOMElement को $_SESSION वैरिएबल को सहेजने के लिए भी यह सच है, लेकिन यह वही है जो मैं कोशिश कर रहा था। ऐसा करने का मेरा कारण एक अतिरिक्त संपत्ति के साथ डोमेलेमेंट की एक विस्तारित कक्षा का उपयोग करना है। मैं उम्मीद कर रहा था कि $ _SESSION में रूट डोमेलेमेंट को सहेजकर मैं बाद में तत्व को पुनर्प्राप्त कर सकता हूं और इस अतिरिक्त प्रॉपर्टी को संशोधित कर सकता हूं और एक परीक्षण कर सकता हूं, अगर (अतिरिक्त प्रॉपर्टी === झूठा) {कुछ करें; }। मैंने यह भी पढ़ा है कि एक DOMDocument को सहेजकर, और बाद में इसे पुनर्प्राप्त करके, सभी तत्व मूल डीओएम कक्षाओं से वस्तुओं के रूप में लौटा दिए जाते हैं। यह कहना है, भले ही मैंने तत्व बनाने के लिए एक विस्तारित वर्ग का उपयोग किया हो, फिर भी जिस संपत्ति को मुझे बाद में आवश्यकता है वह पहुंच योग्य नहीं होगी, क्योंकि विस्तारित-वर्ग ऑब्जेक्ट के चरम होल्डिंग संदर्भ दायरे से बाहर हो गए हैं - यही कारण है कि मैं ' मैं इस दूसरी चीज की कोशिश कर रहा हूँ। मैंने पहले विस्तारित कक्षा (नीचे शामिल नहीं) का उपयोग करने की कोशिश की, लेकिन त्रुटियां मिलीं ... इसलिए मैं यह देखने के लिए एक डोमेलेमेंट ऑब्जेक्ट का उपयोग करने के लिए वापस लौटा, कि यह समस्या है या नहीं, लेकिन मुझे अभी भी वही त्रुटियां मिल रही हैं। कोड यह रहा:

<?php 
session_start(); 

$rootTag = 'root'; 
$doc = new DOMDocument; 

if (!isset($_SESSION[$rootTag])) { 
    $_SESSION[$rootTag] = new DOMElement($rootTag); 
} 

$root = $doc->appendChild($_SESSION[$rootTag]); 
//$root = $doc->appendChild($doc->importNode($_SESSION[$rootTag], true)); 

$child = new DOMElement('child_element'); 
$n = $root->appendChild($child); 

$ct = 0; 
foreach ($root->childNodes as $ch) echo '<br/>'.$ch->tagName.' '.++$ct; 

$_SESSION[$rootTag] = $doc->documentElement; 
?> 

इस कोड को निम्न त्रुटियों देता है (चाहे मैं appendChild का उपयोग पर निर्भर करता है प्रत्यक्ष या importNode का उपयोग कर कोड की टिप्पणी की लाइन):

Warning: DOMNode::appendChild() [domnode.appendchild]: Couldn't fetch DOMElement in C:\Program Files\wamp_server_2.2\www\test2.php on line 11

Warning: DOMDocument::importNode() [domdocument.importnode]: Couldn't fetch DOMElement in C:\Program Files\wamp_server_2.2\www\test2.php on line 12

मैं कई सवाल हैं सबसे पहले, इस त्रुटि का कारण क्या है और मैं इसे कैसे ठीक कर सकता हूं? इसके अलावा, यदि मैं जो करने की कोशिश कर रहा हूं वह संभव नहीं है, तो मैं प्रत्येक तत्व के लिए कस्टम प्रॉपर्टी का उपयोग करते समय एक डोम पेड़ के 'राज्य' को बचाने के अपने सामान्य उद्देश्य को कैसे पूरा कर सकता हूं? ध्यान दें कि अतिरिक्त संपत्ति केवल प्रोग्राम में उपयोग की जाती है और XML फ़ाइल में सहेजी जाने वाली विशेषता नहीं है। साथ ही, मैं सिर्फ डीओएम को प्रत्येक बार फ़ाइल में सहेज नहीं सकता, क्योंकि संशोधन के बाद, DOMDocument, एक स्कीमा के अनुसार मान्य नहीं हो सकता है जब तक मैं बाद में उपयोग नहीं कर रहा हूं जब अतिरिक्त modificaitons/परिवर्धन DOMDocument में किया गया है। यही कारण है कि मुझे अस्थायी रूप से अमान्य DOMDocument को सहेजने की आवश्यकता है। किसी भी सलाह के लिए धन्यवाद!

संपादित: हाकर के समाधान की कोशिश करने के बाद, कोड काम करता था। फिर मैं डोमेलेमेंट की विस्तारित कक्षा का उपयोग करने की कोशिश करने के लिए आगे बढ़ गया, और जैसा कि मुझे संदेह था, यह काम नहीं करता था। यहां नया कोड है:

<?php 
session_start(); 
//$_SESSION = array(); 
$rootTag = 'root'; 
$doc = new DOMDocument; 

if (!isset($_SESSION[$rootTag])) { 
    $root = new FreezableDOMElement($rootTag); 
    $doc->appendChild($root); 
} else { 
    $doc->loadXML($_SESSION[$rootTag]); 
    $root = $doc->documentElement; 
} 

$child = new FreezableDOMElement('child_element'); 
$n = $root->appendChild($child); 

$ct = 0; 
foreach ($root->childNodes as $ch) { 
    $frozen = $ch->frozen ? 'is frozen' : 'is not frozen'; 
    echo '<br/>'.$ch->tagName.' '.++$ct.': '.$frozen; 
    //echo '<br/>'.$ch->tagName.' '.++$ct; 
} 

$_SESSION[$rootTag] = $doc->saveXML(); 

/********************************************************************************** 
* FreezableDOMElement class 
*********************************************************************************/ 
class FreezableDOMElement extends DOMElement { 
    public $frozen; // boolean value 

    public function __construct($name) { 
     parent::__construct($name); 
     $this->frozen = false; 
    } 
} 
?> 

यह मुझे त्रुटि Undefined property: DOMElement::$frozen देता है। जैसा कि मैंने अपनी मूल पोस्ट में उल्लेख किया है, saveXML और loadXML के बाद, मूल रूप से FreezableDOMElement के साथ तत्काल एक तत्व DOMElement लौटा रहा है, यही कारण है कि frozen संपत्ति पहचान नहीं है। क्या इसके आसपास कोई रास्ता है?

उत्तर

4

आप $_SESSION के अंदर DOMElement ऑब्जेक्ट स्टोर नहीं कर सकते। यह पहले काम करेगा, लेकिन अगले अनुरोध के साथ, यह परेशान होगा क्योंकि इसे क्रमबद्ध नहीं किया जा सकता है।

यह आपके प्रश्न में लिखने के साथ DOMDocument जैसा ही है।

इसे एक्सएमएल के रूप में स्टोर करें या धारावाहिक तंत्र को समाहित करें।

आप मूल रूप से यहां तीन समस्याओं का सामना कर रहे:

  • को क्रमानुसार DOMDocument (आप के लिए ऐसा करते हैं)
  • FreezableDOMElement (आप के लिए ऐसा करते हैं) को क्रमानुसार
  • दस्तावेज़ के साथ निजी सदस्य FreezableDOMElement::$frozen रखें ।

लिखित के रूप में, धारावाहिक बॉक्स से बाहर उपलब्ध नहीं है। इसके अतिरिक्त, DOMDocument आपके FreezableDOMElement को भी w/o serialization को जारी नहीं रखता है। निम्नलिखित उदाहरण दर्शाता है कि उदाहरण के लिए स्वचालित रूप से रखा नहीं है, डिफ़ॉल्ट मान FALSE दिया जाता है (Demo):

class FreezableDOMElement extends DOMElement 
{ 
    private $frozen = FALSE; 

    public function getFrozen() 
    { 
     return $this->frozen; 
    } 

    public function setFrozen($frozen) 
    { 
     $this->frozen = (bool)$frozen; 
    } 
} 

class FreezableDOMDocument extends DOMDocument 
{ 
    public function __construct() 
    { 
     parent::__construct(); 
     $this->registerNodeClass('DOMElement', 'FreezableDOMElement'); 
    } 
} 

$doc = new FreezableDOMDocument(); 
$doc->loadXML('<root><child></child></root>'); 

# own objects do not persist 
$doc->documentElement->setFrozen(TRUE); 
printf("Element is frozen (should): %d\n", $doc->documentElement->getFrozen()); # it is not (0) 

पीएचपी करता है नहीं अब तक समर्थन setUserData (डोम स्तर 3), एक तरह से स्टोर करने के लिए किया जा सकता है तत्व के साथ नामांकित विशेषता के अंदर अतिरिक्त जानकारी। जब ऑब्जेक्ट को क्रमबद्ध करते समय एक्सएमएल स्ट्रिंग बनाकर इसे अनियमित करते समय इसे लोड किया जा सकता है (Serializable देखें)।

class FreezableDOMElement extends DOMElement 
{ 
    public function getFrozen() 
    { 
     return $this->getFrozenAttribute()->nodeValue === 'YES'; 
    } 

    public function setFrozen($frozen) 
    { 
     $this->getFrozenAttribute()->nodeValue = $frozen ? 'YES' : 'NO'; 
    } 

    private function getFrozenAttribute() 
    { 
     return $this->getSerializedAttribute('frozen'); 
    } 

    protected function getSerializedAttribute($localName) 
    { 
     $namespaceURI = FreezableDOMDocument::NS_URI; 
     $prefix = FreezableDOMDocument::NS_PREFIX; 

     if ($this->hasAttributeNS($namespaceURI, $localName)) { 
      $attrib = $this->getAttributeNodeNS($namespaceURI, $localName); 
     } else { 
      $this->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $prefix, $namespaceURI); 
      $attrib = $this->ownerDocument->createAttributeNS($namespaceURI, $prefix . ':' . $localName); 
      $attrib = $this->appendChild($attrib); 
     } 
     return $attrib; 
    } 
} 

class FreezableDOMDocument extends DOMDocument implements Serializable 
{ 
    const NS_URI = '/frozen.org/freeze/2'; 
    const NS_PREFIX = 'freeze'; 

    public function __construct() 
    { 
     parent::__construct(); 
     $this->registerNodeClasses(); 
    } 

    private function registerNodeClasses() 
    { 
     $this->registerNodeClass('DOMElement', 'FreezableDOMElement'); 
    } 

    /** 
    * @return DOMNodeList 
    */ 
    private function getNodes() 
    { 
     $xp = new DOMXPath($this); 
     return $xp->query('//*'); 
    } 

    public function serialize() 
    { 
     return parent::saveXML(); 
    } 

    public function unserialize($serialized) 
    { 
     parent::__construct(); 
     $this->registerNodeClasses(); 
     $this->loadXML($serialized); 
    } 

    public function saveBareXML() 
    { 
     $doc = new DOMDocument(); 
     $doc->loadXML(parent::saveXML()); 
     $xp = new DOMXPath($doc); 
     foreach ($xp->query('//@*[namespace-uri()=\'' . self::NS_URI . '\']') as $attr) { 
      /* @var $attr DOMAttr */ 
      $attr->parentNode->removeAttributeNode($attr); 
     } 
     $doc->documentElement->removeAttributeNS(self::NS_URI, self::NS_PREFIX); 
     return $doc->saveXML(); 
    } 

    public function saveXMLDirect() 
    { 
     return parent::saveXML(); 
    } 
} 

$doc = new FreezableDOMDocument(); 
$doc->loadXML('<root><child></child></root>'); 
$doc->documentElement->setFrozen(TRUE); 
$child = $doc->getElementsByTagName('child')->item(0); 
$child->setFrozen(TRUE); 

echo "Plain XML:\n", $doc->saveXML(), "\n"; 
echo "Bare XML:\n", $doc->saveBareXML(), "\n"; 

$serialized = serialize($doc); 

echo "Serialized:\n", $serialized, "\n"; 

$newDoc = unserialize($serialized); 

printf("Document Element is frozen (should be): %s\n", $newDoc->documentElement->getFrozen() ? 'YES' : 'NO'); 
printf("Child Element is frozen (should be): %s\n", $newDoc->getElementsByTagName('child')->item(0)->getFrozen() ? 'YES' : 'NO'); 

यह वास्तव में पूरा सुविधा नहीं है, लेकिन एक काम कर डेमो: यह तो सभी तीन समस्याओं (Demo) को हल करती है। अतिरिक्त "फ्रीज" डेटा के बिना पूर्ण एक्सएमएल प्राप्त करना संभव है।

+0

त्वरित प्रतिक्रिया के लिए धन्यवाद। मैं आपके द्वारा वर्णित समाधान को लागू करने का प्रयास करने जा रहा हूं। हालांकि, ऐसा लगता है कि जब भी एक्सएमएल स्ट्रिंग को DOMDocument में पुनः लोड किया जाता है, तो मैं विस्तारित वर्ग गुणों को सुलभ नहीं होने की समस्या में अभी भी चलाऊंगा, है ना? – neizan

+0

@neizan: आप यहाँ क्या बोलते हैं? यदि आप स्वयं को क्रमबद्ध करने का ख्याल रखते हैं, तो आपके पास ऐसी सभी संभावनाएं होनी चाहिए जिन्हें आप ढूंढ रहे हैं। यह सिर्फ सामान्यतः 'DOMDocument' को क्रमबद्ध करने का कोई मतलब नहीं है, क्योंकि एक्सएमएल पहले से ही क्रमबद्धता का एक रूप है। – hakre

+0

ठीक है, जब मैंने सीरियलाइजेशन कहा था, तो मैं 'saveXML' विधि का उपयोग करने का जिक्र कर रहा था, भ्रम के लिए खेद है। कृपया मेरे द्वारा पोस्ट किए गए अतिरिक्त नमूना कोड पर एक नज़र डालें जो आप जो कहते हैं वह करने की कोशिश करता है। यह 'DOMElement' का उपयोग करके काम करता था, लेकिन विस्तारित वर्ग' फ्रीज़ेबल डीओमेलेमेंट 'के साथ नहीं। – neizan

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