Verschachtelte foreach Schleife


Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

BIM-T

Mitglied
Hallo, in meinem aktuellen Projekt komme ich irgendwie nicht weiter.... :-(
Ich möchte folgendes machen:
Ich Frage mittels "foreach" zwei zusammengehörige Werte aus einem XML DOM aus und erhalte 2 Array:
HTML:
Array
(
    [0] => i2121
    [1] => i2166
    [2] => i2076
    [3] => i1931
    [4] => i2014
)
1
Array
(
    [0] => 2VHvXw$Zj8bxfBIxaTWnfA
    [1] => 2VHvXw$Zj8bxfBIxaTWnfB
    [2] => 2VHvXw$Zj8bxfBIxaTWnf5
    [3] => 2VHvXw$Zj8bxfBIxaTWpV6
    [4] => 2VHvXw$Zj8bxfBIxaTWnf4
)
1
Diese beiden Array möchte ich jetzt mittels prepare in meine DB schreiben. Dabei soll dem Wert 1 aus dem ersten Array (i2121) der zugehörige Wert aus dem zweiten Array (2VHvXw$Zj8bxfBIxaTWnfA) in der Table Reihe hinzugefügt werden. Also wie Abgebildet :
IDXML_IDGUID
0i21212VHvXw$Zj8bxfBIxaTWnfA
1i21662VHvXw$Zj8bxfBIxaTWnfB
2.......


Mein Code sieht aktuell so aus :

PHP:
// Alle Wände im Informationsmodell suchen und die ID's in einen Array schreiben.
$get_all_Walls = $xpath->query('//*/ifc:IfcWallStandardCase/@id');

    foreach ($get_all_Walls as $get_all_Wall_IDs){
        $Wall_IDs[]= $get_all_Wall_IDs->nodeValue;
    }


// Testausgabe der ermittelten Elemente.     
echo '<pre>', print_r($Wall_IDs), '</pre>';
echo '<pre>', print_r($Wall_GUIDs), '</pre>';

foreach ($Wall_IDs as $Wall_ID){
$query = "//ifc:IfcWallStandardCase[@id='{$Wall_ID}']/ifc:GlobalId";
foreach($xpath->query($query) as $test){
    $Wall_GUID2s[]= $test->nodeValue;
};
    
}


// Abfrageschleife um zu ermitteln ob die ausgelesenen XML-IDs bereits in der DB vorhanden sind.
foreach ($Wall_IDs as $Test){
//   
    //echo '<pre>', print_r($Test), '</pre>';
    $Wall_ID_exists = $db -> query("SELECT XML_ID FROM ifcwall WHERE XML_ID='{$Test}'");
    if(mysqli_num_rows($Wall_ID_exists) > 0){
        
    echo "IDs bereits vorhanden";}
 // Wenn abgefragte XML-IDs nicht vorhanden sind, werden sie in die DB geschrieben.   
    else{
    echo "ID nicht da";
      
        $query = "//ifc:IfcWallStandardCase[@id='{$Wall_ID}']/ifc:GlobalId";
        foreach($xpath->query($query) as $test){
    $Wall_GUID2s[]= $test->nodeValue; 
    
        }
    
    $stmt = $db->prepare("INSERT INTO ifcwall (XML_ID, GUID) VALUES (?, ?)");
     $stmt->bind_param("ss", $Test, $Wall_GUID2s);
     $stmt->execute();
      
  
      
    }

};
Könnt ihr mir zufällig bei der Schleife helfen, bzw. ist es überhaupt möglich ein derartiges Konstrukt zu schreiben?

Vielen Dank schon einmal.
 

Yaslaw

n/a
Moderator
Beim bind_param. $Wall_GUID2s ist ein Array, kein String.
Du hast $Test und $test. Mach das nicht das verwirrt nur. Ich rate dir zu einer ganz einfachen Konvention, die du meistens antriffst. Das erleichtert es dir, später gut zu sehen was was ist.
Klassennamen beginnen mit einem Grossbuchstaben. Konstanten sind durchgehend gross geschrieben. Variablen beginnen mit einem kleinen Buchstaben.

PHP:
	$query = "//ifc:IfcWallStandardCase[@id='{$Wall_ID}']/ifc:GlobalId";
	$stmt = $db->prepare("INSERT INTO ifcwall (XML_ID, GUID) VALUES (?, ?)");
	foreach($xpath->query($query) as $sub){
		$stmt->bind_param("ss", $Test, $sub->nodeValue);
		$stmt->execute();
	}
 

BIM-T

Mitglied
Danke für die schnelle Antwort, leider erzeugt der von dir geschriebene Code, dass die letzte GUID (2VHvXw$Zj8bxfBIxaTWnf4) an jede XML_ID angehangen werden.
Hast du eine Idee was ich machen kann?

Deine Anmerkungen werde ich zukünftig beherzigen.
 

Yaslaw

n/a
Moderator
Ist dein Fehler.
Die nimmst $Wall_ID un die GUID auszulesen. Diese verwendest du aber in einer Schleife davor. Somit ist da immer der letzte Wert der Schleife drin. In deinem Code ist an der Stelle $Test die aktuelle ID.
Du solltest nicht mit Variablennamen wie Test etc. arbeiten. Ist nichtsagend.
[code = php]$query = "//ifc:IfcWallStandardCase[@id='{$Test}']/ifc:GlobalId";[/code]
Zudem gehst du hintereinader die Schleifen durch. Das könnte man vereinfachen
PHP:
	// Alle Wände im Informationsmodell suchen und die ID's in einen Array schreiben.
	$xQuery = '//*/ifc:IfcWallStandardCase/@id';
	$allWallNodes = $xpath->query(xQuery);
	foreach ($allWallNodes as $wallIdNode){
		$wallId = $wallIdNode->nodeValue;
		//echo '<pre>', print_r($Test), '</pre>';
		$stmt = $db->prepare("SELECT xml_id AS cnt FROM ifcwall WHERE xml_id=?")
		$stmt->bind_param('s', $wallId);
		$stmt->execute();
		$stmt->store_result();

		if($stmt->num_rows > 0){
			echo "IDs bereits vorhanden";
	 		// Wenn abgefragte XML-IDs nicht vorhanden sind, werden sie in die DB geschrieben.   
		else{
			echo "ID nicht da";
			  
			$xQuery = "//ifc:IfcWallStandardCase[@id='{$wallId}']/ifc:GlobalId";
			
			$stmt = $db->prepare("INSERT INTO ifcwall (XML_ID, GUID) VALUES (?, ?)");
			
			foreach($xpath->query($xQuery) as $wallGuidNode){
				$stmt->bind_param("ss", $wallId, $wallGuidNode->nodeValue);
				$stmt->execute();
			}      
		}
	}
 

BIM-T

Mitglied
Danke für deine Hilfe, funktioniert super und mit der Struktur kann ich es, für mich verständlich" erweitern.
Nur noch eine Verständnisfrage, das SELECT xml_id AS cnt FROM ifcwall WHERE xml_id=?" wird verwendet um durchzuzählen ob der Wert da ist und das $stmt->store_result(); um ihn zwischenzuspeichern? Oder verstehe ich das falsch?
Entschuldige meine Nachfrage, aber ich will es
verstehen.
Viele Grüße
 

Yaslaw

n/a
Moderator
Oh, das AS cnt ist noch von einem anderen Versuch. Das SQL zählt nicht durch, sondern sucht, genau wie deines, den Datensatz. Eigentlich einfach dein SQL auf prepared Statement umgebaut.
Der store_result() habe ch aus der PHP-Hilfe. Ich arbeitete nir mir MySQLi sondern mit PDO. Aber das ist auch schon Jahre her.
Aber die PHP-Hilfe hilft eigentlich ganz gut.
 

BIM-T

Mitglied
Hallo ich noch einmal, es hat wirklich super geklappt mit der Schleife. Ich habe sie jetzt um weitere Abfragewerte erweitert, das funktioniert auch gut bis auf eine Abfrage, bei der ich mittels der Wallid mehrere Werte als Ergebnis erhalten muss und diese in einem Array an die DB übergebe. Hab es mittels json Encode auch geschafft, das ich mir die entsprechenden Werte übergeben und in die DB schreiben lasse, nur muss ich durch aktualisieren der Seite die Schleifen mehrfach durchlaufen lassen.
Ich habe nun schon versucht die Schleife innerhalb mehrfach durchlaufen zu lassen um den entsprechenden Array zu befüllen. Leider ohne Erfolg, hat jemand eine Idee wie ich diese Schleife innerhalb laufen lasse? Oder ist mein Ansatz der Falsche?

Hier mein aktueller Code :
PHP:
// Alle Wände im Informationsmodell suchen und die ID's in einen Array schreiben.

$IDXMLQuery = '//*/ifc:IfcWallStandardCase/@id';
$allWallNodes = $xpath->query($IDXMLQuery);
foreach ($allWallNodes as $WallIdNode){
    $WallId = $WallIdNode->nodeValue;
    $stmt = $db->prepare("SELECT XML_ID FROM ifcwall WHERE XML_ID=?");
        $stmt->bind_param('s', $WallId);
        $stmt->execute();
        $stmt->store_result();

        if($stmt->num_rows > 0){
            echo "IDs bereits vorhanden";}
             // Wenn abgefragte XML-IDs nicht vorhanden sind, werden sie in die DB geschrieben.   
        else{
            
            echo "ID nicht da";
// Denition der Abfragepfade basierend auf der Wall-ID.
            $GUIDXMLQuery = "//ifc:IfcWallStandardCase[@id='{$WallId}']/ifc:GlobalId";
            $NameXMLQuery = "//ifc:IfcWallStandardCase[@id='{$WallId}']/ifc:Name";
            $PsetIDXMLQuery = "//ifc:IfcRelDefinesByProperties/ifc:RelatedObjects/*[@ref='{$WallId}']/ancestor::ifc:IfcRelDefinesByProperties/@id";
            
            $RelPsetXMLQuery = "//ifc:IfcRelDefinesByProperties/ifc:RelatedObjects/*[@ref='{$WallId}']/ancestor::ifc:IfcRelDefinesByProperties/@id";
            
            $stmt = $db->prepare("INSERT INTO ifcwall (XML_ID, GUID, Name, Pset_ID) VALUES (?, ?, ?, ?)");
            
            foreach($xpath->query($GUIDXMLQuery) as $wallGuidNode){
            foreach($xpath->query($NameXMLQuery) as $wallNameNode)
            //foreach($xpath->query($PsetIDXMLQuery) as $wallPsetNode)
       //Zusätzliche Schleife  
  foreach($xpath->query($RelPsetXMLQuery) as $RelPsetNode){
                $Ref_ID[] = $RelPsetNode->nodeValue;
                $string = json_encode($Ref_ID);}
            
                $stmt->bind_param("ssss", $WallId, $wallGuidNode->nodeValue, $wallNameNode->nodeValue, $string);
                $stmt->execute();
            }// Ender der Inneren Schleife zum Definieren der Variablen und Schreiben der Werte in die DB.   
            
            
        }//Ende Else
    }// Ende Hauptschleife
Als Ergebnis soll jeder Wallid die entsprechenden IDs der referenzierten IDs zugewiesen werden und in der DB als Array abgelegt werden.
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Neue Beiträge