【问题标题】:Laravel call method and pass value when got an exceptionLaravel 异常时调用方法和传值
【发布时间】:2020-01-31 08:12:21
【问题描述】:

我得到了获取访问令牌的方法,在这里

   public $token; //I declare global var to read in every func

    public function getToken(){
        $key = 'xxxxxxxxxxxxxx';
        $secret = 'xxxxxxxxxxxxxxxxxx';
        $data = array(
            'key' => 'xxxxxxxxxxxxxxxxxx',
            'secret' => 'xxxxxxxxxxxxxxx'
        );
        $payload = json_encode($data);
        $ch = curl_init('https://cgi.singmap.com/token?key='.$key.'&secret='.$secret.'');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLINFO_HEADER_OUT, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/x-www-form-urlencoded',
            'Accept: application/json',
            'Content-Length: ' . strlen($payload))
        );

        // Submit the POST request
        $response = json_decode(curl_exec($ch), true);
        $trimmed = $response['datas'];
        $token = $trimmed['access_token'];
        curl_close($ch);
        $this->token = $token;
    }

令牌只能使用 5 分钟。但是在我这样使用令牌的其他方法中

 public function propertyUnitDetails(){

        $unitId = \DB::table('property_unit_list')
        ->select('projectId','unitId')
        ->get();

        foreach($unitId as $res){

        $this->getToken();
        $final_token = $this->token;

        // dd($final_token);

        $request_time = Carbon::now()->format('YmdHis');
        $sign = md5($final_token.$request_time);
        $pageNo = 1;
        $pageSize = 200;
        $url = 'https://cgi.singmap.com/unit/queryUnitDetail?request_time='.$request_time.
        '&token='.$final_token.'&sign='.$sign.'&projectId='.$res->projectId.'&unitId='.$res->unitId.'';

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $response = json_decode(curl_exec($ch), true);
        $trimmed = $response['datas'];

        if(empty($trimmed)){
            $this->getToken();
            $final_token = $this->token;
        }

        foreach ($trimmed as $data){
            $inserts[] = [
                'projectId' => $res->projectId,
                'stack' => $data['stack'],
                'floorPlanId' => $data['floorPlanId'],
                'soldBy' => $data['soldBy'],
                'transactionPrice' => $data['transactionPrice'],
                'type' => $data['type'],
                'unitId' => $data['unitId'],
                'floorPlanName' => $data['floorPlanName'],
                'price1' => $data['price1'],
                'price2' => $data['price2'],
                'price3' => $data['price3'],
                'price4' => $data['price4'],
                'custom1' => $data['custom1'],
                'custom2' => $data['custom2'],
                'custom3' => $data['custom3'],
                'custom4' => $data['custom4'],
                'direction' => $data['direction'],
                'area' => $data['area'],
                'buildName' => $data['buildName'],
                'unitName' => $data['unitName'],
                'buildId' => $data['buildId'],
                'bathrooms' => $data['bathrooms'],
                'transactionDate' => $data['transactionDate'],
                'bedrooms' => $data['bedrooms'],
                'purchaseStatus' => $data['purchaseStatus'],

                ];

            }
        }
        $chuncked = array_chunk($inserts, 10);
        foreach($chuncked as $inserts){
          \DB::table('property_project_details')->insert($inserts);
       }
      dd('record inserted'); 
    }

当函数没有完全执行或者数据没有完全插入时,可能是因为它有大量的数据。它会抛出 datas 未找到索引或 curl 响应中的错误。这是因为我只能根据手动获取或手动声明的令牌获取datas。我想要的是如果令牌过期,它将运行函数getToken()并将令牌传递给正在运行的函数以避免中断它。

编辑: 我加了

 $this->getToken();
 $final_token = $this->token;

在我的 foreach 语句中,因为@user001232 说在我得到的每个unitId 结果查询中,都会生成一个新令牌。但是我仍然每 5 分钟出现一次错误,这是因为即使我在其中添加了该功能,我也无法获得新的令牌。

【问题讨论】:

    标签: php laravel function curl conditional-statements


    【解决方案1】:

    给你,这会起作用的:

    <?php 
    
    class NameOfYourClass {
        public $token;
    
        public function refreshToken()
        {
            $key = 'xxxxxxxxxxxxxx';
            $secret = 'xxxxxxxxxxxxxxxxxx';
            $data = array(
                'key' => 'xxxxxxxxxxxxxxxxxx',
                'secret' => 'xxxxxxxxxxxxxxx'
            );
            $payload = json_encode($data);
            $ch = curl_init('https://cgi.singmap.com/token?key='.$key.'&secret='.$secret.'');
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLINFO_HEADER_OUT, true);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
                curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                    'Content-Type: application/x-www-form-urlencoded',
                    'Accept: application/json',
                    'Content-Length: ' . strlen($payload))
            );
    
            $response = json_decode(curl_exec($ch), true);
            $trimmed = $response['datas'];
            $this->token = $trimmed['access_token'];
            curl_close($ch);
        }
    
        private function getUnitDetails($res, $attempts = 1)
        {
            // We only allow 5 attempts to avoid getting into infinite loops
            if ($attempts > 5) {
                throw new \Exception('Signmap API Issue');
            }
    
            $request_time = Carbon::now()->format('YmdHis');
            $sign = md5($this->token.$request_time);
            $pageNo = 1;
            $pageSize = 200;
            $url = 'https://cgi.singmap.com/unit/queryUnitDetail?request_time='.$request_time.
            '&token='.$this->token.'&sign='.$sign.'&projectId='.$res->projectId.'&unitId='.$res->unitId.'';
    
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $response = json_decode(curl_exec($ch), true);
            $trimmed = $response['datas'] ?? null;
    
            // If the response datas is empty, we're assuming it's because of a token error, so we retry
            if(empty($trimmed)){
                $attempts++;
                $this->refreshToken();
                return $this->getUnitDetails($res, $attempts);
            }
    
            return $trimmed;
        }
    
        public function propertyUnitDetails()
        {
            // Grab all of the units
            $unitItds = \DB::table('property_unit_list')->select('projectId','unitId')->get();
    
            foreach($unitId as $res) {
                $trimmed = $this->getUnitDetails($res);
    
                foreach ($trimmed as $data){
                    $inserts[] = [
                        'projectId' => $res->projectId,
                        'stack' => $data['stack'],
                        'floorPlanId' => $data['floorPlanId'],
                        'soldBy' => $data['soldBy'],
                        'transactionPrice' => $data['transactionPrice'],
                        'type' => $data['type'],
                        'unitId' => $data['unitId'],
                        'floorPlanName' => $data['floorPlanName'],
                        'price1' => $data['price1'],
                        'price2' => $data['price2'],
                        'price3' => $data['price3'],
                        'price4' => $data['price4'],
                        'custom1' => $data['custom1'],
                        'custom2' => $data['custom2'],
                        'custom3' => $data['custom3'],
                        'custom4' => $data['custom4'],
                        'direction' => $data['direction'],
                        'area' => $data['area'],
                        'buildName' => $data['buildName'],
                        'unitName' => $data['unitName'],
                        'buildId' => $data['buildId'],
                        'bathrooms' => $data['bathrooms'],
                        'transactionDate' => $data['transactionDate'],
                        'bedrooms' => $data['bedrooms'],
                        'purchaseStatus' => $data['purchaseStatus'],
                    ];
                }
            }
            $chuncked = array_chunk($inserts, 10);
            foreach($chuncked as $inserts){
                \DB::table('property_project_details')->insert($inserts);
            }
            dd('record inserted'); 
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果每次在循环中有 projectId 时调用方法 getToken() 会怎样。是这样的

      foreach($project_id as $res){
              $this->getToken();
              $final_token = $this->token;
      
              $request_time = Carbon::now()->format('YmdHis');
              $sign = md5($final_token.$request_time);
      
      //and so on ....
      
      

      这样。它将在每个projectId 中获得一个新令牌。唯一的缺点是执行速度很慢。

      如果仍然出现错误,请像这样替换您的代码。如果为空则添加条件

      public function propertyBuildings(){
      
              $project_id = \DB::table('project_list')
                              ->select('projectId')
                              ->get();
      
              foreach($project_id as $res){
      
                  $this->getToken();
                  $final_token = $this->token;
      
                  $request_time = Carbon::now()->format('YmdHis');
                  $sign = md5($final_token.$request_time);
                  $url = 'https://cgi.singmap.com/project/queryBuilding?request_time='.$request_time.
                  '&token='.$token.'&sign='.$sign.'&projectId='.$res->projectId.'';
                  $ch = curl_init();
                  curl_setopt($ch, CURLOPT_URL, $url);
                  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                  $response = json_decode(curl_exec($ch), true);
                  $trimmed = $response['datas'];
      
      
                 if(empty($trimmed)){
                     $this->getToken();
                     $final_token = $this->token;
                 }
      
                  // return $trimmed;
                      foreach($trimmed as $data){
                          $inserts[] = [
                          'projectId' => $res->projectId,
                          'buildId' => $data['buildId'],
                          'buildName' => $data['buildName'],
                          ];
                  }
      
               }
               \DB::table('property_building')->insert($inserts);
               dd('Data Inserted');
      
          }
      

      【讨论】:

      • 不适合我。每次令牌过期时仍然出错。
      • 令牌过期时服务器会出现什么错误?非常稀疏的信息 tbh
      • 它说undefined index [datas] 这是因为$trimmed 没有对象datas 因为令牌已过期并且无法获取新数据@mrhn
      • 这不是您正在调用的服务器上的错误,而是您的代码不起作用。为了改进这个答案,我们需要知道它是如何起作用的。如果令牌过期,服务器通常会以 401 响应并且可以返回空响应。但如果你不知道它的作用,那就很难处理了。
      • 是的,但我已经在每个循环中调用了该方法以获取一个新令牌以防止过期,但它仍然导致我undefined index [datas]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 2023-03-14
      • 2021-07-25
      • 2019-10-13
      相关资源
      最近更新 更多