webForumDet fria alternativet

Generera XML filer från en databas

PHP

3 svar · 348 visningar · startad av MickeA.com

Medlem sedan feb. 20034 441 inlägg
Frågan#1

Hej,

Jag ska generea x antal XML filer med info från en databas.
Varje fil kommer innehålla ~1.000 rader och jag har löst det såhär:

$fext = "_" . time() . ".xml";
for($i = 0; $i < sizeof($language); $i++){
	
	$query = "SELECT "
		."a.group_id, a.group_name, a.group_desc, "
		."b.item_id, b.item_parent, b.item_name, b.item_desc, b.item_cdata, "
		."(SELECT value_text FROM phrase_value WHERE value_parentid = b.item_id AND value_language = 1 ORDER BY value_updated DESC LIMIT 1) AS str_english, "
		."(SELECT lang_code FROM document_lang WHERE lang_id = " . $language[$i] . " LIMIT 1) AS lang_code, "
		."(SELECT lang_code_short FROM document_lang WHERE lang_id = " . $language[$i] . " LIMIT 1) AS lang_code_short "
		."FROM phrase_group a INNER JOIN phrase_item b "
		."ON a.group_id = b.item_parent "
		."WHERE a.group_parent = 3 "
		."ORDER BY a.group_order ASC, b.item_order ASC";

	$result = mysql_query($query) or die((DEBUG ? "<h2>An error occurred</h2>\n<p>" . mysql_error() . "<br />\n" . $query . "</p>\n" : "<p>An error has occurred, please contact site admin.</p>\n"));
	if(!(mysql_num_rows($result) == false)){
		$i = 0;
		$curr_group = 0;
		$lang_code = mysql_result($result, 0, 9);
		$lang_code_short = mysql_result($result, 0, 10);
		$fp = fopen(ROOTPATH . "upload/XML/text." . ($filename == 1 ? $lang_code : $lang_code_short) . $fext, "w");
		fwrite($fp, "<?xml version=\"1.0\" charset=\"utf-8\">\n"
			   ."<Resource>\n");
		mysql_data_seek($result, 0);
		while($res = mysql_fetch_assoc($result)){
			if(!($curr_group == $res['group_id'])){
				if($i != 0){
					fwrite($fp, "\t</items>\n"
							   ."\t</group>\n");
				}
				fwrite($fp, "\t<group id=\"" . $res['group_name'] . "\">\n"
					   ."\t<desc>" . $res['group_desc'] . "</desc>\n"
					   ."\t<items>\n");
			}
			$query = "SELECT "
				."a.value_text "
				."FROM phrase_value a "
				."WHERE a.value_parentid = " . $res['item_id'] . " "
				."AND a.value_language = " . $language[$i] . " "
				."AND a.value_updated = ("
				."	SELECT "
				."	MAX(value_updated) "
				."	FROM phrase_value pv "
				."	WHERE pv.value_parentid = a.value_parentid "
				."	AND value_language = " . $language[$i] . " "
				.") "
				."LIMIT 1";
			
			$val = mysql_query($query) or die((DEBUG ? "<h2>An error occurred</h2>\n<p>" . mysql_error() . "<br />\n" . $query . "</p>\n" : "<p>An error has occurred, please contact site admin.</p>\n"));
			if(!(mysql_num_rows($val) == false)){
				$value_text    = mysql_result($val, 0, 0);
			}else{
				$value_text    = $res['str_english'];
			}
			mysql_free_result($val);

			fwrite($fp, "\t\t<item id=\"" . $res['item_name'] . "\">\n"
				   ."\t\t\t<value>" . $value_text . "</value>\n"
				   ."\t\t\t<desc>" . $res['item_desc'] . "</desc>\n"
				   ."\t\t</item>\n");

			$curr_group = $res['group_id'];
		}
		fwrite($fp, "\t</items>\n"
			   ."\t</group>\n"
			   ."</Resource>");
	}
	mysql_free_result($result);
        fclose($fp);
}

$language är en array med id'n över de språk som ska genereras.
Det går jättefint att generera en fil, den sparas i rätt mapp och innehåller alla rader.

Men när jag väljer två språk, så att for-loopen går två varv, så skrivs aldrig fil #2 klart, den innehåller inte alla rader.

Sen tar det flera minuter att exekvera skriptet.

Finns det några andra smart sätt att lösa det här?

Tack!

Medlem sedan mars 20007 896 inlägg
#2

Har du felsökt, och kollat var problemet uppstår? Fungerar det om du enbart tar de 50 första posterna ur databasen (LIMIT 50)? Då kan man dra slutsatsen att det troligtvis rör sig om för mycket information - eller snarare bearbetning av för mycket information. Då skulle du kunna vända på det, och köra en SQL-fråga som hämtar informationen från alla valda språk på en gång, och loopar igenom datan från databasen istället för att loopa igenom språken. Det verkar som att language_id är ett heltal, då kan du använda SQL's nyckelord 'IN'.

SELECT ... FROM tbl WHERE language_id IN (" . implode(',', $language) . ") ...

Jag hoppas att jag gjorde mig förstådd. :)

Medlem sedan feb. 20034 441 inlägg
#3

SPiN skrev:

Jag hoppas att jag gjorde mig förstådd. :)

Javisst gjorde du det.
Det verkar bero på att det är mycket info, nu gjorde jag om och tog bort den andra sql frågan som låg inuti while-loopen.

Då klarar den 2½ fil.
Det här kanske snarare blir ett sql problem nu, men jag har ingen aning om hur jag ska hämta allt med bara en fråga, som du föreslår.

Min databas ser ut såhär:

[b]phrase_group[/b]
group_id, INT
group_parent, INT (är alltid = 3)
group_name, VARCHAR
group_desc, VARCHAR

[b]phrase_item[/b]
item_id, INT
item_parentid, INT (relaterad till [i]phrase_group.group_id[/i])
item_name, VARCHAR
item_desc, INT

[b]phrase_value[/b]
value_id, INT
value_parentid, INT (relaterad till [i]phrase_item.item_id[/i])
value_language, INT
value_text, VARCHAR

Det som ska hända är att en lista ska skrivas ut, men grupper, items och values på resp. språk:

<group id="[i]phrase_group.group_name[/i]">
   <desc>[i]phrase_group.group_desc[/i]</desc>
   <items>
     <item id="[i]phrase_item.item_name[/i]">
       <value>[i]phrase_value.value_text[/i]</value>
       <desc>[i]phrase_item.item_desc[/i]</desc>
     </item>
   </items>
</group>

Om "value_text" inte finns på nuvarande språk, ska den Engleksa frasen hämtas (den finns alltid och där är value_language = 1).

Några förslag på hur min fråga ska se ut?

Tack!

/r När går gränsen för hur mycket data som kan skrivas med mitt nuvarande tillvägagångssätt? Filerna som skapas är på 23KB styck, så jag tycker inte att det låter så mkt?!

Medlem sedan feb. 20034 441 inlägg
#4

Det var ett generalfel i koden som gjorde att loopen strulade.
Jag kör for($i = 0...) över språken, men sen nollställde jag $i innan mitt recordset skulle loopas igenom.

Det berodde på att jag kopierat koden från en annan del av sajten, samt att jag var trött.

*Case closed*

259 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
126 ms — deklarationer (db)
0 ms — hämta statistik (cache)
131 ms — hämta tråd, inlägg och bilagor (db)
125 ms — ändringar (db)