Page 1 of 1

class variables not sticking?

Posted: Fri Feb 02, 2007 2:02 am
by Kieran Huggins
OK - I'm beating my head against the wall on this one: :banghead:

I'm extending the stock DOM classes in php5 to add db save and load functions, plus an extra element type:

A Thing is a special class of element that I've defined to group sets of elements. A Thing is also just an element.

Saving and loading works fine, I've even managed to get Thing caching working.

The Problem

When I save an existing node, there doesn't seem to be any way of verifying the node_id property of the node, nor can I getAttribute('node_id'). This leads my program to believe it's a new node and creates a duplicate node for it. Oddly enough, this is only true for child nodes of the Thing.

I hope one of you who is more class savvy can tell me what I'm doing wrong... and I have a feeling that will be Hockey for some reason :-)

All Files+SQL: http://kieran.ca/www.rar

Snippet from the Thing class:

Code: Select all

function save(){
		global $doc, $db, $xpath;

		// save this element
		$this->saveNode($this);

		// if this is a thing, build the cache
		if($this->parentNode === $doc->root){
			// get XML
			$rawxml = $doc->saveXML($this);
			// save it as a file in the cache dir
			if($rawxml){
				touch(THING_CACHE.$this->thing_id);
				file_put_contents(THING_CACHE.$this->thing_id,$rawxml);
			}

		}
	}

	function saveNode($n){ // until I can upgrade to php 5.2.0
		global $doc, $db, $xpath;
		MySQL_select_db('allyourbase',$db) or die(MySQL_error($db));

		// is this a Thing?
		if($n->parentNode === $doc->root) $this->saveThing($n);


		// if element doesn't exist, make it

		
// problem area	begins

		// neither of these work...
		if(!$n->getAttribute('node_id')){ 
		// if(!isset($n->node_id)){
		
// problem area	ends


			// only continue if the parent is NOT the doc root
			if($n->parentNode !== $doc->root){
				// if the parent has no node_id, save it before continuing
				if(!$n->parentNode->node_id) $n->parentNode->save();
				//now get the parent_node_id
				$fields['parentNode'] = $n->parentNode->node_id;
			}

			// populate other info
			if(isset($n->parentNode->thing_id)) $n->thing_id = $n->parentNode->thing_id;
			$fields['thing'] = @$n->thing_id;
			$fields['nodeType'] = @$n->nodeType;
			$fields['created'] = $n->node_created = time();

			// prepare query field names and values
			foreach($fields as $field=>$value){
				$query['fields'][]=$field;
				$query['values'][]=mysql_real_escape_string($value);
			}

			// query-encode the names and values
			$fields = "`".implode("`,`",$query['fields'])."`";
			$values = "'".implode("','",$query['values'])."'";

			// create the node
			$result = MySQL_query("INSERT INTO nodes ({$fields}) VALUES ({$values})",$db) or die('line:'.__LINE__.', can\'t save node: '.MySQL_error());

			unset($query,$fields);

			// now fetch the node's shiny new id
			$n->node_id = MySQL_insert_id($db);
		}

		// what kind of node is this?
		switch($n->nodeType){
			case XML_ELEMENT_NODE: // Node is a DOMElement
				$this->saveElement($n);
				if($n->parentNode == $doc->root) $n->setAttribute('thing_id',@$n->thing_id);
				$n->setAttribute('element_id',@$n->element_id);
				$n->setAttribute('node_id',@$n->node_id);
//				echo 'node '.$n->node_id.'<br/>';
//				$n->setAttribute('created',@$n->created);
//				$n->setAttribute('modified',@$n->modified);
				break;
			case XML_ATTRIBUTE_NODE: // Node is a DOMAttr
				$this->saveAttr($n);
				break;
			case XML_TEXT_NODE: // Node is a DOMText
				$this->saveText($n);
				break;
			case XML_CDATA_SECTION_NODE: // Node is a DOMCharacterData
				$this->saveCData($n);
				break;
			default: // no nodeType? I doubt this is possible, but it shoudl definitely error out.
				die('There\'s no nodeType! The sky is falling!');
				break;
		}

		// save each child to the DB
		if(!is_null($n->childNodes)) for($i=0;$i<$n->childNodes->length;$i++){
			// save the element
			$this->saveNode($n->childNodes->item($i));
		}

		// save each attribute to the DB
		if(!is_null($n->attributes)) for($i=0;$i<$n->attributes->length;$i++){
			// save the attribute
			if(!property_exists($n,$n->attributes->item($i)->name)) $this->saveAttr($n->attributes->item($i));
		}
	}
The XML it's loading / saving:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <stop thing_id="4" node_id="46" element_id="25" node_created="1170387040" element_modified="1170387040" thing_name="stop">
    <name element_id="26" node_id="47" node_created="1170387040" element_modified="1170387040">Lawrence West</name>
    <lat element_id="27" node_id="49" node_created="1170387040" element_modified="1170387040">43.71572083597938</lat>
    <lon element_id="28" node_id="51" node_created="1170387040" element_modified="1170387040">-79.44428443908691</lon>
    <street element_id="29" node_id="53" node_created="1170387040" element_modified="1170387040">655 Lawrence Ave. West</street>
    <city element_id="30" node_id="55" node_created="1170387040" element_modified="1170387040">Toronto</city>
    <region element_id="31" node_id="57" node_created="1170387040" element_modified="1170387040">Ontario</region>
    <country element_id="32" node_id="59" node_created="1170387040" element_modified="1170387040">Canada</country>
  </stop>
  <stop thing_id="61" node_id="901" element_id="481" node_created="1170387042" element_modified="1170387042" thing_name="stop">
    <name element_id="482" node_id="902" node_created="1170387042" element_modified="1170387042">Lawrence East</name>
    <lat element_id="483" node_id="904" node_created="1170387042" element_modified="1170387042">43.75051320325138</lat>
    <lon element_id="484" node_id="906" node_created="1170387042" element_modified="1170387042">-79.27056312561035</lon>
    <street element_id="485" node_id="908" node_created="1170387042" element_modified="1170387042">2444 Lawrence Ave. East</street>
    <city element_id="486" node_id="910" node_created="1170387042" element_modified="1170387042">Toronto</city>
    <region element_id="487" node_id="912" node_created="1170387042" element_modified="1170387042">Ontario</region>
    <country element_id="488" node_id="914" node_created="1170387042" element_modified="1170387042">Canada</country>
  </stop>
  <stop thing_id="26" node_id="376" element_id="201" node_created="1170387041" element_modified="1170387041" thing_name="stop">
    <name element_id="202" node_id="377" node_created="1170387041" element_modified="1170387041">Lawrence</name>
    <lat element_id="203" node_id="379" node_created="1170387041" element_modified="1170387041">43.72483950684785</lat>
    <lon element_id="204" node_id="381" node_created="1170387041" element_modified="1170387041">-79.40179824829102</lon>
    <street element_id="205" node_id="383" node_created="1170387041" element_modified="1170387041">3101 Yonge St.</street>
    <city element_id="206" node_id="385" node_created="1170387041" element_modified="1170387041">Toronto</city>
    <region element_id="207" node_id="387" node_created="1170387041" element_modified="1170387041">Ontario</region>
    <country element_id="208" node_id="389" node_created="1170387041" element_modified="1170387041">Canada</country>
  </stop>
</xml>
Thanks for getting this far!

Kieran