2010-02-12 3 views
0

Я пытаюсь научить себя SOAP, просто немного расширить свой набор навыков, но я ударил стену, и мне было интересно, может помочь?PHP/SOAP - пытается учиться, но имеет проблемы с реализацией

Я создал свой сервер таким образом:

http://www.domain1.com/server.php

<?php 
// Pull in the NuSOAP code 
require_once('soap/nusoap.php'); 
// Create the server instance 
$server = new soap_server(); 
// Initialize WSDL support 
$server->configureWSDL('hellowsdl', 'urn:hellowsdl'); 
// Register the method to expose 
$server->register('hello', // method name 
array('name' => 'xsd:string'), // input parameters 
array('return' => 'xsd:string'), // output parameters 
'urn:hellowsdl',  // namespace 
'urn:hellowsdl#hello', // soapaction 
'rpc',  // style 
'encoded',  // use 
'Says hello to the caller' // documentation 
); 
// Define the method as a PHP function 
function hello($name) { 
     return 'Hello, ' . $name; 
} 
// Use the request to (try to) invoke the service 
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ''; 
$server->service($HTTP_RAW_POST_DATA); 
?> 

А теперь я пытался настроить клиента на отдельном сервере:

http://www.domain2.com/client.php

<?php 
// Pull in the NuSOAP code 
require_once('soap/nusoap.php'); 
// Create the client instance 
$client = new soapclient('http://domain.com/server.php?wsdl', true); 
// Check for an error 
$err = $client->getError(); 
if ($err) { 
// Display the error 
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>'; 
// At this point, you know the call that follows will fail 
} 
// Call the SOAP method 
$result = $client->call('hello', array('name' => 'Scott')); 
// Check for a fault 
if ($client->fault) { 
echo '<h2>Fault</h2><pre>'; 
print_r($result); 
echo '</pre>'; 
} else { 
// Check for errors 
$err = $client->getError(); 
if ($err) { 
    // Display the error 
    echo '<h2>Error</h2><pre>' . $err . '</pre>'; 
} else { 
    // Display the result 
    echo '<h2>Result</h2><pre>'; 
    print_r($result); 
echo '</pre>'; 
} 
} 
// Display the request and response 
echo '<h2>Request</h2>'; 
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>'; 
echo '<h2>Response</h2>'; 
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>'; 
// Display the debug messages 
echo '<h2>Debug</h2>'; 
echo '<pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>'; 
?> 

Но я не могу заставить рабочую вещь работать. На сервере отображается только тонкий - wdsl вывод лота. Но клиент не может/не сможет подключиться и завершить транзакцию. Я получаю сообщение:

Warning: SoapClient::SoapClient() expects parameter 2 to be array, boolean given in /home/public_html/slidebank_soap_client.php on line 5 

Fatal error: Uncaught SoapFault exception: [Client] SoapClient::SoapClient() [<a href='soapclient.soapclient'>soapclient.soapclient</a>]: Invalid parameters in /home/soap/slidebank_soap_client.php:5 Stack trace: #0 /home/soap/slidebank_soap_client.php(5): SoapClient->SoapClient('http://testing....', true) #1 {main} thrown in /home/public_html/soap/slidebank_soap_client.php on line 5 

И это где я тупик ...

Любые идеи?

H

ответ

1

Я использовал, чтобы быть поклонником использования NuSOAP с PHP3/4 (то есть назад, когда PHP не имеет встроенный клиент SOAP), но с SOAP Client PHP5, я нахожу, что нет какого-либо нужно для nusoap в эти дни.

Преимущество PHP5, построенного в SOAP-клиенте, заключается в том, что он намного чище и проще реализовать, и поэтому упоминайте его как полезный для вас (я знаю, что некоторые предпочитают использовать nusoap вместо этого, но многие люди, по-видимому, просто aren ' t знает, что он есть в PHP5, поскольку многие руководства «HOWTO» устарели и не упоминают об этом).

Пример использования:

ini_set("soap.wsdl_cache_enabled", "1"); // Set to zero to avoid caching WSDL 
$soapClient = new SoapClient('http://www.example.com/webservices/HelloWorldService/?wsdl");  
$result = $soapClient->HelloWorldMethod(array('string' => "hello!"));  
print_r($result); 

На заметку о типах услуг:

Когда дело доходит до службы SOAP, в идеале вы хотите реализовать Document/Literal службы, а не RPC/закодирован сервис, поскольку RPC/Encoded - сложный формат для работы, и по этой причине WS-I устарел в пользу Document/Literal (что намного проще в работе и более логично в дизайне).

Для начала вам может понадобиться попробовать реализовать клиент против существующей службы, если сможете - таким образом, вы знаете, что он работает как минимум, что может сэкономить вам несколько головных болей.

К сожалению, пока он отлично разбирается в них - PHP не имеет особо большой поддержки для Документ/Буквенные услуги. Для этого IIRC существует, по крайней мере, одна сторонняя nusoap-подобная библиотека, но она не совсем сократила ее для меня.

(Если какой-либо из этого является устаревшим, поправки приветствуются.)

+0

Благодаря Иэн, это было очень полезно! В конце концов, я использовал свой код обслуживания и ваш код клиента, и они были без проблем! Теперь все работает, поэтому большое спасибо :) – MrFidge

+0

Рад, что вы сочли это полезным! Кажется, что nusoap (по-прежнему) лучший вариант для создания SOAP-сервисов с PHP на данный момент, так что похоже, что вы пошли по лучшему маршруту. Надеюсь, PHP в какой-то момент получит встроенную реализацию SOAP-сервера, столь же изящную, как и клиентскую! –

+0

Да, похоже, это упущение tbh! Зачем делать полузакрытую работу и обеспечивать ее без нее? – MrFidge

0

Только в случае, если некоторые Googlers найти это ...

Я редактировал PHP.ini, как предложил ccheneson, и этот код работал отлично, даже на том же dev-сервере.

Клиент - основанный на странице Drupal в режиме PHP:

<?php 
# URL for the service WSDL 
ini_set("soap.wsdl_cache_enabled", "0"); // Set to zero to avoid caching WSDL 
try { 
    // Get a service proxy from the WSDL 
    $proxy = new SoapClient('http://testing.domain.com/soap.php?wsdl'); 
    global $user; 
    if (is_array($user->roles) && in_array('group1', array_values($user->roles))) { 
     // User is logged in and is in the usergroup, perform login 
     $id = $user->uid; 
     $key = 1234; 
     $hashgenerator = $key . "xyz" . $id . "randomstringhere"; 
     $hash = sha1($hashgenerator); 
     // Call a method on the service via the proxy 
     $result = $proxy->handshake($id, $key, $hash); 
     if ($hash==$result) { 
      //Send all user details 
      profile_load_profile($user); 
      $email = $user->mail; 
      $fname = $user->{profile_firstname}; 
      $lname = $user->{profile_lastname}; 
      $phone = $user->{profile_phone}; 
      $fax = $user->{profile_fax}; 
      $dept = "Speakers"; 
      $role = "Speakers"; 
      //Send request 
      $authresult = $proxy->authlogin($id, $email, $fname, $lname, $phone, $fax, $authgroup); 
      if ($authresult=='ok') { 
       //Logged in, show them the page 
       $_SESSION['loggedin'] = 1; 
      } else { 
       echo "Error 3";   
      } 
     } else { 
      echo "Error 2"; 
     } 
    } else { 
     echo "Error 1"; 
    } 
} catch(SoapFault $ex) { 
    echo 'Error: '; 
    if ($ex->getMessage() != '') { 
     echo $ex->getMessage(); 
    } else { 
     echo $ex . "\n"; 
    } 
} 
?> 

Услуги:

<?php 
//----------------------------------// 
// This file is a dummy service It obviously does nothing with the data, but i needed it to build my client scripts and so it might give you a hand returning the correct strings. 
//----------------------------------// 

// Pull in the NuSOAP code 
require_once('nusoap/nusoap.php'); 
// Create the server instance 
$server = new soap_server(); 
// Initialize WSDL support 
$server->configureWSDL('WDSL', 'urn:WDSL'); 
// Register the methods to expose 
$server->register('handshake',    // method name 
    array('id' => 'xsd:string', 
      'key' => 'xsd:string', 
      'hash' => 'xsd:string'),   
    array('return' => 'xsd:string'),  // output parameters 
    'urn:WDSL',        // namespace 
    'urn:WDSL#_handshake',     // soapaction 
    'rpc',         // style 
    'encoded',        // use 
    'Initial handshake'      // documentation 
); 
$server->register('authlogin',    // method name 
    array('id' => 'xsd:string',    // User ID 
      'email' => 'xsd:string',   // User email address 
      'fname' => 'xsd:string',   // User first name 
      'lname' => 'xsd:string',   // User last name 
      'phone' => 'xsd:string',   // User phone 
      'fax' => 'xsd:string',   // User fax 
      'dept' => 'xsd:string',   // SB department 
      'role' => 'xsd:string'),   // SB role 
    array('return' => 'xsd:string'),  // output parameters 
    'urn:WDSL',        // namespace 
    'urn:WDSL#authlogin',     // soapaction 
    'rpc',         // style 
    'encoded',        // use 
    'Authentication of a user'    // documentation 
); 
// Define the method as a PHP function 
function slidebank_handshake($uid, $key, $hash) { 
    //returns the same hash string for confirmation. No need to pass UID again. 
    $hashgenerator = $key . "xyz" . $uid . "randomstringhere"; 
    $hash = sha1($hashgenerator); 
    return $hash; 
} 
// Define the method as a PHP function 
function slidebank_authlogin($id, $email, $fname, $lname, $phone, $fax, $dept, $role) { 
    //logic to log user in and capture details etc 
    return 'ok'; //options = ok or fail 
} 
// Use the request to (try to) invoke the service 
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : ''; 
$server->service($HTTP_RAW_POST_DATA); 
?>