Ich habe ein Problem mit meinem Skript, das Einträge aus einer CSV-Datei importiert und sie als benutzerdefinierte WordPress-Posts einfügt (jede Zeile ist ein einzelner Post) … Anfangs habe ich die Importfunktion in einer eigenen Klasse eingerichtet und das hat kaum funktioniert … nach dem, was ich gesammelt habe, war das Problem, dass die globalen Variablen nicht zwischengespeichert werden und jedes Mal, wenn ich die Instanz aufrufe, mehr Speicher verbraucht wird, bis der Prozess keinen Speicher mehr hat und abstürzt … also habe ich die Klasse und den Satz entfernt Importieren Sie die Importfunktion wie im folgenden Code beschrieben.
Mit diesem Setup habe ich den Punkt erreicht, an dem es mit bis zu 17.000 Posts gut funktioniert, aber wenn ich versuche, mehr Posts als das zu importieren, bricht es einfach ohne Fehler ab (keine Fehler werden in meinem PHP-Fehlerprotokoll oder der WordPress debug.log-Dateien)
Das Skript fügt erfolgreich 17.000 Posts ein und druckt die Echoinformationen bis zu dem Punkt, an dem es vorzeitig bei “XXX verbleibende Elemente” stoppt, und es beendet das Laden der Seite, wobei an diesem Punkt nichts mehr ausgegeben wird … es schafft es nie bis zum Finale echo "Done!";
Aussage…
Dies geschieht sowohl in der Localhost-Entwicklungsumgebung als auch auf einem gehosteten Entwicklungsserver. Ich habe die Speicherauslastung im Auge behalten, und sie überschreitet auf meinem lokalen Host nie 60 % (beginnt bei ~50 %), und ich sehe keinen schrittweisen Speicheranstieg, der auf einen Speicherverlust hindeutet…
Ich habe auch versucht, ini_set(‘memory_limit’, ’64M’) zu verwenden; und set_time_limit(0);
Nach dem, was ich über einige andere ähnliche Fragen zu diesem Thema gelesen habe,
- für SQL sollten 20k Einträge keine große Sache sein
- WordPress sollte das auch können, wenn der Server leistungsfähig genug ist
Welche Art von Optimierungen/Verbesserungen kann ich am folgenden Code vornehmen, damit dieses Skript in dieser Größenordnung funktioniert?
oder vielleicht die eingebaute WordPress-Funktionalität überspringen und alles mit LOAD DATA INFILE verarbeiten, wie von fancypants hier erwähnt
Ich würde die Daten lieber über die bereitgestellte WordPress-Funktionalität verarbeiten.
Die CSV-Datei ist ~ 1 MB …
der Code:
diese Funktionen befinden sich in einer eigenen Datei – import.php
function fileupload_process() {
ini_set('memory_limit', '64M');
set_time_limit(0);
$uploadfiles = $_FILES['uploadfiles'];
if (is_array($uploadfiles)) {
foreach ($uploadfiles['name'] as $key => $value) {
// look only for uploaded files
if ($uploadfiles['error'][$key] == 0) {
$filetmp = $uploadfiles['tmp_name'][$key];
if (($handle = fopen($filetmp, "r")) !== FALSE) {
$flag = true;
$songs = explode("\n",file_get_contents($filetmp));
$count = count( $songs );
unset($songs);
echo "Total item count: " . $count . "<BR />";
// typical entry: If You Have To Ask,Red Hot Chili Peppers,0:03:37, Rock & Alternative,1991,on
// using a generous 1000 length - will lowering this actually impact performance in terms of memory allocation?
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// Skip the first entry in the csv containing colmn info
if($flag) {
$flag = false;
echo "<BR />";
$count--;
continue;
}
// insert the current post and relevant info into the database
$currently_processed = process_custom_post($data, $count);
$count--;
}
echo "Done!";
fclose($handle);
}
unlink($filetmp); // delete the temp csv file
}
}
}
} // END: file_upload_process()
function process_custom_post($song, $count) {
$track = (array_key_exists(0, $song) && $song[0] != "" ? $song[0] : 'N/A');
$artist = (array_key_exists(1, $song) && $song[1] != "" ? $song[1] : 'N/A');
$length = (array_key_exists(2, $song) && $song[2] != "" ? $song[2] : 'N/A');
$genre = (array_key_exists(3, $song) && $song[3] != "" ? $song[3] : 'N/A');
$year = (array_key_exists(4, $song) && $song[4] != "" ? $song[4] : 'N/A');
$month = (array_key_exists(5, $song) && $song[5] != "" ? $song[5] : 'N/A');
$playlist = (array_key_exists(6, $song) && $song[6] != "" ? $song[6] : '');
$custom_post = array();
$custom_post['post_type'] = 'songs';
$custom_post['post_status'] = 'publish';
$custom_post['post_title'] = $track;
echo "Importing " . $artist . " - " . $track . " <i> (" . $count ." items remaining)...</i><BR />";
$post_id = wp_insert_post( $custom_post );
$updated = update_post_meta($post_id, 'artist_name', $artist);
$updated = update_post_meta($post_id, 'song_length', $length);
$updated = update_post_meta($post_id, 'song_genre', $genre);
$updated = update_post_meta($post_id, 'song_year', $year);
$updated = update_post_meta($post_id, 'song_month', $month);
$updated = update_post_meta($post_id, 'sample_playlist', $playlist);
return true;
} // END: process_custom_post()
function import_page () {
//HTML for the import page + the file upload form
if (isset($_POST['uploadfile'])) {
fileupload_process();
}
}
Die import.php ist in einem WordPress-Plugin außerhalb der Klasse des Plugins enthalten
dh hier sind die relevanten Informationen darüber, wie ich das Skript auf der Importseite bekomme:
define( 'MY_PLUGIN_ROOT' , dirname(__FILE__) );
include_once( MY_PLUGIN_ROOT . 'import.php');
class my_plugin () {
function __construct() {
add_action( 'init', array( &$this, 'admin_menu_init' ) );
}
function admin_menu_init() {
if(is_admin()) {
//Add the necessary pages for the plugin
add_action('admin_menu', array(&$this, 'add_menu_items'));
}
}
function add_menu_items() {
add_submenu_page( 'edit.php?post_type=songs', 'Import Songs', 'Import Songs', 'manage_options', 'import-songs', 'import_page' );
}
}
Alle Gedanken, Kommentare oder Empfehlungen würden sehr geschätzt.
Das einzige, was ich empfehlen kann, ist, Ihre Zählung in der While-Schleife zu erhalten, anstatt die gesamte Datei zu lesen und sie dann zu explodieren, um die Zählung zu erhalten. Außerdem scheint es, als würden Sie den Zähler nur verwenden, um ihn für die menschliche Lesbarkeit auszugeben. Immer wenn ich große Importe mache, echoe ich nur am Ende, vielleicht ein paar Zeilen, die Ausgabe von 20.000 Zeilen auf dem Bildschirm könnte ein weiteres Problem sein.
– Bryan
29. September 2013 um 19:29 Uhr
Ich habe alle Echo-Anweisungen entfernt, mit Ausnahme des abschließenden Echos ‘Fertig!’; Ich habe die Zähldatei-Explosion weggelassen und sie innerhalb der Schleife implementiert … es importiert immer noch nicht alle Posts, stoppt bei ~ 17K … Allerdings bekomme ich jetzt einen 500 Internal Server Error, obwohl die Server-Logfiles meines Providers absolut fehlerfrei sind?? Ich werde versuchen, dies auf localhost zu tun, da ich mehr Übersicht zur Verfügung habe, und hoffentlich werde ich sehen, ob ich das Problem aufspüren kann, das dies verursacht ….
– zoranc
29. September 2013 um 22:51 Uhr
Kein Glück, localhost beendet sich ohne Fehler wie zuvor … trotzdem danke für die Vorschläge
– zoranc
30. September 2013 um 1:56 Uhr
Nehmen Sie Originalbeiträge aus der lokalen/entfernten Datenbank, oder ist die CSV-Datei Ihre einzige Quelle für Beitragsdaten? Wenn Sie Zugriff auf db haben, geben Sie einfach Tabellen in SQL-Dateien aus
– Gwillie
30. September 2013 um 4:38 Uhr
Ich frage mich, ob es kein Problem mit der Datei um Zeile 17k gibt?
– Bryan
1. Oktober 2013 um 6:32 Uhr