Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: TIME OUT lub CPU LIMIT skryptu
Forum PHP.pl > Forum > PHP
tom3k21
Witam wszystkich smile.gif
Mam nadzieje że jest ktoś w stanie mi pomóc rozwiązać problem ze skryptem do aktualizacji stanów magazynowych.
Otóż sklep stoi na home.pl i tutaj jest problem... (od administatorów jedyne czego się dowiedziałem to żeby przenieść na inny pakiet hostingowy tongue.gif ot tak pomocni są)... a mianowicie mają ustawione limity CPU (ok rozumie) ale także max_execution_time na ok 5min którego zmienić nie można :/ ale do sedna...

Moje wypociny ponizej i jako że jestem laikiem w programowaniu to nie bardzo wiem jak go zoptymalizować lub podzielić na części aby wykonywały się jedna po drugiej (np podzielic plik xml i jeden po drugim parsowac, plik zawiera około 10 000 produktów ~10mb).

  1. <?php
  2. //error_reporting(E_ALL);
  3. header('Content-type: text/html; charset=utf8');
  4. include 'import_config.php';
  5. include 'import_functions.php';
  6. ?>
  7. <body>
  8.  
  9. <div id="information"></div>
  10.  
  11. <?php
  12.  
  13. $xmlfile = 'import/plik.xml';
  14.  
  15. if($xml = simplexml_load_file($xmlfile)){
  16. echo "<br>Załadowano poprawnie plik XML<br>";
  17. } else {
  18. echo "<br><span style='color:red'>Nie załadowano pliku XML, operacja została przerwana</span><br>";
  19. }
  20.  
  21. $total = mysql_result(mysql_query('SELECT COUNT(id_product) FROM ps_product'), 0);
  22.  
  23. $row2 = $productid = $instock = array();
  24.  
  25. foreach($xml->offers->offer as $entry)
  26. {
  27. $productid[] = $entry->id;
  28. if(!empty($entry->instock)){
  29. $instock[] = $entry->instock;
  30. } else {
  31. $instock[] = '0';
  32. }
  33.  
  34. }
  35.  
  36. $query= mysql_query("SELECT `id_product`, `reference` FROM `ps_product`");
  37. $row = mysql_fetch_assoc($query);
  38. while($row = mysql_fetch_assoc($query)){
  39. $row2[] = $row;
  40. }
  41.  
  42. $niezmienione = $nieaktywne = $zaktualizowane = 0;
  43. for($i = 0; $i <= $total; $i++){
  44. $reference = $row2[$i]['reference'];
  45. $productid2 = array_search($reference, $productid);
  46. if(isset($reference) == $productid2){
  47. $id_produktu = mysql_result(mysql_query("SELECT id_product FROM ps_product WHERE reference = '".$reference."'"), 0);
  48. if(!empty($instock[$productid2])){$stock2 = $instock[$productid2];} else { $stock2 = 0; }
  49. @mysql_query("UPDATE ps_stock_available SET `quantity` = '".$stock2."' WHERE `id_product` = '".$id_produktu."'");
  50. if( $stock2 > 0){ $active = 1; } else { $active = 0; }
  51. @mysql_query("UPDATE ps_product_shop SET `active` = '".$active."' WHERE `id_product` = '".$id_produktu."'");
  52. $zaktualizowane++;
  53. //echo $row2[$i]['reference']. ' znaleziony ze stanem magazynowym '. $stock2 .'<br>';
  54. } else {
  55. $instock2 = '0';
  56. if((int)$reference){
  57. @mysql_query("UPDATE ps_stock_available SET `quantity` = '".$instock2."' WHERE `id_product` = '".$id_produktu."'");
  58. @mysql_query("UPDATE ps_product_shop SET `active` = '".$instock2."' WHERE `id_product` = '".$id_produktu."'");
  59. $nieaktywne++;
  60. //echo $row2[$i]['reference']. ' <span style="color:red">nie znaleziony! Zmieniono stan magazynowy na '. $instock2 .'</span><br>';
  61. } else {
  62. $niezmienione++;
  63. //echo $row2[$i]['reference']. ' <span style="color:green">Stan nie zmieniony</span><br>';
  64. }
  65. }
  66. echo '<script language="javascript">
  67. document.getElementById("information").innerHTML="'.$i.' / '.$total.'<br>Produkty zaktualizowane: '.$zaktualizowane.'<br>Produkty niezmienione: '.$niezmienione.'<br>Nieaktywne produkty: '.$nieaktywne.'";
  68. </script>';
  69. echo str_repeat(' ',1024*64);
  70. flush();
  71. }
  72. echo '<script language="javascript">document.getElementById("information").innerHTML="Aktualizacja zakonczona<br>Produkty zaktualizowane: '.$zaktualizowane.'<br>Produkty niezmienione: '.$niezmienione.'<br>Nieaktywne produkty: '.$nieaktywne.'"</script>';
  73.  
  74. mysql_close($con2);
  75. unlink($xmlfile);
  76. ?>
  77. </body>


Fragment XML:
  1. <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE nokaut SYSTEM "http://www.nokaut.pl/integracja/nokaut.dtd">
  2. -<nokaut ver="7.2" generator="Comarch ERP e-Sklep">-<offers>-<offer><id>23270</id><name>PEDAŁY DO ROWERKA JD BUG TC04G czarne </name><description> PEDAŁY DO ROWERKA JD BUG TC04G czarne Zestaw do rowerków - mechanizm do rowerków biegowych. kompatybilny z modelami Nanny i Billy. </description><price>89.41</price><weight>1.000</weight><category>Dla dzieci / Sport dla dzieci / Rowery biegowe</category><producer>Smj</producer><property name="Dostępne kolory">Czarny</property><instock>3</instock></offer></offers></nokaut>


pokrótce:
skrypt pobiera xml przy pomocy simpleXML oraz laczy sie z baza danych gdzie wcześniej zostały zaimportowane produkty z numerem ID wpisanym do tabelki `reference` i jeśli produkt istnieje zarówno w DB jak i XML jego stan magazynowy zostaje uzupelniony odpowiednią liczbą, natomiast jeśli produkt znajduje się w bazie danych ale nie w XMLu to jego stan określa się jako 0. całość opiera się na metodzie array_search() czyli przeszukuje określonego wyrażenia w całej tablicy trzymającej numery ID produktów z XML'a. I pewnie dlatego nieraz otrzymuje komunikat CPU LIMIT jednak nie wymyśliłem jakiegoś innego sposobu aby to sprawdzać.

Za każdą sugestie podpowiedź, przykład, rzut okiem na kod będę bardzo wdzięczny smile.gif
sazian
nie pchaj całej bazy do zmiennych

wrzuć sobie wszystko w tą pętle z linii 27

czyli w w uproszczeniu
  1. $i=0;
  2. $j=0;
  3. foreach($xml->offers->offer as $entry)
  4. {
  5. mysql_query("UPDATE ps_stock_available SET `quantity` = '".((int)$entry->instock)."' WHERE `id_product` in ("SELECT id_product FROM ps_product WHERE reference = '".$entry->id."'")");
  6. $i++;
  7.  
  8. }
  9. echo 'wiersze:'.$i.' zmieniono: '.$j;
  10.  


pisane z palca i nie analizowałem dokładnie twojego kodu więc mogą być błędy

----
edit:
co to za potworek if(isset($reference) == $productid2)

isset daje w wyniku boolean, a $productid2 zawiera int więc takie porównanie większego sensu niema
tom3k21
dzieki za rade jednak nie moge wykorzystac tej petelki poniewaz plik xml nie zawiera wszystkich importowanych produktów (w pliku xml hurtowni jeśli produkt jest niedostepny (0 stan) jest usuwany), dlatego muszę dokonac sprawdzenia na podstawie numerów ID (tabela: reference) już zapisanych w bazie danych.
Na razie rozwiazałem to właśnie przy pomocy array_search() dzięki której wyszukuje czy dany numer ID produktu jest w pliku XML (tablica utworzona w petli linia 27) i bazie danych

ten 'potworek' tworzący warunek choc sensu nie ma dzięki niemu jakoś to działa wmiarę poprawnie smile.gif

może masz jakiś pomysł jak ominąć tworzenie tablicy z pliku xml i dopiero w petli while dokonac sprawdzenia czy dany numer ID istnieje właśnie w pliku xml pomijając array_serach()?
Pyton_000
zamiast simplexml_load_file który pakuje całego XML do pamięci zainteresuj sie XMLRead który czyta strumieniowo, dzięki temu zaoszczędzisz masę pamięci.

Kolejnym krokiem może być (o ile często robisz importy stanów) dodanie kolumny flagi. Podczas rozpoczęcia importu ustawiasz flagi na 0 dla wszystkich.
Potem przy aktualizacji konkretnego stanu w bazie z XML zmieniasz stan flagi na 1
A na koniec dla każdego prod gdzie flaga === 0 robisz stock na 0
  1. if(isset($reference) == $productid2)

wystarczy
  1. if(false !== $productid2)
tom3k21
+plusik dla każdego za dobre chęci i rady smile.gif

Udało mi się to dopracowac (tak przynajmniej mysle) nie jest idealnie poniewaz wykorzystałem petelke for aby robiła się ograniczona ilosc produktów a nastepnie GETem pobierało na czym się zakończył poprzedni proces ale działa. Ale przez to za każdym nowym wywołaniem skryptu musi on tworzyć od nowa całą tablice z pliku xml i kontynuować od wyznaczonego miejsca (wykorzystałem XMLreader ale czy poprawnie?).

Jeszcze mam takie pytanie:
Czy jakbym chciał ten skrypt wrzucic do CRONa aby robił się automatycznie to nie bedzie problemu z takim przekazywaniem zmiennych GETem?
  1. print '<meta http-equiv="Refresh" content="0; url='.$_SERVER['PHP_SELF'].'?x='.($x+1).'&file='.$plik.'&updated='.$zaktualizowane.'&inactive='.$nieaktywne.'&dontexist='.$niezmienione.'">';


jako że nigdy nie korzystałem z CRONa to niestety nie wiem i prosiłbym tylko o jeszcze taką drobną podpowiedz smile.gif

Kodzik dla zainteresowanych:
  1. $plik = 'tmp_xml';
  2. if(isset($_GET['file'])){
  3. $xmlfile = 'import/'.$_GET['file'].'.xml';
  4. } else {
  5. $xmlfile = 'import/'.$plik.'.xml';
  6. $xmlurl = 'URL_DO_PLIKU';
  7.  
  8. $downxml = file_get_contents($xmlurl);
  9. file_put_contents($xmlfile, $downxml);
  10. }
  11.  
  12. $total = mysql_result(mysql_query('SELECT COUNT(id_product) FROM ps_product'), 0);
  13.  
  14. $xml = new XMLReader();
  15. if($xml->open($xmlfile)){
  16. echo "<br>Załadowano poprawnie plik XML<br>";
  17. } else {
  18. echo "<br><span style='color:red'>Nie załadowano pliku XML, operacja została przerwana</span><br>";
  19. }
  20. $productid = $instock = array();
  21. while ($xml->read() && $xml->name !== "offer");
  22. do {
  23. $node = new SimpleXMLElement($xml->readOuterXML());
  24. $productid[] = $node->id;
  25. if($node->instock){
  26. $instock[] = $node->instock;
  27. } else {
  28. $instock[] = '0';
  29. }
  30. } while ($xml->next('offer'));
  31.  
  32. $query= mysql_query("SELECT `id_product`, `reference` FROM `ps_product`");
  33. while($row = mysql_fetch_assoc($query)){
  34. $row2[] = $row;
  35. }
  36.  
  37.  
  38. if(isset($_GET['x']) && isset($_GET['updated']) && isset($_GET['inactive']) && isset($_GET['dontexist'])){
  39. $x = $_GET['x'];
  40. $zaktualizowane = $_GET['updated'];
  41. $nieaktywne = $_GET['inactive'];
  42. $niezmienione = $_GET['dontexist'];
  43. } else {
  44. $x = $niezmienione = $nieaktywne = $zaktualizowane = 0;
  45. }
  46. $limit = $x+1000;
  47. for($i = $x; $i <= $limit; $i++){
  48. $reference = $row2[$i]['reference'];
  49. $productid2 = array_search($reference, $productid);
  50. $id_produktu = mysql_result(mysql_query("SELECT id_product FROM ps_product WHERE reference = '".$reference."'"), 0);
  51. if(false !== $productid2){
  52. if(!empty($instock[$productid2])){$stock2 = $instock[$productid2];} else { $stock2 = 0; }
  53. @mysql_query("UPDATE ps_stock_available SET `quantity` = '".$stock2."' WHERE `id_product` = '".$id_produktu."'");
  54. if( $stock2 > 0){ $active = 1; } else { $active = 0; }
  55. @mysql_query("UPDATE ps_product_shop SET `active` = '".$active."' WHERE `id_product` = '".$id_produktu."'");
  56. $zaktualizowane++;
  57. //echo $reference. ' znaleziony ze stanem magazynowym '. $stock2 .'<br>';
  58. } else {
  59. $instock2 = '0';
  60. if((int)$reference){
  61. @mysql_query("UPDATE ps_stock_available SET `quantity` = '".$instock2."' WHERE `id_product` = '".$id_produktu."'");
  62. @mysql_query("UPDATE ps_product_shop SET `active` = '".$instock2."' WHERE `id_product` = '".$id_produktu."'");
  63. $nieaktywne++;
  64. //echo $reference. ' <span style="color:red">nie znaleziony! Zmieniono stan magazynowy na '. $instock2 .'</span><br>';
  65. } else {
  66. $niezmienione++;
  67. //echo $reference. ' <span style="color:green">Stan nie zmieniony</span><br>';
  68. }
  69. }
  70.  
  71. echo '<script language="javascript">
  72. document.getElementById("information").innerHTML="'.$x.' / '.$total.'<br>Produkty zaktualizowane: '.$zaktualizowane.'<br>Produkty niezmienione: '.$niezmienione.'<br>Nieaktywne produkty: '.$nieaktywne.'";
  73. </script>';
  74. echo str_repeat(' ',1024*64);
  75. flush();
  76.  
  77. if($i==$total){
  78. echo '<script language="javascript">document.getElementById("information").innerHTML="Aktualizacja zakończona<br>Produkty zaktualizowane: '.$zaktualizowane.'<br>Produkty niezmienione: '.$niezmienione.'<br>Nieaktywne produkty: '.$nieaktywne.'"</script>';
  79. if(unlink($xmlfile)){
  80. echo "Usunięto plik XML";
  81. } else {
  82. echo "<span style='color:red'>Nie udało się usunąć pliku XML, usuń go samodzielnie: </span>". $xmlfile;
  83. }
  84. } elseif($i==$limit){
  85. print '<meta http-equiv="Refresh" content="0; url='.$_SERVER['PHP_SELF'].'?x='.($x+1).'&file='.$plik.'&updated='.$zaktualizowane.'&inactive='.$nieaktywne.'&dontexist='.$niezmienione.'">';
  86. //print '<a href="'.$_SERVER['PHP_SELF'].'?x='.($x+1).'&file='.$plik.'&updated='.$zaktualizowane.'&inactive='.$nieaktywne.'&dontexist='.$niezmienione.'">Kontynuuj import od: .'$x'.</a>';
  87. }
  88. $x++;
  89. }


----- EDIT

Ok trochę poszperałem i już wiem że głupie pytanie zadałem bo przecież oczywiste ze meta i headers jest dla przegladarki i CRON to pominie :/
Jednak jakby ktoś mógł mi pokazać jak zamienić ten meta tag i GET na CURL byłbym ogromnie wdzięczny, ponieważ gdzieś wynalazłem iż tym da rade wykonać to co stworzyłem jako zadanie crona

Pozdrawiam
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.