Привет! Я очень начинающий, в PHP у меня есть небольшие практические навыки, но в теории пока только разбираюсь. Это был дисклеймер Буду очень рад конструктивной критике и помощи. Пишу для собственных нужд небольшой инструмент для работы с REST API. Получаю из источника данные, например, о товарах. Они разбиты постранично, объем не сказать чтоб мелкий — при 100 товарах на страницу ответ на запрос превышает 5 Мб. Источник данных иногда тормозит, и потому подключение может отваливаться. Задача — вытянуть сначала существующие товары и записать их в MongoDB. Первый скрипт выглядел так: Спойлер PHP: $products = $woocommerce->get('products?per_page=20'); // Получаем первую страницу $lastResponse = $woocommerce->http->getResponse(); // Нужно получить количество страниц из хэдера $headers = $lastResponse->getHeaders(); $totalPages = $headers['X-WP-TotalPages']; // Получаем количество страниц $productsCollection = $database->selectCollection('products'); // Указываем, куда записывать в MongoDB for ($n=1; $n<($totalPages + 1); $n++) { // Перебираем страницы $products_page = $woocommerce->get('products?per_page=20&page=' . $n); // Текущая страница echo '<b>Страница ' . $n . ' из ' . $totalPages . '</b><br>'; // Вывод номера страницы foreach ($products_page as $product) { $product_id = $product->id; // Получаем ID товара $productdata = $woocommerce->get('products/' . $product_id); // Получаем товар, отсюда можно начинать отправлять в базу //$productsCollection->insertOne($productdata); // Закомментировано, пока просто проверим, дойдет ли до конца echo 'Товар ' . $product_id . ' отправлен в базу. <br>'; // Получилось } } echo 'Готово!'; Страниц в ответе 56, на каждой по 20 товаров. Сколько я ни пытался, сколько ни отключал таймауты и ни увеличивал max_execution_time, я так ни разу и не увидел надписи «Готово!». Скрипт не доходит до конца, отваливаясь, насколько я могу понять, именно на получении очередного товара (всегда разные id). Так как я ни черта не знаю о проверках подключения, я в поисках решения не нашел ничего лучше, чем сделать циклы проверок переменных. Получилось вот так: Спойлер PHP: prodStart: $products = $woocommerce->get('products?per_page=20'); // Получаем первую страницу if ($products) { $lastResponse = $woocommerce->http->getResponse(); // Нужно получить количество страниц из хэдера $headers = $lastResponse->getHeaders(); $totalPages = $headers['X-WP-TotalPages']; // Получаем количество страниц $productsCollection = $database->selectCollection('products'); // Указываем, куда записывать в MongoDB for ($n=1; $n<($totalPages + 1); $n++) { // Перебираем страницы prodPageLoop: $products_page = $woocommerce->get('products?per_page=20&page=' . $n); // Текущая страница if ($products_page) { echo '<b>Страница ' . $n . ' из ' . $totalPages . '</b><br>'; // Вывод номера страницы foreach ($products_page as $product) { prodCycleLoop: if ($product) { $product_id = $product->id; // Получаем ID товара prodSingleLoop: $productdata = $woocommerce->get('products/' . $product_id); // Получаем товар, отсюда можно начинать отправлять в базу if ($productdata) { //$productsCollection->insertOne($productdata); // Закомментировано, пока просто проверим, дойдет ли до конца echo 'Товар ' . $product_id . ' отправлен в базу. <br>'; } else { goto prodSingleLoop; } } else { goto prodCycleLoop; } } } else { goto prodPageLoop; } } } else { goto prodStart; } echo 'Готово!'; Теоретически этот код должен долбить запрос, пока не получит ответ и не обработает его. Но даже такой код отваливается на каком-нибудь товаре. Последний раз он исполнился до 11 товара на 43 странице. Это, конечно, успех Но задача не выполнена. Скажите, есть ли какой-то более эффективный способ решения?
Оператор goto есть в PHP. Помню такое дело еще из Бейсика Подскажете, как правильнее — будет очень клёво.
Если будетelse, будет бесконечный цикл. Очень мило А с чего вы решили вообще, что вам может прийти сюда что-то ещё? --- Добавлено --- Есть. Точнее, появился в 5.3. Раза два использовал за свою карьеру шестилетнюю. В вашем случае, не понятно, что вы пытаетесь этим достичь. Не надо выполнять длительные задачи по запросу из браузера. Их надо выполнять в консольных скриптах либо использовать очереди.
@mkramer Я могу ошибаться, но смысл в том, чтобы циклически запрашивать данные, пока они не будут получены. То есть это проверка на наличие данных. Сейчас я уже вместо if($productdata) поставил if(!empty($productdata)). Но ситуацию это никак не изменило. Отваливается на рандомных местах. Ориентировочный объем данных одной страницы 2-3 МБ
Ну, во-первых, такие вещи делаются циклами while или do-while, а не с помощью goto. Goto в современном программировании стараются избегать. Во-вторых, покажите фрагменты json-ов, которые возвращаются.
Мои goto остались в бейсике. Ни разу не использовал его в работе! @Moor проверь работу скрипта на малом наборе данных, лучше из консоли, как @mkramer подсказывает.
На Бейсике goto я использовал очень часто, когда начал изучать Паскаль, то преподаватель сказал, что goto признак дурного тона, после недолговременного "разрыва шаблона" я понял красоту жизни без goto и я уже не использовал его нигде и никогда. Признаться честно я далеко не сразу узнал, что он вообще есть в РНР, узнал лишь для того что бы забыть.
@artoodetoo, @Valick, @mkramer, спасибо, уроки некоторые для себя вынес, читаю мануалы. В сообщение форума не влезает даже JSON одного товара По ссылке 1 товар, не самый объемный https://codeshare.io/Gb1mBj
В корень зрите Я перепроверил — общего запроса хватает для товаров. Просто перед этим делал заказы, там надо было в каждый заходить. Я уже упростил, и заработало как надо. Правда, пришлось пошаманить, потому что массиве есть ключи, которые содердат точку, Монго их не любит, и скрипт падал. В общем, вот что получилось: Спойлер PHP: $products = $woocommerce->get('products'); // первая страница $a = 0; // счетчик — посмотрим, совпадет ли количество $find = 'amazonS3_cache'; // дрянь, из-за которой добавление в базу не работает $lastResponse = $woocommerce->http->getResponse(); $headers = $lastResponse->getHeaders(); $totalPages = $headers['X-WP-TotalPages']; // получаем количество страниц $productsCollection = $database->selectCollection('products'); // отправляем в эту коллекцию for ($n=1; $n<($totalPages + 1); $n++) { // перебираем страницы, пока не кончатся $products_page = $woocommerce->get('products?page='.$n); // добавляем номер страницы echo '<b>Страница ' . $n . ' из ' . $totalPages . '</b><br>'; ////////////// foreach ($products_page as $product) { // перебираем товары на каждой странице $product_id = $product->id; foreach($product->meta_data as $struct) { // ищем дрянь if ($find == $struct->key) { unset($struct->value); // очищаем ключи дряни } } $productsCollection->insertOne($product); echo 'Товар ' . $product_id . ' отправлен в базу.<br>'; ////////////// $a++; // плюс 1 к счетчику } } echo '<h1>' . $a . ' товаров добавлено!</h1>'; Буду очень признателен за любые советы и комментарии по делу.