Soy bastante nuevo en PHP, DOM y en la implementación de PHP DOM. Lo que intento hacer es guardar el elemento raíz del DOMDocument
en una variable $_SESSION
para poder acceder a él y modificarlo en las siguientes cargas de página.
Pero me da un error en PHP cuando se utiliza $_SESSION
para guardar el estado de DOMElement:
Advertencia: DOMNode :: appendChild() [domnode.appendchild]: No se pudo obtener DOMElement
He leído que un objeto PHP DOMDocument no puede guardarse en $_SESSION
de forma nativa. Sin embargo, puede guardarse guardando la serialización del DOMDocument (por ejemplo, $_SESSION['dom'] = $dom->saveXML()
).
No sé si lo mismo se aplica para guardar un DOMElement
en una variable $_SESSION
también, pero eso es lo que estaba intentando. Mi razón para querer hacer esto es usar una clase extendida de DOMElement con una propiedad adicional. Tenía la esperanza de que al guardar el elemento raíz DOMElement en $ _SESSION podría recuperar el elemento y modificar esta propiedad adicional y realizar una prueba como, if (additionalProperty === false) {hacer algo; }. También he leído que al guardar un DOMDocument y luego recuperarlo, todos los elementos se devuelven como objetos de las clases DOM nativas. Es decir, incluso si utilicé una clase extendida para crear elementos, la propiedad que posteriormente necesitaré no será accesible, porque la variable que contiene la referencia al objeto de clase extendida ha salido del alcance, que es la razón por la que ' Estoy intentando esta otra cosa. Intenté usar la clase extendida (no incluida a continuación) primero, pero obtuve errores ... así que volví a usar un objeto DOMElement para ver si ese era el problema, pero sigo recibiendo los mismos errores. Aquí está el código:
<?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;
?>
Este código da los siguientes errores (dependiendo de si utilizo appendChild directa o la línea comentada de código usando 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
I tiene varias preguntas Primero, ¿qué está causando este error y cómo lo soluciono? Además, si lo que trato de hacer no es posible, ¿cómo puedo lograr mi objetivo general de guardar el 'estado' de un árbol DOM mientras uso una propiedad personalizada para cada elemento? Tenga en cuenta que la propiedad adicional solo se usa en el programa y no es un atributo que se guardará en el archivo XML. Además, no puedo simplemente guardar el DOM de nuevo en el archivo cada vez, porque el DOMDocument, después de una modificación, puede no ser válido de acuerdo con un esquema que estoy utilizando hasta más adelante cuando se hayan realizado modificaciones/adiciones adicionales al DOMDocument. Es por eso que necesito guardar un DOMDocument temporalmente inválido. Gracias por cualquier consejo!
EDITADO: Después de probar la solución de hakre, el código funcionó. Luego pasé a tratar de usar una clase extendida de DOMElement, y, como sospechaba, no funcionó. Aquí está el nuevo código:
<?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;
}
}
?>
Me da el error Undefined property: DOMElement::$frozen
. Como mencioné en mi publicación original, después de saveXML
y loadXML
, un elemento originalmente instanciado con FreezableDOMElement
está devolviendo el tipo DOMElement
, por lo que la propiedad frozen
no se reconoce. ¿Hay alguna forma de evitar esto?
Gracias por la respuesta rápida. Voy a intentar implementar la solución que describes. Sin embargo, parece que probablemente me encuentre con el problema de no tener acceso a las propiedades de clase ampliadas cuando la cadena XML se vuelve a cargar en un DOMDocument, ¿verdad? – neizan
@neizan: ¿Sobre qué hablas aquí? Si se ocupa de la serialización, debe tener todas las posibilidades que está buscando. Es solo que normalmente serializar 'DOMDocument' no tiene sentido, ya que XML ya es una forma de serialización. – hakre
Correcto, cuando dije serialización me refería a utilizar el método 'saveXML', disculpe la confusión. Por favor, eche un vistazo al código de muestra adicional que acabo de publicar que intenta hacer lo que usted dice. Funcionó usando un 'DOMElement', pero no con la clase extendida' FreezableDOMElement'. – neizan