Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ PHP _ [SOLVED] pobieranie aukcji przez api i paginacja

Napisany przez: Aquarius 22.07.2015, 12:28:14

witam,
udało mi się przerobić po wielu bojach starą metodę pobierania informacji o aukcjach na nową (w końcu zrozumiałem czemu ktoś w internecie napisał że to Allegro API to koszmar programisty), nie otrzymuję już błędów przy pobieraniu informacji, mam jednak problem z paginacją (stronicowaniem), załączam cały kod, być może przyda się komuś do przejścia na nową metodę:

  1. $offset = ($_GET['id']) ;
  2. $limit = 12;
  3. $soap = new SoapClient('https://webapi.allegro.pl/service.php?wsdl', http://www.php.net/array('trace' => true));
  4.  
  5. $items = $soap->doGetItemsList(
  6. http://www.php.net/array(
  7. 'webapiKey' => 'XXXXXXXX',
  8. 'countryId' => 1,
  9. 'filterOptions' => http://www.php.net/array(
  10. http://www.php.net/array(
  11. 'filterId' => 'userId',
  12. 'filterValueId' => http://www.php.net/array('XXXXXXX')
  13. )
  14. )
  15. )
  16. );
  17.  
  18. $items = get_object_vars($items);
  19. $ile_stron = $items['itemsCount'] / $limit;
  20. $pag = http://www.php.net/floor($ile_stron);
  21. if ($offset >= "1") {
  22. $back = ($_GET['id'] - 1);
  23. }
  24. else {
  25. $back = $pag;
  26. }
  27. if ($offset != $ile_stron) {
  28. $next = ($_GET['id'] + 1);
  29. }
  30. else {
  31. $next = "0";
  32. }
  33. http://www.php.net/echo "<span style=\"font-size: 16px\"><strong>Strona:</strong></span><br /><div style=\"line-height: 16px;padding-top: 5px\"><a href=\"aukcje?id=".$back."\"><img src=\"images/arrow-left.png\" style=\"padding-right:3px\" /></a> <span style=\"font-size: 16px\"><a href=\"aukcje?id=0\"> 0 </a>";
  34. for($i = 1; $i < $ile_stron; $i++)
  35. {
  36. http://www.php.net/echo '<a href="aukcje?id='.$i.'"> '.$i.' </a>';
  37. }
  38. http://www.php.net/echo " <a href=\"aukcje?id=".$next."\"><img src=\"images/arrow-right.png\" style=\"padding-left:3px\" /></a></span></div><br /><br />";
  39.  
  40. for($i=0;$i<$limit ;$i++)
  41. {
  42. http://www.php.net/echo '<div style="margin-right: 10px;margin-bottom: 10px;display: inline-block;">';
  43. http://www.php.net/echo '<a target="_blank" href="http://allegro.pl/show_item.php?item='.$items[$i]['itemsList']['itemId'].'"><img src="'.$items[$i]['itemsList']['photosInfo']['photoUrl'].'"/></a>';
  44. http://www.php.net/echo '<div style="width: 130px;margin-top: 5px;margin-bottom: 8px;line-height: 16px"><span style="line-height:14px;font-size: 11px;font-weight: bold">'.$items[$i]['itemsList']['itemTitle'].'</span><br />';
  45. if ($items[$i]['itemsList']['priceInfo']['priceType'] == "buyNow") {
  46. http://www.php.net/echo '<span style="line-height:20px;color: red;font-size: 16px;font-weight: bold">'.$items[$i]['itemsList']['priceInfo']['priceValue'].' zł</span></div>';
  47. }
  48. else {
  49. http://www.php.net/echo '<span style="line-height:20px;color: red;font-size: 16px;font-weight: bold">'.$items[$i]['itemsList']['priceInfo']['priceValue'].' zł</span></div>';
  50. }
  51. http://www.php.net/echo '</div>';
  52. }



problem w tym że serwer zwraca błąd:
Kod
PHP Notice:  Undefined offset: 0
PHP Notice:  Undefined offset: 1
PHP Notice:  Undefined offset: 2
PHP Notice:  Undefined offset: 3
PHP Notice:  Undefined offset: 4
PHP Notice:  Undefined offset: 5
PHP Notice:  Undefined offset: 6
PHP Notice:  Undefined offset: 7
PHP Notice:  Undefined offset: 8
PHP Notice:  Undefined offset: 9
PHP Notice:  Undefined offset: 10
PHP Notice:  Undefined offset: 11



przypuszczam że mam błąd w kodzie, jednak przejrzałem go już tyle razy i nie mam pojęcia w czym problem, proszę o pomoc

Napisany przez: IProSoft 22.07.2015, 14:28:45

Co zwróci

  1. http://www.php.net/var_dump($items);
?

Napisany przez: Aquarius 23.07.2015, 07:21:03

mniej więcej tak to wygląda:

Kod
array(5) { ["itemsCount"]=> int(501) ["itemsFeaturedCount"]=> int(0) ["itemsList"]=> object(stdClass)#3 (1) { ["item"]=> array(100) { [0]=> object(stdClass)#4 (14) { ["itemId"]=> int(5118545340) ["itemTitle"]=> string(36) "RENAULT TRAFIC 2011 2,5 DCI KOMPLET" ["leftCount"]=> int(1) ["bidsCount"]=> int(0) ["biddersCount"]=> int(0) ["quantityType"]=> string(6) "pieces" ["timeToEnd"]=> string(27) "do wyczerpania przedmiotów" ["categoryId"]=> int(50851) ["conditionInfo"]=> string(4) "used" ["promotionInfo"]=> int(0) ["additionalInfo"]=> int(0) ["sellerInfo"]=> object(stdClass)#5 (5) { ["userId"]=> int(4921350) ["userLogin"]=> string(9) "xxxxxx" ["userRating"]=> int(225) ["userIcons"]=> int(10) ["countryId"]=> int(1) } ["priceInfo"]=> object(stdClass)#6 (1) { ["item"]=> array(2) { [0]=> object(stdClass)#7 (2) { ["priceType"]=> string(6) "buyNow" ["priceValue"]=> float(14000) } [1]=> object(stdClass)#8 (2) { ["priceType"]=> string(12) "withDelivery" ["priceValue"]=> float(14160) } } } ["photosInfo"]=> object(stdClass)#9 (0) { } } [1]=> object(stdClass)#10 (14)

...


pominąłem konwersję na zmienne:
  1. //$items = get_object_vars($items)


i chcę teraz wywołać dane w ten sposób:
  1. for($i=0; $i < $limit; $i++)
  2. {
  3. http://www.php.net/echo '<div style="margin-right: 10px;margin-bottom: 10px;display: inline-block;">';
  4. http://www.php.net/echo '<a target="_blank" href="http://allegro.pl/show_item.php?item='.$items[$i]->itemsList->itemId.'"><img src="'.$items[$i]->itemsList->photosInfo->photoUrl.'"/></a>';
  5. }


jednak tak jest jeszcze gorzej:
Kod
PHP Fatal error:  Cannot use object of type stdClass as array

Napisany przez: thek 23.07.2015, 08:18:54

Przyjrzyj się strukturze zwrotnej z serwisu i dopasuj do tego pętlę smile.gif var_dump Ci jasno pokazuje ją, a PHP także daje wskazówkę, że coś nie tak jest z indeksem. Może po prostu iterujesz nie po tym co trzeba? wink.gif Jeśli nadal nie kumasz to rozpiszę Ci to nieco według tego co pokazuje var_dump jaki dałeś:

Kod
$items = array(5) {
   ["itemsCount"]=> int(501) <- element tablicy typu int
   ["itemsFeaturedCount"]=> int(0)  <- element tablicy typu int
   ["itemsList"]=> object(stdClass)#3 (1) { element tablicy typu object
      ["item"]=> array(100) { <- atrybut obiektu typu array
         [0]=> object(stdClass)#4 (14) { element tablicy typu object
            ["itemId"]=> int(5118545340) <- atrybut obiektu typu int
(...)

Widzisz dlaczego $items[0] zawoła błędem? Oraz dlaczego $items[0]['itemsList']['itemId'] także się wysypie? Wcale nie patrzysz na dane zwracane, ich strukturę i typy oraz z bardzo radosną twórczością podchodzisz do nich wink.gif Popatrz na to jak ja rozpisałem co jest czym i wyciągnij wnioski kiedy używać [], kiedy -> a kiedy użyć pętli...

EDIT: I uważaj na zawartość "itemsList" oraz "item", bo "itemsCount" sugeruje istnienie 501 przedmiotów, ale już "item" wskazuje 100, a reszty var_dump brak, więc ciężko wyrokować o dalszej strukturze całości i jak obie wartości współgrają ze sobą. Myślę, że ta mała uwaga naprowadzi Cię na to, gdzie byka w logice robisz.

Napisany przez: Aquarius 23.07.2015, 08:30:04

ok, właśnie dochodziłem do tego że trzeba każdy element tej pętli "wylistować" aby otrzymać element docelowy, pomogło rozpisanie sobie struktury całej pętli elementów obiektu do nowej linii, każdą pętlę elementu do nowej itd.,
czyli:

  1. for($i=0; $i < $limit; $i++)
  2. {
  3. http://www.php.net/echo '<div style="margin-right: 10px;margin-bottom: 10px;display: inline-block;">';
  4. http://www.php.net/echo '<a target="_blank" href="http://allegro.pl/show_item.php?item='.$items->itemsList->item[0]->itemId.'"><img src="'.$items->itemsList->item[0]->photosInfo->item[1]->photoUrl.'"/></a>';
  5. }


i to działa już dobrze, informacje pobrane i poprawnie wyświetlone

słabo u mnie z pisaniem obiektowym i to tylu elementów, czas to podciągnąć bo to podobno przyszłość PHP, pytanie teraz jak to zapętlić aby otrzymać te 12 aukcji? jak tylko próbuję zapętlić wywala mi błąd że nie można zapętlić obiektu:

Kod
Cannot use object of type stdClass as array


co do item które podaje wartość 100 elementów to dlatego że Allegro ma limit pobierania 100 aukcji jednocześnie, aby pobrać większą zawartość trzeba to zdefiniować przy inicjacji połączenia api

Napisany przez: thek 23.07.2015, 08:42:11

To może napisz jak tę pętlę chcesz przeprowadzić? Bo sprawa jest prosta jeśli tylko chwilkę pomyślisz. To wariacja na temat jednej pętli, numeru strony i limitu na stronę. Inna sprawa że użycie floor do wyliczania ilości stron wprowadzi Cię w mały kłopot, skoro mając 14 elementów floor(14/12) = 1? wink.gif

EDIT: Jeśli limit przedmiotów to 100, to chyba warto też zwrócić uwagę czy dostajemy 100 czy tyle ile wskazuje "itemsCount", bo inaczej z paginacją też będą cyrki smile.gif bo 501 podzielisz na 12, da Ci to około 40 stron, ale tylko 9 będzie cokolwiek zawierać biggrin.gif

Napisany przez: Aquarius 23.07.2015, 08:52:18

zapętlać się zapętla do tych 12 elementów, ale dostaję 12 tych samych, jak miałem zmienne zamiast obiektów w poprzedniej metodzie pobierania aukcji to najnormalniej zwiększałem numer wyświetlanej aukcji poprzez

Kod
[$i]


no i pętla for
  1. for($i=0; $i < $limit; $i++)

robiła swoje

tutaj właśnie kiedy chcę zapętlić dostaję informację
Kod
Cannot use object of type stdClass as array



co do limitów API - powinienem oczywiście to inaczej zrobić, mianowicie definiować na każdej stronie że chcę pobrać 12 aukcji, na każdej kolejnej również 12 począwszy od (strona poprzednia * 12), ale problem sprawiało mi samo wyświetlanie jak na razie

Napisany przez: thek 23.07.2015, 08:55:32

Chodzi mi o to po czym iterujesz... gdzie jest to $i, które potem łapiesz. Jak wygląda Twoje wnętrze pętli for. Bo to tam siedzi diabeł smile.gif

Napisany przez: Aquarius 23.07.2015, 09:00:14

starą dobrą metodą prób i błędów sprawdzałem i na początku:

  1. for($i=0; $i < $limit; $i++)
  2. {
  3. http://www.php.net/echo '<a target="_blank" href="http://allegro.pl/show_item.php?item='.$items[$i]->itemsList->item[0]->itemId.'"><img src="'.$items[$i]->itemsList->item[0]->photosInfo->item[1]->photoUrl.'"/></a>';
  4. }


i na końcu:
  1. for($i=0; $i < $limit; $i++)
  2. {
  3. http://www.php.net/echo '<a target="_blank" href="http://allegro.pl/show_item.php?item='.$items->itemsList->item[0]->itemId[$i].'"><img src="'.$items[$i]->itemsList->item[0]->photosInfo->item[1]->photoUrl[$i].'"/></a>';
  4. }


zazwyczaj problemu ze zrozumieniem że tak jest źle albo tak jest dobrze nie mam, ale pierwszy raz trafiło mi się zderzyć z taką ilością elementów i pętli w obrębie jednego obiektu, oczywiście zdaję sobie sprawę że tak to nie może być bo oznaczałoby to element w strukturze samego obiektu a nie iterację

Napisany przez: aniolekx 23.07.2015, 09:36:53

  1. foreach ($items->itemsList->item as $item) {
  2. {
  3. http://www.php.net/echo '<a target="_blank" href="http://allegro.pl/show_item.php?item='.$item->itemId.'"><img src="'.$item->photosInfo->item[1]->photoUrl.'"/></a>';
  4. }



chyba tak bedzie czytelniej? wink.gif

Napisany przez: thek 23.07.2015, 09:45:00

W takim wypadku chyba nadal nie widzisz gdzie jest Twoja tablica z obiektami. Chyba zrobię to co poprzednio i Ci to rozpiszę smile.gif

Kod
$items = array(5) {
   ["itemsCount"]=> int(501) <- element tablicy zawierający liczbę przedmiotów
   ["itemsFeaturedCount"]=> int(0)  <- element tablicy zawierający liczbę przedmiotów wyszczególnionych
   ["itemsList"]=> object(stdClass)#3 (1) { element tablicy typu object zawierający listę wszystkich informacji związanych z przedmiotami
      ["item"]=> array(100) { <- atrybut obiektu  będący tablicą przedmiotów
         [0]=> object(stdClass)#4 (14) { element tablicy typu object będący konkretnym przedmiotem
            ["itemId"]=> int(5118545340) <- atrybut przedmiotu
(...)

Napisany przez: Aquarius 23.07.2015, 10:23:17

zrobiłem tak jak się należało od początku, czyli pobranie 12 aukcji (a nie 100), dla każdej strony inną porcję zaczynając tak jak pisałem wcześniej od

  1. $resultOffset = ($offset - 1) * 12;


i tu już było łatwiej dla mnie bo wystarczyło zapętlić w pętli foreach tak jak zasugerował aniolekx

w oczekiwaniu na odpowiedzi do tematu poczytałem trochę o zapętlaniu obiektów, ale nie wpadłem na żaden trop jaki podsuwałeś thek, być może będę miał jeszcze w przyszłości okazję (czyt. potrzebę)
w każdym razie sposób z pobieraniem od razu właściwej porcji aukcji jest poprawniejszy,

podziękował pięknie za podpowiedzi smile.gif


PS. co do funkcji floor - uważałem że jest ona tutaj właściwa, ale zaokrąglenie w dół np. 41,75 strony da mi 41 stron czyli niewłaściwą ilość (41 * 12 = 492), w moim przypadku przy 12 wynikach na stronę, zamieniłem ją na ceil

Napisany przez: thek 23.07.2015, 12:25:03

I o to mi chodziło co rzucił @aniolekx smile.gif Chciałem byś zauważył, że u Ciebie iteracja idzie po $items->itemsList->item, bo to jest wlaściwa tablica obiektów klasy stdClass smile.gif Ty wcześniej iterowałeś albo za płytko (po $items), więc rzucało Ci undefined index, albo za głęboko ($items->itemsList->item[0]->itemId), co kończyło się próbą iteracji po liczbie typu int wink.gif A nie sugerowałem Ci foreach, bo foreach potrafi iterować po publicznych atrybutach obiektu. To by Cię mogło zupełnie w błąd wprowadzić. Dlatego taki nacisk położyłem na zrozumienie przez Ciebie struktury odpowiedzi zwracanej przez serwer. Tak byś sam załapał co jest nie tak.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)