질문/조언질답게시판

        $new_data = new stdClass();
        self::initData($geo, $new_data);

        //공기
        $aqicn_url = 'https://api.waqi.info/feed/geo:'.$geo->lat.';'.$geo->lng.'/?token='.$_aqicn_token;
        if($air = json_decode(self::file_get_contents_curl($aqicn_url, $_timeout)) && $air->status=='ok')
        {

            $new_data->aqi = self::getAirQualityIndex((int)$air->data->aqi);
            $new_data->aqi->pm10 = $air->data->iaqi->pm10->v;
            $new_data->aqi->pm10_color = self::getAirQualityIndex((int)$new_data->aqi->pm10, 'color');
            $new_data->aqi->pm25 = $air->data->iaqi->pm25->v;
            $new_data->aqi->pm25_color = self::getAirQualityIndex((int)$new_data->aqi->pm25, 'color');
            $new_data->aqi->time = date('H:i', strtotime($air->data->time->s));
            $new_data->aqi->time_full = $air->data->time->s;
        }
        elseif($air->status!='ok')
        {
            $new_data = new stdClass();
            self::initData($geo, $new_data);
            if($air = json_decode(self::file_get_contents_curl($aqicn_url, $_timeout)))
            {
                $air = json_decode(self::file_get_contents_curl($aqicn_url, $_timeout));
                $new_data->aqi = self::getAirQualityIndex((int)$air->data->aqi);
                $new_data->aqi->pm10 = $air->data->iaqi->pm10->v;
                $new_data->aqi->pm10_color = self::getAirQualityIndex((int)$new_data->aqi->pm10, 'color');
                $new_data->aqi->pm25 = $air->data->iaqi->pm25->v;
                $new_data->aqi->pm25_color = self::getAirQualityIndex((int)$new_data->aqi->pm25, 'color');
                $new_data->aqi->time = date('H:i', strtotime($air->data->time->s));
                $new_data->aqi->time_full = $air->data->time->s;
            }
            elseif($cache_data)
            {
                $new_data->aqi = $cache_data->aqi;
            }
        }

 

 

php를 잘 모르는 입장에서 기존에 쓰여진 코드를 보고 수정해 본건데요.

 

이렇게 하는 이유는 간헐적으로 api에서 첫번째 시도시 비정상 응답을 하는 경우가 있습니다. 

이때 다시 한번 요청시에는 거의 100% 정확한 응답을 하기때문에 실패시 한번을 더 시도하는 것으로 해보고 싶어 이렇게 고쳐 보았는데요.

 

물론 캐시는 ok 응답이 있을때만 저장하도록 밑에서 처리했습니다.

 

위 코드가 제가 의도한 대로 동작하고 문제가 되는 부분은 없을까요 ?

  • profile
    혹시라도 계속 실패할 때를 대비해서 재시도 한도를 고려하는것도 좋을 것 같아요. 괜히 무한루프가 걸리실가봐서요.그리고 재시도 할때도 혹시라도 무한루프로 서버 다운이 되지 않도록 슬립을 한번 주시는것도 좋을것 같아요.
  • profile profile

    제가 봤을때는 딱 1번만 더 시도하는 걸로 생각하고 코드를 짠건데 무한루프가 걸리게 되나요??

  • profile profile
    글쎄요... 코드가 정확히 어떻게 되어 있는지는 잘 몰라서요..
  • profile profile
    따로 반복문은 없습니다. 그냥 위 코드가 전부라고 생각하셔도 될 것 같은데요.
  • profile

            $new_data = new stdClass();
            self::initData($geo, $new_data);

            // API 주소 및 재시도 횟수
            $aqicn_url = 'https://api.waqi.info/feed/geo:'.$geo->lat.';'.$geo->lng.'/?token='.$_aqicn_token;

            $retry_count = 0;

     

            // 최대 5회까지 요청

            while($retry_count < 5) {

                $air = json_decode(self::file_get_contents_curl($aqicn_url, $_timeout))

                if(isset($air->status) && $air->status == 'ok') break;

                $retry_count++;

            }

     

            if($air->status == 'ok') {

                $new_data->aqi = self::getAirQualityIndex((int)$air->data->aqi);
                $new_data->aqi->pm10 = $air->data->iaqi->pm10->v;
                $new_data->aqi->pm10_color = self::getAirQualityIndex((int)$new_data->aqi->pm10, 'color');
                $new_data->aqi->pm25 = $air->data->iaqi->pm25->v;
                $new_data->aqi->pm25_color = self::getAirQualityIndex((int)$new_data->aqi->pm25, 'color');
                $new_data->aqi->time = date('H:i', strtotime($air->data->time->s));
                $new_data->aqi->time_full = $air->data->time->s;
            } elseif($cache_data) {

                $new_data->aqi = $cache_data->aqi;

            }

     

    문제는 없지만 같은부분이 반복되면 나중에 수정할때 빼먹을수가 있어서 최대한 반복되는 부분은 따로 빼는게 좋습니다. 위 경우라면 받는 부분만 반복하면 되니 굳이 데이터를 가져오는 부분을 if문안에 넣을필요는 없는것이죠.

  • profile profile
    네. 일부러 반복문 써서 횟수 제한의 코드가 잘못되어 무한루프가 되는 등 오류가 있을까봐 직접 같은 코드를 두번 반복해서 작성했었습니다.

    반복문을 사용해서 간단한 코드로 쓰면 더 좋겠네요. 검토 감사합니다!
  • profile profile

    아.. 그리고 정해진 시도 에서 ok 를 응답받지 못해도 응답받은 값을 그대로 데이터를 넣으려고 의도를 한 것입니다.
    지금 정리해주신 코드는 아마 ok가 아닌 응답의 경우는 아예 빠지게 되는 듯 하네요.

    ok를 받지 못하면 "미수신" 으로 처리하게 해 놓았습니다. 그래서 데이터 부분이 if 문 안에 한번 더 들어가게 되었어요.

     

     

     

     if($air) {

                $new_data->aqi = self::getAirQualityIndex((int)$air->data->aqi);
                $new_data->aqi->pm10 = $air->data->iaqi->pm10->v;
                $new_data->aqi->pm10_color = self::getAirQualityIndex((int)$new_data->aqi->pm10, 'color');
                $new_data->aqi->pm25 = $air->data->iaqi->pm25->v;
                $new_data->aqi->pm25_color = self::getAirQualityIndex((int)$new_data->aqi->pm25, 'color');
                $new_data->aqi->time = date('H:i', strtotime($air->data->time->s));
                $new_data->aqi->time_full = $air->data->time->s;
            } elseif($cache_data) {

                $new_data->aqi = $cache_data->aqi;

            }

     

     

    이렇게 해도 좋을 것 같습니다.

  • profile profile
    또하나 궁금한게
    $air = json_decode(self::file_get_contents_curl($aqicn_url, $_timeout))

    요기는 세미콜론이 끝에 없는데 차이가 뭔지 궁금하네요. 보통 세미콜론 없으면 에러가 나더라구요.
  • profile profile
    세미콜론은 명령 줄의 끝을 의미합니다.
    대부분의 명령줄에는 끝이 있어야 하죠. if문같은 예외를 제외하면요.

    에어라는 변수에 제이슨디코드한 값을 넣으라는 명령이 끝났어요. 라는 것을 세미콜론이 알려주는 거에요.
  • profile profile
    생략되어 있는데 넣어야 하는건가요 ?
  • profile profile
    본문의 코드에는 if문 안에 쓰였고 &&로 인해 명령이 끝났음을 인지하죠.
    그런데 그것이 따로 나오면 세미콜론이 필요해지는 거에요.
  • profile
    본문에서...
    elseif문 뒤쪽이 한번도 시도해보기 위해서 추가하신 것인가요???

    저라면
    $air = json_decode(self::file_get_contents_curl($aqicn_url, $_timeout));
    이걸 if문 위로 올리고

    첫번째 if문의 조건에는 $air->status=='ok' 만 남겨놓을 것 같아요.
    그리고 elseif문 안에 있는 air변수는 air2같은 걸로 변수명을 바꾸구요.

    아니면 데이터를 처리하는 부분을 function으로 만드는 것도 방법이겠어요.
    그럼 같은 걸 두번 쓰지 않아도 되니까요.
  • profile profile
    같은 걸 두번 쓰지 않게 반복문으로
    @YJSoft님께서 정리를 잘해주셔서 사용하면 될 것 같아요~~
  • profile profile
    전 자주 쓰지는 않는데
    while문도 유용하죠~^^