Webservices bilden ein Softwaresystem, das entwickelt wurde, um kompatible Interaktion zwischen Maschinen über ein Netzwerk zu unterstützen. Im Zusammenhang mit Webanwendungen beziehen sie sich in der Regel auf eine Reihe von APIs, die über das Internet zugänglich sind und auf einem entfernten Rechner ausgeführt werden können, der den angeforderten Dienst beherbergt. Ein flex-basierter Client könnte zum Beispiel serverseitig Funktionen einer PHP-basierten Webanwendung aufrufen. Webservices bauen auf SOAP als grundlegendem Kommunikations-Protokollstapel auf.
Um die Verwirklichung von Webservices in einer Webanwendung zu vereinfachen, beinhaltet Yii CWebService und CWebServiceAction. Die APIs werden zu Klassen gruppiert, den sogenannten Dienstanbietern (engl.: service provider). Für jede Klasse erzeugt Yii eine WSDL-Spezifikation, die die verfügbaren APIs und deren Aufruf von Clientseite beschreibt. Wenn eine API von einem Client aufgerufen wird, instanziiert Yii den enstprechenden Dienstanbieter und ruft die angeforderte API auf, um die Anfrage zu verarbeiten.
Hinweis: CWebService basiert auf der SOAP-Erweiterung von PHP. Stellen Sie sicher, dass diese Erweiterung aktiviert wurde, bevor Sie die Beispiele in diesem Abschnitt ausprobieren.
Wie erwähnt, ist ein Dienstanbieter eine Klasse mit entfernt aufrufbaren Methoden. Yii verwendet Doc Comments und Reflection von Klassen, um herauszufinden, welche Methoden entfernt aufrufbar sind und wie deren Parameter und Rückgabewerte aussehen.
Beginnen wir mit einem einfachen Dienst zur Abfrage von Börsenkursen. Mit
diesem Dienst kann ein Client den Kurs einer bestimmten Aktie abfragen. Wir
definieren den Dienstanbieter wie folgt. Beachten Sie, dass wir die
Anbieterklasse von CController
ableiten. Das ist nicht unbedingt nötigt. Wir
erklären in Kürze, warum wir das machen.
class StockController extends CController
{
/**
* @param string das symbol der Aktie
* @return float der Preis der Aktie
* @soap
*/
public function getPrice($symbol)
{
$prices=array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol])?$prices[$symbol]:0;
//...Aktienpreis für $symbol zurückliefern
}
}
In diesem Beispiel deklarieren wir die Methode getPrice
als API eines
Webservices, indem wir sie in ihrem Doc Comment mit dem Tag @soap
markieren.
Wir stützen uns auf die Angaben im Doc Comment, um die Datentypen der
Eingangsparameter und des Rückgabewerts zu bestimmen. Weitere APIs können auf
ähnliche weise deklariert werden.
Nachdem wir den Dienstanbieter definiert haben, müssen wir ihn für Clients
verfügbar machen. Im einzelnen heißt das, wir müssen eine Controller-Action
erstellen, die diesen Dienst öffentlich bereitstellt. Dies kann einfach dadurch erreicht
werden, indem wir eine CWebServiceAction-Action in einer Controllerklasse
deklarieren. Für unser Beispiel bringen wir diese einfach in StockController
unter:
class StockController extends CController
{
public function actions()
{
return array(
'quote'=>array(
'class'=>'CWebServiceAction',
),
);
}
/**
* @param string das symbol der Aktie
* @return float der Preis der Aktie
* @soap
*/
public function getPrice($symbol)
{
//...Aktienpreis für $symbol zurückliefern
}
}
Das ist alles, was wir tun müssen, um einen Webservice zu erstellen! Wenn wir
die Action über die URL http://hostname/pfad/zu/index.php?r=stock/quote
aufrufen, sehen wir eine Menge XML-Inhalte, die die WSDL für den von uns
definierten Webservice darstellen.
Tipp: Standardmäßig geht CWebServiceAction davon aus, dass der aktuelle Controller auch der Dienstanbieter ist. Deshalb haben wir die Methode
getPrice
in derStockController
-Klasse definiert.
Um das Beispiel abzuschließen, erstellen wir noch einen Client, der den eben
erstellten Webservice verwendet. Der Beispielclient wurde in PHP geschrieben,
könnte aber auch in anderen Sprachen wie Java
, C#
oder Flex
vorliegen.
$client=new SoapClient('http://hostname/pfad/zu/index.php?r=stock/quote');
echo $client->getPrice('GOOGLE');
Wenn Sie dieses Script im Web- oder Konsolenmodus aufurfen, sollten wir 350
als Preis für GOOGLE
erhalten.
Beim deklarieren der Klassenmethoden und -eigenschaften, die von Ferne verfügbar gemacht werden sollen, müssen wir die Datentypen der Ein- und Ausgangsparameter angeben. Die folgenden Grundtypen können verwendet werden:
xsd:string
;xsd:int
;xsd:float
;xsd:boolean
;xsd:date
;xsd:time
;xsd:dateTime
;xsd:string
;xsd:struct
;xsd:anyType
.Falls ein Typ nicht in der Liste dieser Grundtypen vorkommt, wird von einem
aus Eigenschaften zusammengesetzten Typ (engl.: composite type) ausgegangen.
Ein zusammengesetzter Typ wird als Klasse dargestellt, seine Eigenschaften
als öffentliche und in den Doc Comments mit @soap
markierte Eigenschaften
dieser Klasse.
Wir können auch den Typ Array verwenden, indem wir []
hinter einem Grundtyp
oder einem zusammengesetzten Typ anhängen. Damit würde ein Array des angegebenen
Typs angegeben.
Untenstehend finden Sie ein Beispiel für die Web-API von getPosts
, welches
ein Array von Post
-Objekten zurückliefert.
class PostController extends CController
{
/**
* @return Post[] eine Liste von Posts (Beiträgen)
* @soap
*/
public function getPosts()
{
return Post::model()->findAll();
}
}
class Post extends CActiveRecord
{
/**
* @var integer post ID
* @soap
*/
public $id;
/**
* @var string post title (Beitragstitel)
* @soap
*/
public $title;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
Um die Parameter für einen zusammengesetzten Typ vom Client beziehen zu können, muss eine Anwendung eine Abbildung von WSDL-Typen auf die entsprechenden PHP-Klassen deklarieren. Dies geschieht, indem die Eigenschaft classMap von CWebServiceAction konfiguriert wird.
class PostController extends CController
{
public function actions()
{
return array(
'service'=>array(
'class'=>'CWebServiceAction',
'classMap'=>array(
'Post'=>'Post', // oder einfach nur 'Post'
),
),
);
}
......
}
Ein Dienstanbieter kann die entfernten Methodenaufrufe abfangen, wenn er das Interface IWebServiceProvider implementiert. In IWebServiceProvider::beforeWebMethod kann der Anbieter die aktuelle Instanz von CWebService beziehen und den Namen der angeforderten Methode über CWebService::methodName ermitteln. Sie kann false zurückgeben, falls die entfernte Methode aus irgendeinem Grund nicht ausgeführt werden soll (z.B. bei unberechtigtem Zugriff).
Signup or Login in order to comment.