Есть задача, подключить Booking-Manager.com API к сайту. API использует протокол SOAP
Я вроде все подключил и форму поиска написал, но грузятся результаты очень долго
Ответ от сервера, при использовании поиска, получаю в таком виде:
<root>
<resource resourceid="" companyid=”” reservationstatus="" baseprice=""
discountvalue="" price="" baseid=”” datefrom=”” dateto=””></resource>
…
</root>
Т.е., по факту, список Ресурсов. Но данных для вывода мало и потому мне приходится по каждому элементу списка проходиться отдельно (через While) и получать информацию по каждому ресурсу из списка
Приведу несколько кусков кода
Собственно, обработка полученного XML от сервера после поиска для сбора массива и дальнейшего вызова функции получения информации по каждому 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;
}
А здесь, собственно и сама обработка ресурса
//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;
}
}
Так вот. Моим способом, получается, что каждый полученный ресурс от сервера, обрабатывается отдельно через XML Reader. Т.е. в начале цикл для сбора данных ответа в массив. Потом получившийся массив используется для вызова функции обработки Ресурса и отправки туда ID для дальнейшей обработки Ресурса. В самом ресурсе цикл по сбору данных ресурса в том виде в котором мне надо.
В итоге, грубо говоря на 50 ресурсов, получается 50 циклов по сбору данных по ресурсу. К тому же 50 запросов к серверу SOAP, дабы получить необходимый XML
Вопрос: это нормально и можно ли как-то исправить если нет? Если да, то подскажите как улучшить код, пожалуйста. В текущем виде, данные получает долго (и многое влияет то, сколько ID получил от сервера). Уже несколько дней с этим вожусь и в голову ничего стоящего не приходит