Веб-сервис — программная система, разработанная для обеспечения взаимодействия между несколькими компьютерами через сеть. В веб-приложении это обычно набор API, который можно использовать через интернет для выполнения действий на удалённом сервере, обслуживающем веб-сервис. К примеру, клиент, основанный на Flex, может вызывать функции, реализованные на сервере в PHP-приложении. В качестве базового уровня протокола используется SOAP.
Для того, чтобы упростить задачу создания веб-сервиса, в Yii включены CWebService и CWebServiceAction. API сгруппированы по классам, которые называются провайдерами. Для каждого класса Yii генерирует WSDL, описывающий функционал предоставляемого API и правила его использования клиентом. При обработке вызова клиента, Yii создаёт соответствующий ему экземпляр провайдера, вызывает метод API и отвечает на запрос.
Примечание: Для работы CWebService требуется расширение PHP SOAP. Убедитесь, что оно включено, прежде, чем пробовать примеры, описанные далее.
Как уже было описано, провайдер — это класс, реализующий методы, которые могут быть вызваны удалённо. Для того, чтобы определить, какие методы могут быть вызваны удалённо и какое значение возвращать, Yii использует специальные комментарии и reflection.
Попробуем реализовать простой сервис, отдающий информацию о котировках акций
определённой компании. Для этого нам потребуется реализовать провайдер, как показано
ниже. Стоит отметить, что наследуем класс провайдера StockController
от CController. Наследование не является обязательным.
class StockController extends CController
{
/**
* @param string индекс предприятия
* @return float цена
* @soap
*/
public function getPrice($symbol)
{
$prices=array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol])?$prices[$symbol]:0;
//…возвращаем цену для компании с индексом $symbol
}
}
Выше мы описали, что метод getPrice
является частью API веб-сервиса, пометив его
в комментарии тэгом @soap
. Там же мы описали типы параметров и возвращаемого
значения. Дополнительные методы API могут быть описаны точно таким же образом.
После создания провайдера необходимо сделать его доступным для клиентов.
Для этого необходимо описать действие контроллера CWebServiceAction.
В нашем примере мы используем StockController
:
class StockController extends CController
{
public function actions()
{
return array(
'quote'=>array(
'class'=>'CWebServiceAction',
),
);
}
/**
* @param string индекс предприятия
* @return float цена
* @soap
*/
public function getPrice($symbol)
{
//…возвращаем цену для компании с индексом $symbol
}
}
Это всё, что требуется для создания веб-сервиса. Теперь при обращении к URL
http://hostname/path/to/index.php?r=stock/quote
, мы получим объёмистый
XML, на самом деле являющийся WSDL описанного нами веб-сервиса.
Подсказка: По умолчанию, при использовании CWebServiceAction подразумевается, что текущий контроллер является провайдером. Именно поэтому мы определили метод
getPrice
в классеStockController
.
Для того, чтобы наш пример был полным, создадим клиент, использующий веб-сервис,
который мы только что создали. В примере клиент будет написан на PHP, но для его
реализации можно использовать и другие языки, такие как Java
, C#
, Flex
и т.д.
$client=new SoapClient('http://hostname/path/to/index.php?r=stock/quote');
echo $client->getPrice('GOOGLE');
Запустив данный скрипт через браузер или в консоли, вы должны получить 350
,
что соответствует цене акций GOOGLE
.
При описании методов и свойств класса, которые должны быть доступны через веб-сервис, нам необходимо определить типы параметров и возвращаемых значений. Для этого могут быть использованы следующие типы:
xsd:string
;xsd:int
;xsd:float
;xsd:boolean
;xsd:date
;xsd:time
;xsd:dateTime
;xsd:string
;xsd:struct
;xsd:anyType
.Если тип не является одним из приведённых выше, он воспринимается как
составной тип, состоящий из свойств. Этот тип соответствует классу, а его
свойства — public-переменным класса, отмеченных в комментариях @soap
.
Также можно использовать массивы. Для этого необходимо дописать []
в конец
примитивного или составного типа. Таким образом мы получим массив с элементами
заданного типа.
Ниже приведён пример определения метода API getPosts
, возвращающего массив
объектов класса Post
.
class PostController extends CController
{
/**
* @return Post[] список записей
* @soap
*/
public function getPosts()
{
return Post::model()->findAll();
}
}
class Post extends CActiveRecord
{
/**
* @var integer ID записи
* @soap
*/
public $id;
/**
* @var string заголовок записи
* @soap
*/
public $title;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
Для получения от клиента параметров составного типа, в приложении должны быть заданы соответствия типов WSDL классам PHP. Для этого необходимо настроить свойство classMap класса CWebServiceAction.
class PostController extends CController
{
public function actions()
{
return array(
'service'=>array(
'class'=>'CWebServiceAction',
'classMap'=>array(
'Post'=>'Post', // или просто 'Post'
),
),
);
}
…
}
Если реализован интерфейс IWebServiceProvider, провайдер может перехватывать удалённые вызовы методов. Используя IWebServiceProvider::beforeWebMethod можно получить текущий экземпляр CWebService. Через CWebService::methodName — название вызываемого метода. Если метод по каким либо причинам (например, отсутствие прав на его выполнение) не должен быть вызван, необходимо вернуть false.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.