tags:

views:

39

answers:

4

Somewhere in my code I have:

class aclass {
  ...
  function amethod() {
    $this->dom = $a_dom_document;
    $this->about = array('an_element' => $an_element_of_that_document);
  }
  ...
}

/* Somewhere else */

$instance->dom; // It's there, no problem.
$instance->about['an_element']->parentNode->replaceChild($something_else, $this->about['an_element']);

The code is complicated; I'm trying to only give the gist, here.

The strange thing is that it works about a quarter of the time. 3 out of 4 times, PHP says that replaceChild is a "Call to a member function replaceChild() on a non-object", but a quarter of the time, it actually works. What could be going on?

Edit: the following

print_r($instance->about['an_element']);
print_r($instance->about['an_element']->parentNode);
print method_exists($instance->about['an_element'], 'replaceChild')?'exists':'does not exist');
print_r($something_else);    

returns:

DOMElement Object
(
)
DOMElement Object
(
)
exists
DOMElement Object
(
)

This is true even when the page fails.

I must be missing something very obvious. The $something_else is a node of the same DOM document.

SOLUTION: It was indeed very simple: for reasons I still don't quite understand, that part of the code is called twice. In one case, the instance is not defined, but that instance shows up in second place in the logs and I really was only looking for one. An if took care of it. Now I have to see why the #@!~ there are two of them in the first place.

A: 

Welcome to debugging.

do print_r($instance->about['an_element']) and add that output to your answer.

I would suspect that no parent is being found for $instance->about['an_element'].

Michael Robinson
I can't format code here; I'll put it as an edit of the question.
eje211
+1  A: 

Well, let's look at this logically. It's saying that call to a member function replaceChild() on a non-object. That means that you're trying to call replaceChild on something that either is not set, or is not an object (duh). Let's look for where there's a call to replace child.

$instance->about['an_element']->parentNode->replaceChild(...)

So that means that $instance->about['an_element'] must not have a parent node (otherwise it would be an object). So that means it's either the root node or an orphaned node (A node that is still bound to the dom, but was already removed from the tree. So it has no parent). You can either add logic to prevent an_element from ever being non-parented, or you can check to make sure it has a parent before replacing:

if (is_object($instance->about['an_element']->parentNode)) {
    $instance->about['an_element']->parentNode->replaceChild(...);
} else {
    // You have a non-parented node, do something else
}
ircmaxell
A: 

insertBefore() the current node then use removeChild() on the current node. you may occasionally be replacing a child node of a parent that doesn't exist.

stillstanding
This means that during traversal the DOM tree structure may have changed, i.e. the parent may have also experienced a replaceChild() which changes the structure, so the current node may not be a child of the alleged parent anymore.
stillstanding
A: 

print_r($instance->about['an_element']);

is not useful at all because the error is at the call to replaceChild. If $instance->about['an_element'] were null you would get the error that you're accessing a property (parentNode) on a non-object which you don't. Check that

print_r($instance->about['an_element']->parentNode);

is not null. I cannot say more without seeing the full code.

Raoul Duke