If you create an instance and insert a record in each loop, it will create a Music instance and 1 insert query for each loop and this is not efficient. What if you save data to an array first, chunk it, and then save it to database.
For example, you have 1000 music data, if you make music instance for each loop, it will create 1000 times of Music instance and 1000 times of insert operation in database. But if you save your music data first into an array and chunk it to 20 array (each array contains 50 music data) it will execute 20 insert operations only. Kinda more efficient, isn't?
So, your codes will looks like it :
<?php
use AppMusic;
Music::truncate(); //clear existing data
DB::disableQueryLog(); //helps speed up queries by disabling log
ini_set('memory_limit', '512M'); //boost memory limit
ini_set('max_execution_time', '90'); //try to prevent time-out
//list of files to import (I sometimes have more than 1):
$files = [
"path/to/my/database.xml",
"path/to/my/database2.xml"
];
$video_files = ["mp4","mov","avi","flv"]; //used to identify music videos
//declare array of music here
$arrayOfMusic = [];
foreach($files as $file){
$reader = new XMLReader();
if(!$reader->open($file)){
die("Failed to open xml file!");
}
$doc = new DOMDocument;
while ($reader->read() && $reader->name !== 'Song');
while ($reader->name === 'Song') {
$song = simplexml_import_dom($doc->importNode($reader->expand(), true));
if(strpos($song['FilePath'], 'netsearch://') === false && strpos($song['FilePath'], ':/DJ Tools/') === false) {
foreach ($song->Tags as $tag) {
if (($tag['Author'] != "" || $tag['Title'] != "") && ($tag['Grouping'] != "Studio")) {
$insert = true; //insert record or not
foreach ($song->Infos as $info) {
$length = gmdate("H:i:s",floatval($info['SongLength']));
$file_date = date("Y-m-d",intval($info['FirstSeen']));
}
if($insert == true){
//set the kind (audio, video or karaoke):
if(strpos($song['FilePath'], '/Karaoke/') !== false){
$kind = "karaoke";
} elseif (in_array(strtolower(substr($song['FilePath'],-3)),$video_files)) {
$kind = "video";
} else{
$kind = "audio";
}
//Fill array of music
$arrayOfMusic[] = [
'bpm' => ($tag['Bpm'] > 0) ? round(1 / floatval($tag['Bpm']) * 60) : null, //to calculate use 1/bpm * 60 and round
'file_path' => $song['FilePath'],
'artist' => trim($tag['Author']),
'length' => $length ?? '0', //set $length to 0 if it cannot be found
'file_date' => $file_date ?? '0', //set $file_date to 0 if it cannot be found
'title' => trim($tag['Title']),
'remix' => trim($tag['Remix']),
'album' => trim($tag['Album']),
'genre' => trim($tag['Genre']),
'filetype' => substr($song['FilePath'],-3),
'year' => ($tag['Year'] > 0) ? intval($tag['Year']) : null;
'kind' => $kind,
];
}//end if insert true
} //end has title or author + non-studio
} //end for each tag
} //end not a netsearch file
$reader->next('Song');
} //end while
$reader->close();
} //end for each files
//Chunk the array if $arrayOfMusic is not null
if (!empty($arrayOfMusic)) {
$arrayOfMusicChunked = array_chunk($arrayOfMusic, 30); //Chunk large array, in this example, chunked array will contains 30 items
//loop the array and insert it use insert() function
foreach ($arrayOfMusicChunked as $arrayOfMusicToSave) {
Music::insert($arrayOfMusicToSave);
}
}
Source
- https://www.w3schools.com/php/func_array_chunk.asp
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…