XML-RPC: работа с помощью Zend Framework

В 1998 году Microsoft совместно с Дейвом Винером разработала протокол XML-RPC, который является реализацией RPC (Remote Procedure Call — Вызов удаленных процедур) на основе XML. Позже Microsoft разработала собственный протокол SOAP, основанный на XML-RPC, и начала продвигать свой стандарт, полностью отказавшись от предыдущего. На мой взгляд это было большой ошибкой. SOAP намного сложнее своего предка, что увеличивает не только время разработки приложения, но еще и размер передаваемых данных, что сказывается на скорости работы приложения. Но сегодня мы не будем обсуждать эту ошибку, а займемся подробностями использования XML-RPC в Zend Framework.


Фреймворк

Последнюю версию Zend Framework можно скачать на страничке Downloads официального сайта. На момент написания статьи, последней была версия 1.11.9. Именно на ней и будем проводить все тесты.

Далее предполагается, что читатель знаком с шаблоном проектирования MVC и его реализацией в Zend Framework. Поэтому все подробности о создании и настройки проектов в этой статье мы рассматривать не будем.


От слов к делу

Напишем контроллер, в котором расположим код постинга в LiveJournal. Подробнее о постинге в LiveJournal читайте в одной из предыдущих статей.

Хочу отдельно заметить, что код не является самодостаточным. Это всего-лишь пример использования библиотек Zend Framework. Хотя, если запустить этот код, он работает вполне корректно.

Весь код написан в кодировке UTF-8. Я рекомендую использовать именно эту кодировку, чтобы не было никаких проблем.

Вот собственно код контроллера.

application/controllers/IndexController.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
 
class IndexController extends Zend_Controller_Action
{
 
    //логин и пароль в ЖЖ
    private $lj_uname = 'ЖЖ_логин';
    private $lj_upass = 'ЖЖ_пароль';
 
    public function indexAction()
    {
 
 
	/*создаем новый объект класса Zend_XmlRpc_Client 
и передаем ему адрес сервера*/
	$client = new Zend_XmlRpc_Client(
'http://www.livejournal.com/interface/xmlrpc');
	try{
	  //получаем challenge для авторизации
	  $challenge = $client->call('LJ.XMLRPC.getchallenge');
	}catch(Exception $e){
	  //в случае неудачи выводим ошибку
	  die($e);
	}
 
 
	//собираем данные для поста
	$data = array(
	  //имя пользователя
	  'username'=>$this->lj_uname,
	  //тип авторизации - challenge
	  'auth_method'=>'challenge',
	  //сам challenge
	  'auth_challenge'=>$challenge['challenge'],
	  //зашифрованный пароль
	  'auth_response'=>md5($challenge['challenge'].
md5($this->lj_upass)),
	  //версия
	  'ver'=>'1',
	  //переводы строк
	  'lineendings'=>"\n",
	  //название поста
	  'subject'=>'Пост в живой журнал',
	  //отформатированный текст поста
	  'event'=>'<strong>Антивирус.</strong> Ты кто?<br/>
	  <strong>Вирус.</strong> Область данных!<br/>
	  <strong>Антивирус.</strong> А не вирус?<br/>
	  <strong>Вирус.</strong> Hи боже мой!<br/>
	  <strong>Антивирус.</strong> А зачем прерывания '.
'перехватываешь?<br/>
	  <strong>Вирус.</strong> Я?!<br/>
	  <strong>Антивирус.</strong> Вот же подпрограмма.<br/>
	  <strong>Вирус.</strong> Это не подпрограмма. Это цитата из'.
' Лао-цзы на языке оригинала в альтернативной кодировке.<br/>
	  <strong>Антивирус.</strong> А зачем EXE-файлы ищешь?<br/>
	  <strong>Вирус.</strong> А вдруг хозяин спросит: '.
'"А где мои ЕХЕ-файлы?" А я ему - вот они!<br/>
	  <strong>Антивирус.</strong> Сдается мне, что ты '.
'все-таки вирус.<br/>
	  <strong>Вирус.</strong> Hу ладно, только тебе признаюсь, '.
'только ты никому не говори! Hа самом деле я... '.
'антивирусная вакцина!<br/>
	  <strong>Антивирус.</strong> А зачем нужна антивирусная'.
' вакцина, если есть я?<br/>
	  <strong>Вирус.</strong> Откуда я знаю? У хозяина спроси.<br/>
	  <strong>Антивирус.</strong> А если я тебя на всякий случай '.
'все-таки грохну?<br/>
	  <strong>Вирус.</strong> А если я тебя?<br/>
	  <strong>Антивирус.</strong> Hе получится. У меня'.
' управление.<br/>
	  <strong>Вирус.</strong> А ты свою контрольную сумму давно'.
' пересчитывал?<br/>
	  <strong>Антивирус.</strong> А причем тут моя '.
'контрольная... ой!!!<br/>
	  <strong>Вирус.</strong> То-то же.',
	  //день
	  'day'=>date('d'),
	  //месяц
	  'mon'=>date('m'),
	  //год
	  'year'=>date('Y'),
	  //час
	  'hour'=>date('H'),
	  //минута
	  'min'=>date('i'),
	  //публичный доступ к посту
	  'security'=>'public',
	  'props'=>array(
	    //true, если пост в отформатирован в html
	    'opt_preformatted'=>true,
	    //если добавляем запись задним числом
	    'opt_backdated'=>true,
	    //список тегов через запятую
	    'taglist'=>'юмор,анекдот'
	  ),
	);
 
	//отправляем данные на сервер
	try{
	  $p_data = $client->call('LJ.XMLRPC.postevent', array($data));
	}catch(Exception $e){
	  die($e);
	}	
 
	//если все нормально, то сервер вернет массив с 3-мя переменными:
	//itemid - идентификатор поста
	//url - URL-адрес поста
	//anum - аутентификационный номер, созданный для этой записи
	die('Пост успешно добавлен. Прочитать его можно <a href="'.
$p_data['url'].'" target="_blank">здесь</a>');
 
    }
 
 
 
}

Если не произошло никаких ошибок, то получим пост в LiveJournal.

Все оказалось не сложнее похищения яблока у слепого =)

Для работы нам потребуется класс Zend_XmlRpc_Client. Вся работа строится именно через него.

Конструктор объявлен следующим образом:

Zend_XmlRpc_Client::__construct($server, Zend_Http_Client $httpClient = null)

Параметры:

  • string $server — адрес XML-RPC сервера, с которым будем работать. В нашем случае — это http://www.livejournal.com/interface/xmlrpc;
  • Zend_Http_Client $httpClient — объект класса-клиента Zend_Http_Client. По умолчанию этот параметр имеет значение null. Если какой-то особенный http-клиент не нужен, то этот параметр можно пропустить. Zend_XmlRpc_Client сам создаст простой объект этого класса.

Вся основная работа (вызов процедур) строится через метод Zend_XmlRpc_Client::call(), который объявлен так:

Zend_XmlRpc_Client::call($method, $params=array())

Параметры:

  • string $method — имя вызываемой процедуры вместе с пространством имен, например LJ.XMLRPC.postevent;
  • mixed $params — параметры, передаваемые процедуре. Представляет собой массив. Каждый элемент массива является параметром XML-RPC процедуры.

Практически все параметры преобразовываются автоматически из php-типов в типы XML-RPC и обратно. Исключение составляют XML-RPC типы array, struct, base64, dateTime.iso8601. Типы array и struct получаются из массивов. Первый — из массива с числовыми индексами, а второй — из ассоциативного массива. Типы base64 и dateTime.iso8601 никак не преобразовываются. Чтобы передать параметр одного из этих типов нужно использовать объект класса Zend_XmlRpc_Value, например, так

$value = Zend_XmlRpc_Value::getXmlRpcValue('какая-то строка в base64',
 Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64)

А для dateTime.iso8601 используем константу Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME


Прокси

Для более удобного вызова процедур XML-RPC в Zend Framework реализована технология проксирования. Смысл в следующем. Мы вызываем нужную XML-RPC процедуру у объекта прокси, напрмер так

$proxy->getchallenge()

а он отправляет ее на сервер. Удобно, не правда ли?

Добавим к нашему контроллеру proxyAction, в котором рассмотрим пример использования этой технологии

application/controllers/IndexController.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public function proxyAction(){
 
 
	/*создаем новый объект класса Zend_XmlRpc_Client 
и передаем ему адрес сервера*/
	$client = new Zend_XmlRpc_Client(
'http://www.livejournal.com/interface/xmlrpc');
	/*получаем объект прокси, при этом передаем 
ему пространство имен*/
	$proxy = $client->getProxy('LJ.XMLRPC');
	try{
	  //получаем challenge для авторизации
	  $challenge = $proxy->getchallenge();
	}catch(Exception $e){
	  //в случае неудачи выводим ошибку
	  die($e);
	}
 
 
	//собираем данные для поста
	$data = array(
	  //имя пользователя
	  'username'=>$this->lj_uname,
	  //метод аутентификации
	  'auth_method'=>'challenge',
	  //значение challenge, которое прислал нам сервер
	  'auth_challenge'=>$challenge['challenge'],
	  //зашифрованный пароль
	  'auth_response'=>md5($challenge['challenge'].
md5($this->lj_upass)),
	  //версия протокола
	  'ver'=>'1',
	  //переводы строк
	  'lineendings'=>"\n",
	  //название поста
	  'subject'=>'Новый пост в живой журнал',
	  //текс поста
	  'event'=>'Сидит Дрим перед компом, '.
'занимается аутотренингом:<br/>
	  - Я не войду в Интернет, я не войду в Интернет, '.
'я не войду в Интернет...<br/>
	  Срывается, стучит что-то на клавиатуре. '.
'На дисплее появляется: <a href="http://www.web-junior.net">'.
'web-junior.net</a>.
	  <br/>Дрим:<br/>
	  - Это не я... Это не я... Это не я...',
	  //день
	  'day'=>date('d'),
	  //месяц
	  'mon'=>date('m'),
	  //год
	  'year'=>date('Y'),
	  //час
	  'hour'=>date('H'),
	  //минута
	  'min'=>date('i'),
	  //тип поста - публичный
	  'security'=>'public',
	  'props'=>array(
	    //пост отформатирован в html
	    'opt_preformatted'=>true,
	    //добавляем задним числом
	    'opt_backdated'=>true,
	    //список тегов
	    'taglist'=>'юмор,анекдот'
	  ),
	);
 
	//отправляем данные на сервер
	try{
	  $p_data = $proxy->postevent($data);
	}catch(Exception $e){
	  die($e);
	}	
 
	/*если все нормально, то сервер вернет структуру с 
3-мя переменными:
	itemid - идентификатор поста
	url - URL-адрес поста
	anum - аутентификационный номер, созданный для этой записи*/
	die('Пост успешно добавлен. Прочитать его можно <a href="'.
$p_data['url'].'" target="_blank">здесь</a>');
    }

В результате

В результате имеем новый пост

Вся настройка прокси-объекта сводится к вызову метода

Zend_XmlRpc_Client::getProxy($namespace = '')

В метод передается строка с пространством имен. В нашем случае — это LJ.XMLRPC. Если не передавать пространство имен, то придется вписывать его в вызов метода так

$proxy->LJ->XMLRPC->getchallenge()


Вот и все на сегодня. В следующий раз рассмотрим принципы организации XML-RPC сервера с помощью Zend Framework.



Читайте все статьи цикла:

Популярность: 3%


Интересное из других блогов:

2leep.com

И не забывайте комментировать статью.

Добавляйся в группу во вконтакте, чтобы самым первым узнавать все новости сайта

Отзывов: 5 на «XML-RPC: работа с помощью Zend Framework»

  1. Автор: GiN, 25 июля 2011 в 00:00

    использует Firefox 5.0 Firefox 5.0 на Windows XP Windows XP

    Спасибо за статью, очень познавательно.
    Прям захотелось Zend Framework попробовать поюзать )

  2. Автор: Алинка, 9 августа 2011 в 20:34

    использует Google Chrome 11.0.696.68 Google Chrome 11.0.696.68 на Windows XP Windows XP

    Полезная штука! все вышло настроить по вашей статье. Спасибо

  3. Автор: Sasha, 25 августа 2011 в 15:38

    использует Firefox 3.6.20 Firefox 3.6.20 на Windows XP Windows XP

    Такого рода статьи мотивирует человека овладеть таким навыком как знание программирования zend framework))) спасибо за статью

  4. Автор: Сергей, 8 сентября 2011 в 13:48

    использует Google Chrome 13.0.782.220 Google Chrome 13.0.782.220 на Windows 7 Windows 7

    Вот это полезная статья по зенду! Спасибо!)

  5. Автор: Валерий, 2 декабря 2011 в 23:49

    использует Firefox 8.0 Firefox 8.0 на Windows 7 x64 Edition Windows 7 x64 Edition

    Реально полезно было!

RSS-лента комментариев. Адрес для трекбека

Трэкбэки и пинги:

Ваш отзыв

Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Нажимая на кнопку "Добавить" вы принимаете правила комментирования