Uwaga, blog przeniesiony

Posty na tym blogu już nie będą się pojawiać. Zapraszam gorąco pod nowy adres: blog.grzegorzpawlik.com



Subskrybuj ten blog...

wtorek, 19 lutego 2008

CakePHP + serwer SOAP (pierwsze kroki)

Mimo tego, że cake chwali się, że jest WebServices ready tyczy się to jedynie tak zwanego routingu (np. gdy użyjesz users/index - będzie "normalnie" czyli wyrenderuje widok /vews/users/index.thtml, a gdy "xml/user/index" - /views/users/xml/index.thtml) ale nie jest to prawdziwe WebSerwice. Nie wiem ile jest sposobów na zmianę CakePHP w prawdziwy serwer SOAP, ja znam jeden i Wam go pokażę.

1. Potrzebna nam biblioteka SOAP (jako prawdziwy programiści pozwalamy, żeby najtrudniejsze rzeczy pisali za nas inni). Ja wybrałem NuSOAP. Wrzuć pliki do /app/vendors/nusoap/*.
2. Stwórz kontroler do obsługi Soap. W moim przypadku soap_controller.php
/**
* Soap Serwer
* @package package
*/
vendor('nusoap/nusoap');
class
SoapController extends AppController {
var
$name = 'Soap';
var
$server;
var
$namespace;
var
$layout = 'blank';
var
$components = array('othAuth','Conf');
var
$othAuthRestrictions = null;

/**
* Inicjalizacja ustawień serwera
*
*/
function _init() {
$this->namespace = $this->Session->host;
$this->server = new soap_server();
$this->server->debug_flag = false;
$this->server->configureWSDL('MyWsdl', $this->namespace, 'http://'.$_SERVER['HTTP_HOST'] . $this->webroot . $this->params['controller'] ); // należy nadpisać endpoint, gdyż domyślnie ustawi się na /twoja_aplikacja/app/index.php
$this->server->wsdl->schemaTargetNamespace = $this->namespace;
$this->_defineTypes();
$this->_registerMethods();
}

/**
* Serwer endpoint handler
*
*/
function index(){
Configure::write('debug', 0);

$this->_init();

$HTTP_RAW_POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$this->server->service($HTTP_RAW_POST_DATA);
exit();
}


/**
* define types required by this server
* przyda się później
*/
function _defineTypes() {

}

function
_registerMethods() {

$this->server->register(
'SoapController.hello', // method name
array('name' => 'xsd:string'), // input parameters
array('return' => 'xsd:string'),
$this->namespace,
$this->namespace . '#hello',
'document', // style
'encoded' // use
);

}

function
hello($name){
return array(
'return' => 'hello, '.$name);
}

}

?>

3. Do tego stwórz model, który nic nie robi :)
class Soap extends AppModel {
var $name = 'Soap';
var $useTable = false;
}
?>


Teraz objaśnienia:
SoapController::index() - to twój endpoint serwera SOAP. SoapController::_registerMethods() zajmuje się rejestrowaniem metod dostępnych przez serwer. W tym wypadku tylko jednej: SoapController::hello (notacja metod soap to Klasa.metoda).
Metoda hello przyjmuje string jako parametr i zrwaca 'Hello, '+ to co zostało jej przekazane.
Przykładowy klient (poza cake.php):
require('./nusoap/nusoap.php');

function
pr($var) {
echo
"<pre>";
var_dump($var);
echo
"&lt/pre>";
}

/* create client */
$endpoint = "http://localhost/meta/application_in_cakePHP/soap/index";

$mynamespace = "";
$client = new soapclient($endpoint);

$err = $client->getError();
if (
$err) {
// Display the error
echo '

Constructor error: '

. $err . '

'
;
// At this point, you know the call that follows will fail
}

$response = $client->call('SoapController.hello', array('name' =>"Greg"));
echo
"Call SoapController.hello";
if (
$client->fault) {
echo
'

Fault: '

;
print_r($response);
echo
'

'
;
} else {
// Check for errors
$err = $client->getError();
if (
$err) {
// Display the error
echo '

Error: '

. $err . '

'
;
} else {
echo(
'response:');
pr($response);
}
}

?>


I ładny response:
string(11) "hello, Greg"
Dodatkowo, gdy w przeglądarce wpiszesz ścieżkę do kontrolera Soap zobaczysz ładną dokumentację Twojego serwera. A dodając do ścieżki ?wsdl - dokument wsdl.

żródła:
http://www.scottnichol.com/nusoapprog.htm
http://dietrich.ganx4.com/nusoap/faq.php


2 komentarze:

Anonimowy pisze...

Cześć.
Dzięki za informacje. :)Już myślałem, że zjem klawiaturę, bo troszczkę mi nie szło ostatnio...
A tak może spróbuję NuSOAP.
Męczę się właśnie kilka dni nad Webservice w CakePHP i nie wiem jak to się stało, że twojego wpisu nie zauważyłem. Korzystałem z artykułów bakery: http://bakery.cakephp.org/articles/view/implementing-soap-on-cakephp
http://bakery.cakephp.org/articles/view/a-component-to-help-creating-soap-services
Nawet to działa, ale niestety ten wykorzystany WShelper nie za bardzo jest przygotowany do pracy z CakePHP. Efektem czego nie mogę nawet wysłać tablicy ponieważ nie potrafi stworzyć odpowiedniego WSDLa. O Obiektach stdClass czy swoich mogę również zapomnieć.
Mam pytanie - czy masz jakieś doświadczenia z complex type?
Chodzi mi o np. wysyłanie i odbieranie konkretnych obiektów do/z metod webservice. Może spotkałeś gdzieś jakieś informacje na ten temat?
pozdr.
wilkuu($)interia.pl

Acha jeszcze jedno: Co to za komponenty?

Grześ pisze...

A co masz na myśli mówiąc o Complex Type? Obiekty najlepiej **chyba** byłoby serializować (pod warunkiem, że nie zawierają referencji), albo utworzyć typ podobny (z takimi samymi atrybutami) do obiektu i je do tego typu skopiować. Nie jestem pewien, czy natknąłem się na ten problem.

Uwaga! blog przeniesiony

Posty na tym blogu już nie będą się pojawiać. Zapraszam gorąco pod nowy adres: blog.grzegorzpawlik.com
Komentowanie artykułów możliwe jest pod nowym adresem.