У меня есть CSV-файл, который имеет около 500000 строк. Что мне нужно сделать, это взять первые 100 строк в первом цикле и манипулировать строками (скажем, отправить первые 100 идентификаторов в API и сохранить ответ). Во втором цикле пропустите первые 100 строк (уже занятых), возьмите еще 100 строк и отправьте запрос в веб-службу. Точно так же в третьем цикле пропустите первые 200 строк, возьмите еще 100 строк и отправьте запрос в веб-службу и так далее …
Я могу взять по одной каждой строке с кодом ниже. (проверено: отлично работает)
if (($handle = fopen($filename, "r")) !== FALSE) {
$id = 1;
$line = fgetcsv($handle); //skip first row
//fetch data from each row
while (($data = fgetcsv($handle, ",")) !== FALSE) {
$hotel_id = $data[0];
//call service to request to web service
$hotelDetailRequest = (new \Services\Hotel\Hotel)->getHotelStaticData($hotel_id);
//do stuff to response
}
}
Точно так же я могу пропустить некоторые начальные строки, как если бы я пропустил добавление первой строки
$line = fgetcsv($handle);
$line = fgetcsv($handle);
$line = fgetcsv($handle);
Но это не мой ожидаемый результат, как объяснено выше. Я использую PHP (Laravel). Я погуглил, но не смог найти ни одного подходящего, соответствующего моим критериям. Кто-нибудь сталкивался с такой же проблемой?
Любая помощь будет оценена. Благодарю вас
вот решение для вас:
<?php
$filename = "the_data.csv";
$chunk_size = 200;
// parse csv file into an array
$csv_data = array_map('str_getcsv', file($filename));
// split data array into chunks
$chunked_data = array_chunk($csv_data, $chunk_size);
foreach($chunked_data as $chunk){
// here you have $chunk_size row data
// iterate in chunk
foreach($chunk as $row ){
$hotel_id = $row[0];
// send request to web service
// do stuff to response
}
sleep(1);
}
?>
Вы можете использовать SplFileObject
в сочетании с ->seek($start)
, Мы можем сделать ссылку на limit/offset
отношения, которые вы бы использовали с обычной базой данных MySQL; вот пример:
$file = SplFileObject("myfile.csv");
$rules = DB::query("select * from file_rules where id = 1");
if ($rules->limit) {
$file->seek($rules->offset);
}
На этом этапе вы можете просто выполнить простой цикл и сравнить счетчик индекса со значением вашего смещения.
foreach ($file as $index => $row ) {
if ($file->valid() && $index <= $rules->limit ) {
//perform your calls to do your API request
}
}
Когда вы закончите, просто обновите записи вашей БД:
DB::query('update file_rules set offset='.$rules->offset+$rules->limit.' where id =1');
Это суть этого. Замените мой код psuedo БД своим. Это позволит вам выполнить его как CRON и использовать базу данных в качестве точки взаимодействия, чтобы получить ваш limit/offset
и применить его к вашей петле с seek
для дальнейшего сохранения памяти.