I'm trying to save a very large form in to a SQL database as XML. The form is created from a XML file that the user uploads so the size of the form is unknown. Everything is working great unless the user uploads a file with more than 832 elements. The form is generated fine but the output from the form to XML just ends after the 832th element.
The form looks like this. This code is equal to one element in the XML file.
<tr>
<td><input type="text" name="115panel" value="1"></td>
<td><input type="text" name="115loop" value="1"></td>
<td><input type="text" name="115zone" value="1"></td>
<td><input type="text" name="115det" value="5"></td>
<td><input type="text" name="115type" value="OPT"></td>
<td><input type="checkbox" name="115ir" value="1"></td>
<td><input type="checkbox" name="115ok" value="1"></td>
<td><input type="checkbox" name="115iok" value="1"></td>
<td><input type="checkbox" name="115fr" value="1"></td>
<td><input type="text" name="115value" value="39"></td>
</tr>
$_POST[name] and $_POST[type] is set in the beginning of the form.
The PHP code to parse the form into XML looks like this
if($_POST['type'] == "PBS") {
$xml = new DOMDocument("1.0");
$root = $xml->createElement("data");
$root->setAttribute('name', $_POST['name']);
$root->setAttribute('type', $_POST['type']);
$xml->appendChild($root);
$i = 0;
$iP = 1;
$iL = 1;
$iD = 1;
$run = 1;
while($run == 1) {
$search = $iP;
$search .= $iL;
$search .= $iD;
if(isset($_POST[$search.'det'])) {
$id = $xml->createElement("ID".$i);
$root->appendChild($id);
$central = $xml->createElement("panel");
$centralText = $xml>createTextNode($_POST[$search.'panel']);
$central->appendChild($centralText);
$loop = $xml->createElement("loop");
$loopText = $xml->createTextNode($_POST[$search.'loop']);
$loop->appendChild($loopText);
$zone = $xml->createElement("zone");
$zoneText = $xml->createTextNode($_POST[$search.'zone']);
$zone->appendChild($zoneText);
$logicnumber = $xml->createElement("det");
$logicnumberText = $xml->createTextNode($_POST[$search.'det']);
$logicnumber->appendChild($logicnumberText);
$type = $xml->createElement("type");
$typeText = $xml->createTextNode($_POST[$search.'type']);
$type->appendChild($typeText);
$ir = $xml->createElement("ir");
$irText = $xml->createTextNode(xIt($_POST[$search.'ir']));
$ir->appendChild($irText);
$ok = $xml->createElement("ok");
$okText = $xml->createTextNode(xIt($_POST[$search.'ok']));
$ok->appendChild($okText);
$iok = $xml->createElement("iok");
$iokText = $xml->createTextNode(xIt($_POST[$search.'iok']));
$iok->appendChild($iokText);
$fr = $xml->createElement("fr");
$frText = $xml->createTextNode(xIt($_POST[$search.'fr']));
$fr->appendChild($frText);
$value = $xml->createElement("value");
$valueText = $xml->createTextNode($_POST[$search.'value']);
$value->appendChild($valueText);
$id->appendChild($central);
$id->appendChild($loop);
$id->appendChild($zone);
$id->appendChild($logicnumber);
$id->appendChild($type);
$id->appendChild($ir);
$id->appendChild($ok);
$id->appendChild($iok);
$id->appendChild($fr);
$id->appendChild($value);
$i++;
}
$iD++;
if($iD >= 250){
$iD = 1;
$iL++;
}
if($iL >= 9){
$iL = 1;
$iP++;
}
if($iP >= 10){
$iP = 1;
$run = 0;
}
}
$xml->formatOutput = true;
$mysqli->query("INSERT INTO kl_sks (customerID, user, date, data, status)
VALUES ('".addslashes($_POST['name'])."', '".$_SESSION[sesUser]."', '".time()."', '".$xml->saveXML()."', '1')");
}
The code are looped through 250*8*9 times. A total of 18000 times, but the output stops at 832.
Here are an example of the output shorted down to the last one.
<ID831>
<panel>1</panel>
<loop>1</loop>
<zone>42</zone>
<det>13</det>
<type>801PH</type>
<ir>0</ir>
<ok>0</ok>
<iok>0</iok>
<fr>0</fr>
<value>5</value>
</ID831>
<ID832>
<panel>1</panel>
<loop>1</loop>
<zone>42</zone>
<det>14</det>
<type>801PH</type>
<ir>0</ir>
<ok>0</ok>
<iok>0</iok>
<fr>0</fr>
<value>8</value>
</ID832>
<data>
This was a XML document with 1300 elements, so 468 elements is missing
This seems to be a problem regarding the php_value max_input_vars 5000
in php.ini, wich I can't change. So the question is how do i combine all the values in a element to a single $_POST variable, easily?
Consider the following alternative approach that hopefully resolves memory leakage or variable limit. No longer does it involve running while
looping but iterates through the $_POST
associative array.
Also I condensed your XML code, removing the CreateTextNode
object:
if($_POST['type'] == "PBS") {
$dom = new DOMDocument("1.0");
$root = $xml->createElement("data");
$root->setAttribute('name', $_POST['name']);
$root->setAttribute('type', $_POST['type']);
$dom->appendChild($root);
$i = 1;
$panel = $loop = $zone = $det = $type = $it = $ok = $iok = $fr = $value = "";
foreach ($_POST as $key => $item){
if (strpos('panel', $key) !== FALSE) { $panel = $item; }
if (strpos('loop', $key) !== FALSE) { $loop = $item; }
if (strpos('zone', $key) !== FALSE) { $zone = $item; }
if (strpos('det', $key) !== FALSE) { $det = $item; }
if (strpos('type', $key) !== FALSE) { $type = $item; }
if (strpos('it', $key) !== FALSE) { $it = $item; }
if (strpos('ok', $key) !== FALSE) { $ok = $item; }
if (strpos('iok', $key) !== FALSE) { $iok = $item; }
if (strpos('fr', $key) !== FALSE) { $fr = $item; }
if (strpos('value', $key) !== FALSE) { $value = $item; }
if !empty($panel) && !empty($loop) && !empty($zone)
&& !empty($det) && !empty($type) && !empty($it) && !empty($ok)
&& !empty($iok) && !empty($fr) && !empty($value) {
$id = $dom->createElement("ID".$i);
$root->appendChild($id);
$panel = $dom->createElement("panel", $panel);
$id->appendChild($panel);
$loop = $dom->createElement("loop", $loop);
$id->appendChild($loop);
$zone = $dom->createElement("zone", $zone)
$id->appendChild($zone);
$det = $dom->createElement("det", $det);
$id->appendChild($det);
$type = $dom->createElement("type", $type);
$id->appendChild($type);
$ir = $dom->createElement("ir", $ir);
$id->appendChild($ir);
$ok = $dom->createElement("ok", $ok);
$id->appendChild($ok);
$iok = $dom->createElement("iok", $iok);
$id->appendChild($iok);
$fr = $dom->createElement("fr", $fr)
$id->appendChild($fr);
$value = $dom->createElement("value", $value);
$id->appendChild($value);
$i++;
$panel = $loop = $zone = $det = $type = $it = $ok = $iok = $fr = $value = "";
$mysqli->query("INSERT INTO kl_sks (customerID, user, date, data, status)
VALUES ('".addslashes($_POST['name'])."', '".$_SESSION[sesUser]."',
'".time()."', '".$dom->saveXML()."', '1')");
}
}
}
One caveat of this approach is if any of the ten node items are missing, it waits for next corresponding item to complete its 10 batch set, and hence misaligning rows (e.g., 115ok, 115iok, 116fr, 115value). Additional logic on the keys can help in this case.