P
P
PGSky2019-08-25 05:46:59
PHP
PGSky, 2019-08-25 05:46:59

How to improve response handling from API via SOAP protocol?

There is a task to connect the Booking-Manager.com API to the site. The API uses the SOAP protocol.
I seem to have connected everything and wrote the search form, but the results are loading for a very long time
. The response from the server, when using the search, I receive in this form:

<root>
<resource resourceid="" companyid=”” reservationstatus="" baseprice="" 
discountvalue="" price="" baseid=”” datefrom=”” dateto=””></resource></root>

That is, in fact, a list of Resources.
But there is not enough data to output, and therefore I have to go through each element of the list separately (through While) and get information on each resource from the list
. for each ID:
function getSearchResults($dataConnect,$_xmlValues,$fieldsMain) {
  $connectOptions = $dataConnect;
  $struct = array($connectOptions['id'], $connectOptions['email'], $connectOptions['password'], $_xmlValues);
  $result = soapClientResult($struct,'getSearchResultsFilter');
  
  $resources_final = array();
  
  if (!is_soap_fault($result)) {
    try {
      if(isset($result->out)) {
        
        $resources = array();
        $xml = $result->out;
        
        $reader = new XMLReader();
        $reader->xml($xml);
        
        $dom = new DOMDocument();
        
        $i = 0;
        while($reader->read()) {
          if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == "resource") {
            $node = simplexml_import_dom($dom->importNode($reader->expand(), true));
            $resources[$i]['resourceid'] = $reader->getAttribute('resourceid');
            $resources[$i]['baseprice'] = $reader->getAttribute('baseprice');
            $resources[$i]['reservationstatus'] = $reader->getAttribute('reservationstatus');
            $resources[$i]['baseid'] = $reader->getAttribute('baseid');
            $i++;
          }
        }
        $reader->close();
        
        $i = 0;
        foreach ($resources as $resource) {
          $resources_final[$i] = get_xml_soap_single($connectOptions,$resource['resourceid'],false,$fieldsMain);
          if($i == 50) {
            break;
          }
          $i++;
        }
      }
    }
    catch (Exception $e) {
      print_r($e->getMessage());
      echo '<br>';
      print_r($soapClient->__getLastRequest());
      echo '<br>';
      print_r($soapClient->__getLastResponse());
    }
  } else {
    return 'error';
  }
  return $resources;
}

And here, in fact, the resource processing itself
//SOAP CLIENT
function get_soapClient() {
  $wsdl = 'https://www.booking-manager.com/cbm_web_service2/services/CBM?wsdl';
  $arrContextOptions=array("ssl"=>array( "verify_peer"=>false, "verify_peer_name"=>false,'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT)); 
  $options = array(
      'exceptions'=>false,
      'trace'=>1,
      'stream_context' => stream_context_create($arrContextOptions),
      'keep_alive' => true,
  );
  $soapClient = new SoapClient($wsdl, $options);
  return $soapClient;
}

//Cбор аттрибутов отдельных элементов XML по Name 
function soapXMLReaderGetResult($dom,$reader,$resource,$result_final,$result_source,$array_name,$final,$count,$current_count) {
  if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == $resource) {
    $node = simplexml_import_dom($dom->importNode($reader->expand(), true));
    if($reader->hasAttributes)  {
      while($reader->moveToNextAttribute()) { 
        if($count == true) {
          if($final == true) {
            $result_final[$array_name][$current_count][$reader->name] = $reader->value;
          } else {
            $result_source[$array_name][$current_count][$reader->name] = $reader->value;
          }
        } else {
          if($final == true) {
            $result_final[$array_name][$reader->name] = $reader->value;
          } else {
            $result_source[$array_name][$reader->name] = $reader->value;
          }
        }
      }
    }
  }
  if($final == true) {
    return $result_final[$array_name];
  } else {
    return $result_source[$array_name];
  }
}

// Инициализация подключения к SOAP

function soapClientResult($struct_result, $struct_function) {

  $soapClient = get_soapClient();
  
  $struct = new MMKStruct($struct_result);
  $result = $soapClient->__soapCall($struct_function,array($struct));
  
  return $result;
}

// Собственно сама обработка ресурса

function get_xml_soap_single($dataConnect,$request_id,$single = bool,$fieldsSearch) {
  
    $pathImages = $_SERVER['DOCUMENT_ROOT'] . '/tmp/images';
    
    if(!file_exists($pathImages)) {
      mkdir($pathImages,0755,true);
    } else {
      foreach (glob($pathImages.'/*') as $file) {
        unlink($file);
      }
    }
  
    $currentDate = date('Y-m-d');
    
    $connectOptions = $dataConnect;
    
    $struct = array($connectOptions['id'], $connectOptions['email'], $connectOptions['password'], $request_id);
    $result = soapClientResult($struct,'getResourceDetails');
    
    if (!is_soap_fault($result)) {
      
      try {
        
        $result_source = array();
        $result_source['prices_source'] = array();
        $result_source['images_source'] = array();
        $result_source['locations_source'] = array();
        
        $result_final = array();
        $result_final['attributes'] = array();
        $result_final['prices_current'] = array();
        $result_final['images_final'] = array();
        $result_final['locations_current'] = array();
        $result_final['locations_current_base'] = array();
        
        if(isset($result->out)) {
      
          $xml = $result->out;
          $reader = new XMLReader();
          $reader->xml($xml);
          
          $dom = new DOMDocument();
          
          $resource_count = 0;
          $prices_count = $images_count = $equipment_count = $extras_count = $discounts_count = $products_count = $locations_count = 0;
          
          while($reader->read()) {
            
            if ($reader->nodeType == XMLReader::ELEMENT) {
              if($reader->name == 'resource') {
                $resource_count = 0;
              }
              if ($reader->name == 'price') {
                ++$prices_count;
              }
              if ($reader->name == 'image') {
                ++$images_count;
              }
              if ($reader->name == 'location') {
                ++$locations_count;
              }
            }
            
            $result_final['attributes'] = soapXMLReaderGetResult($dom,$reader,'resource',$result_final,$result_source,'attributes',true,false,$resource_count);
            
            $result_source['prices_source'] = soapXMLReaderGetResult($dom,$reader,'price',$result_final,$result_source,'prices_source',false,true,$prices_count);
            
            $result_source['images_source'] = soapXMLReaderGetResult($dom,$reader,'image',$result_final,$result_source,'images_source',false,true,$images_count);
            
            $result_source['locations_source'] = soapXMLReaderGetResult($dom,$reader,'location',$result_final,$result_source,'locations_source',false,true,$locations_count);
            
            
          }
          $reader->close();
          
          usort($result_source['images_source'], "images_sort_main");
          if(file_exists($_SERVER['DOCUMENT_ROOT'] . '/tmp/images')) {
            $i = 0;
            foreach ($result_source['images_source'] as $image) {
              $fileBasename = basename($image['href']);
              $result_final['images_final'][$i]['href'] = '/tmp/images/' . $fileBasename;
              $result_final['images_final'][$i]['comment'] = $image['comment'];
              $i++;
            }
          }
          
          usort($result_source['prices_source'], "cmp_date");
          
          $alignment_validate = false;
          foreach ($result_source['prices_source'] as $price) {
            if(strtotime($price['datefrom']) < strtotime($currentDate) && strtotime($price['dateto']) > strtotime($currentDate)) {
              foreach($price as $key => $val) {
                $result_final['prices_current'][$key] = $val;
              }
              $alignment_validate = true;
              break;
            }
          }
          if(!$alignment_validate) {
            foreach ($result_source['prices_source'][0] as $key => $val) {
              $result_final['prices_current'][$key] = $val;
            }
          }
          
          if($result_source['locations_source'] != 0) {
            usort($result_source['locations_source'], "cmp_date");
            
            $alignment_validate = false;
            foreach ($result_source['locations_source'] as $price) {
              if(strtotime($price['datefrom']) < strtotime($currentDate) && strtotime($price['dateto']) > strtotime($currentDate)) {
                foreach($price as $key => $val) {
                  $result_final['locations_current'][$key] = $val;
                }
                $alignment_validate = true;
                break;
              }
            }
            if(!$alignment_validate) {
              foreach ($result_source['locations_source'][0] as $key => $val) {
                $result_final['locations_current'][$key] = $val;
              }
            }
            
            if($result_final['locations_current'] != 0) {
              $baseCurrent = soapClientBasesCurrent($result_final['locations_current']['baseid'],$fieldsSearch);
              if($baseCurrent != false) {
                $result_final['locations_current_base'] = $baseCurrent;
              }
            }
          }
          
          if($result_final != 0) {
            return $result_final;
          }
          
        }
      }
      
      catch (Exception $e) {
        print_r($e->getMessage());
        echo '<br>';
        print_r($soapClient->__getLastRequest());
        echo '<br>';
        print_r($soapClient->__getLastResponse());
      }
      
    } else {
      return false;
    }
}

So. In my way, it turns out that each resource received from the server is processed separately through the XML Reader. Those. at the beginning of the loop to collect the response data into an array. Then the resulting array is used to call the Resource processing function and send the ID there for further processing of the Resource. In the resource itself, there is a cycle for collecting resource data in the form in which I need it.
As a result, roughly speaking for 50 resources, it turns out 50 cycles of collecting data on the resource. In addition, 50 requests to the SOAP server in order to get the necessary XML
Question: is this normal and can I somehow fix it if not? If yes, then tell me how to improve the code, please. In its current form, the data is received for a long time (and much depends on how many IDs received from the server). I've been fiddling with this for several days and nothing worthwhile comes to mind

Answer the question

In order to leave comments, you need to log in

1 answer(s)
L
lubezniy, 2019-08-25
@lubezniy

If there is no other possibility in the API for extended data retrieval, you need to either reduce the amount of output to a list (if the task allows), or generally output data retrieval to a separate process (daemon) that is not associated with issuing responses to the user, with the organization of a queue for processing and issuing results after a time longer than the web server's timeout settings.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question