eje211
eje211

Reputation: 2429

PHP throws an error... sometimes, on a DOM Element

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.

Upvotes: 1

Views: 863

Answers (4)

bcosca
bcosca

Reputation: 17555

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.

Upvotes: 0

Raoul Duke
Raoul Duke

Reputation: 4311

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.

Upvotes: 1

ircmaxell
ircmaxell

Reputation: 165261

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
}

Upvotes: 2

Michael Robinson
Michael Robinson

Reputation: 29498

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'].

Upvotes: 0

Related Questions