CodeIgniter 的 XML-RPC 類允許你向另一個(gè)服務(wù)器發(fā)送請(qǐng)求, 或者建立一個(gè)你自己的 XML-RPC 服務(wù)器來(lái)接受請(qǐng)求。
這是一種在兩臺(tái)計(jì)算機(jī)之間使用 XML 通過(guò)互聯(lián)網(wǎng)進(jìn)行通信的簡(jiǎn)單方法。 一臺(tái)計(jì)算機(jī) , 我們稱之為客戶端 , 發(fā)送一個(gè) XML-RPC 請(qǐng)求給另外一臺(tái)計(jì)算機(jī), 我們稱之為服務(wù)器,當(dāng)服務(wù)器收到請(qǐng)求時(shí),對(duì)其進(jìn)行處理然后將結(jié)果返回給客戶端。
例如,使用 MetaWeblog API 時(shí),XML-RPC 客戶端(通常是桌面發(fā)布工具) 將會(huì)發(fā)送請(qǐng)求到你站點(diǎn)上的 XML-RPC 服務(wù)器,這個(gè)請(qǐng)求可能是發(fā)布一篇新博客, 或者編輯一篇已有的博客。當(dāng) XML-RPC 服務(wù)器收到該請(qǐng)求時(shí),它會(huì)決定使用 哪個(gè)類和方法來(lái)處理該請(qǐng)求,請(qǐng)求處理完成后,服務(wù)器將發(fā)送一條回復(fù)消息。
關(guān)于 XML-RPC 的規(guī)范,你可以查看 XML-RPC 的網(wǎng)站。
跟 CodeIgniter 中的其他類一樣,可以在你的控制器中使用 $this->load->library() 方法加載 XML-RPC 類和 XML-RPC 服務(wù)器類。
加載 XML-RPC 類如下:
$this->load->library('xmlrpc');
一旦加載,XML-RPC 類就可以像下面這樣使用:
$this->xmlrpc
加載 XML-RPC 服務(wù)器類如下:
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
一旦加載,XML-RPC 服務(wù)器類就可以像下面這樣使用:
$this->xmlrpcs
注解
當(dāng)使用 XML-RPC 服務(wù)器類時(shí),xmlrpc 和 xmlrpcs 都需要加載。
向 XML-RPC 服務(wù)器發(fā)送一個(gè)請(qǐng)求,你需要指定以下信息:
下面是個(gè)基本的例子,向 Ping-o-Matic 發(fā)送一個(gè)簡(jiǎn)單的 Weblogs.com ping 請(qǐng)求。
$this->load->library('xmlrpc');
$this->xmlrpc->server('http://rpc.pingomatic.com/', 80);
$this->xmlrpc->method('weblogUpdates.ping');
$request = array('My Photoblog', 'http://www.my-site.com/photoblog/');
$this->xmlrpc->request($request);
if ( ! $this->xmlrpc->send_request())
{
echo $this->xmlrpc->display_error();
}
上面的代碼初始化了一個(gè) XML-RPC 類,并設(shè)置了服務(wù)器 URL 和要調(diào)用的方法 (weblogUpdates.ping)。然后通過(guò) request() 方法編譯請(qǐng)求, 例子中請(qǐng)求是一個(gè)數(shù)組(標(biāo)題和你網(wǎng)站的 URL)。最后,使用 send_request() 方法發(fā)送完整的請(qǐng)求。如果發(fā)送請(qǐng)求方法返回 FALSE ,我們會(huì)顯示出 XML-RPC 服務(wù)器返回的錯(cuò)誤信息。
XML-RPC 請(qǐng)求就是你發(fā)送給 XML-RPC 服務(wù)器的數(shù)據(jù),請(qǐng)求中的每一個(gè)數(shù)據(jù)也被稱為請(qǐng)求參數(shù)。 上面的例子中有兩個(gè)參數(shù):你網(wǎng)站的 URL 和 標(biāo)題。當(dāng) XML-RPC 服務(wù)器收到請(qǐng)求后, 它會(huì)查找它所需要的參數(shù)。
請(qǐng)求參數(shù)必須放在一個(gè)數(shù)組中,且數(shù)組中的每個(gè)參數(shù)都必須是 7 種數(shù)據(jù)類型中的一種 (string、number、date 等),如果你的參數(shù)不是 string 類型,你必須在請(qǐng)求數(shù)組中 指定它的數(shù)據(jù)類型。
下面是三個(gè)參數(shù)的簡(jiǎn)單例子:
$request = array('John', 'Doe', 'www.some-site.com');
$this->xmlrpc->request($request);
如果你的數(shù)據(jù)類型不是 string ,或者你有幾個(gè)不同類型的數(shù)據(jù),那么你需要將 每個(gè)參數(shù)放到它單獨(dú)的數(shù)組中,并在數(shù)組的第二位聲明其數(shù)據(jù)類型:
$request = array(
array('John', 'string'),
array('Doe', 'string'),
array(FALSE, 'boolean'),
array(12345, 'int')
);
$this->xmlrpc->request($request);
下面的 數(shù)據(jù)類型 一節(jié)列出了所有支持的數(shù)據(jù)類型。
XML-RPC 服務(wù)器扮演著類似于交通警察的角色,等待進(jìn)入的請(qǐng)求, 并將它們轉(zhuǎn)到恰當(dāng)?shù)暮瘮?shù)進(jìn)行處理。
要?jiǎng)?chuàng)建你自己的 XML-RPC 服務(wù)器,你需要先在負(fù)責(zé)處理請(qǐng)求的控制器中初始化 XML-RPC 服務(wù)器類,然后設(shè)置一個(gè)映射數(shù)組,用于將請(qǐng)求轉(zhuǎn)發(fā)到合適的類和方法, 以便進(jìn)行處理。
下面是個(gè)例子:
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
$config['functions']['new_post'] = array('function' => 'My_blog.new_entry');
$config['functions']['update_post'] = array('function' => 'My_blog.update_entry');
$config['object'] = $this;
$this->xmlrpcs->initialize($config);
$this->xmlrpcs->serve();
上例中包含了兩個(gè)服務(wù)器允許的請(qǐng)求方法,數(shù)組的左邊是允許的方法名, 數(shù)組的右邊是當(dāng)請(qǐng)求該方法時(shí),將會(huì)映射到的類和方法。
其中,'object' 是個(gè)特殊的鍵,用于傳遞一個(gè)實(shí)例對(duì)象,當(dāng)映射的方法無(wú)法使用 CodeIgniter 超級(jí)對(duì)象時(shí),它將是必須的。
換句話說(shuō),如果 XML-RPC 客戶端發(fā)送一個(gè)請(qǐng)求到 new_post 方法, 你的服務(wù)器會(huì)加載 My_blog 類并調(diào)用 new_entry 函數(shù)。如果這個(gè)請(qǐng)求是到update_post 方法的,那么你的服務(wù)器會(huì)加載 My_blog 類并調(diào)用 update_entry 方法。
上面例子中的函數(shù)名是任意的。你可以決定這些函數(shù)在你的服務(wù)器上叫什么名字, 如果你使用的是標(biāo)準(zhǔn)的 API,比如 Blogger 或者 MetaWeblog 的 API, 你必須使用標(biāo)準(zhǔn)的函數(shù)名。
這里還有兩個(gè)附加的配置項(xiàng),可以在服務(wù)器類初始化時(shí)配置使用。debug 設(shè)為 TRUE 以便調(diào)試, xss_clean 可被設(shè)置為 FALSE 以避免數(shù)據(jù)被安全類庫(kù)的 xss_clean 函數(shù)過(guò)濾。
當(dāng) XML-RPC 服務(wù)器收到請(qǐng)求并加載類與方法來(lái)處理時(shí),它會(huì)接收一個(gè)包含客戶端發(fā)送的數(shù)據(jù)參數(shù)。
在上面的例子中,如果請(qǐng)求的是 new_post 方法,服務(wù)器請(qǐng)求的類與方法會(huì)像這樣:
class My_blog extends CI_Controller {
public function new_post($request)
{
}
}
$request 變量是一個(gè)由服務(wù)端匯集的對(duì)象,包含由 XML-RPC 客戶端發(fā)送來(lái)的數(shù)據(jù)。 使用該對(duì)象可以讓你訪問(wèn)到請(qǐng)求參數(shù)以便處理請(qǐng)求。請(qǐng)求處理完成后, 發(fā)送一個(gè)響應(yīng)返回給客戶端。
下面是一個(gè)實(shí)際的例子,使用 Blogger API 。Blogger API 中的一個(gè)方法是 getUserInfo(), XML-RPC 客戶端可以使用該方法發(fā)送用戶名和密碼到服務(wù)器,在服務(wù)器返回的數(shù)據(jù)中, 會(huì)包含該用戶的信息(昵稱,用戶 ID,Email 地址等等)。下面是處理的代碼:
class My_blog extends CI_Controller {
public function getUserInfo($request)
{
$username = 'smitty';
$password = 'secretsmittypass';
$this->load->library('xmlrpc');
$parameters = $request->output_parameters();
if ($parameters[1] != $username && $parameters[2] != $password)
{
return $this->xmlrpc->send_error_message('100', 'Invalid Access');
}
$response = array(
array(
'nickname' => array('Smitty', 'string'),
'userid' => array('99', 'string'),
'url' => array('http://yoursite.com', 'string'),
'email' => array('jsmith@yoursite.com', 'string'),
'lastname' => array('Smith', 'string'),
'firstname' => array('John', 'string')
),
'struct'
);
return $this->xmlrpc->send_response($response);
}
}
output_parameters() 函數(shù)獲取一個(gè)由客戶端發(fā)送的請(qǐng)求參數(shù)數(shù)組。 上面的例子中輸出參數(shù)將會(huì)是用戶名和密碼。
如果客戶端發(fā)送的用戶名和密碼無(wú)效的話,將使用 send_error_message() 函數(shù)返回錯(cuò)誤信息。
如果操作成功,客戶端會(huì)收到包含用戶信息的響應(yīng)數(shù)組。
和請(qǐng)求一樣,響應(yīng)也必須被格式化為數(shù)組。然而不同于請(qǐng)求信息,響應(yīng)數(shù)組 只包含一項(xiàng) 。 該項(xiàng)可以是一個(gè)包含其他數(shù)組的數(shù)組,但是只能有一個(gè)主數(shù)組,換句話說(shuō), 響應(yīng)的結(jié)果大概是下面這個(gè)樣子:
$response = array('Response data', 'array');
但是,響應(yīng)通常會(huì)包含多個(gè)信息。要做到這樣,我們必須把各個(gè)信息放到他們自己的數(shù)組中, 這樣主數(shù)組就始終只有一個(gè)數(shù)據(jù)項(xiàng)。下面是一個(gè)例子展示如何實(shí)現(xiàn)這樣的效果:
$response = array(
array(
'first_name' => array('John', 'string'),
'last_name' => array('Doe', 'string'),
'member_id' => array(123435, 'int'),
'todo_list' => array(array('clean house', 'call mom', 'water plants'), 'array'),
),
'struct'
);
注意:上面的數(shù)組被格式化為 struct,這是響應(yīng)最常見(jiàn)的數(shù)據(jù)類型。
如同請(qǐng)求一樣,響應(yīng)可以是七種數(shù)據(jù)類型中的一種,參見(jiàn) 數(shù)據(jù)類型 一節(jié)。
如果你需要發(fā)送錯(cuò)誤信息給客戶端,可以使用下面的代碼:
return $this->xmlrpc->send_error_message('123', 'Requested data not available');
第一個(gè)參數(shù)為錯(cuò)誤編號(hào),第二個(gè)參數(shù)為錯(cuò)誤信息。
為了幫助你理解目前為止講的這些內(nèi)容,讓我們來(lái)創(chuàng)建兩個(gè)控制器,演示下 XML-RPC 的客戶端和服務(wù)端。你將用客戶端來(lái)發(fā)送一個(gè)請(qǐng)求到服務(wù)端并從服務(wù)端收到一個(gè)響應(yīng)。
使用文本編輯器創(chuàng)建一個(gè)控制器 Xmlrpc_client.php ,在這個(gè)控制器中, 粘貼以下的代碼并保存到 applications/controllers/ 目錄:
<?php
class Xmlrpc_client extends CI_Controller {
public function index()
{
$this->load->helper('url');
$server_url = site_url('xmlrpc_server');
$this->load->library('xmlrpc');
$this->xmlrpc->server($server_url, 80);
$this->xmlrpc->method('Greetings');
$request = array('How is it going?');
$this->xmlrpc->request($request);
if ( ! $this->xmlrpc->send_request())
{
echo $this->xmlrpc->display_error();
}
else
{
echo '<pre>';
print_r($this->xmlrpc->display_response());
echo '</pre>';
}
}
}
?>
注解
上面的代碼中我們使用了一個(gè) URL 輔助函數(shù),更多關(guān)于輔助函數(shù)的信息, 你可以閱讀 這里 。
使用文本編輯器創(chuàng)建一個(gè)控制器 Xmlrpc_server.php ,在這個(gè)控制器中, 粘貼以下的代碼并保存到 applications/controllers/ 目錄:
<?php
class Xmlrpc_server extends CI_Controller {
public function index()
{
$this->load->library('xmlrpc');
$this->load->library('xmlrpcs');
$config['functions']['Greetings'] = array('function' => 'Xmlrpc_server.process');
$this->xmlrpcs->initialize($config);
$this->xmlrpcs->serve();
}
public function process($request)
{
$parameters = $request->output_parameters();
$response = array(
array(
'you_said' => $parameters[0],
'i_respond' => 'Not bad at all.'
),
'struct'
);
return $this->xmlrpc->send_response($response);
}
}
現(xiàn)在使用類似于下面這樣的鏈接訪問(wèn)你的站點(diǎn):
example.com/index.php/xmlrpc_client/
你應(yīng)該能看到你發(fā)送到服務(wù)端的信息,以及服務(wù)器返回的響應(yīng)信息。
在客戶端,你發(fā)送了一條消息("How's is going?")到服務(wù)端, 隨著一個(gè)請(qǐng)求發(fā)送到 "Greetings" 方法。服務(wù)端收到這個(gè)請(qǐng)求并映射到 "process" 函數(shù),然后返回響應(yīng)信息。
如果你希望在你的方法參數(shù)中使用關(guān)聯(lián)數(shù)組,那么你需要使用 struct 數(shù)據(jù)類型:
$request = array(
array(
// Param 0
array('name' => 'John'),
'struct'
),
array(
// Param 1
array(
'size' => 'large',
'shape'=>'round'
),
'struct'
)
);
$this->xmlrpc->request($request);
你可以在服務(wù)端處理請(qǐng)求信息時(shí)獲取該關(guān)聯(lián)數(shù)組。
$parameters = $request->output_parameters();
$name = $parameters[0]['name'];
$size = $parameters[1]['size'];
$shape = $parameters[1]['shape'];
根據(jù) XML-RPC 規(guī)范 一共有七種不同的數(shù)據(jù)類型可以在 XML-RPC 中使用:
classCI_Xmlrpc
initialize([$config = array()])
參數(shù):
返回類型: void
初始化 XML-RPC 類,接受一個(gè)包含你設(shè)置的參數(shù)的關(guān)聯(lián)數(shù)組。
server($url[, $port = 80[, $proxy = FALSE[, $proxy_port = 8080]]])
參數(shù):
返回類型: void
用于設(shè)置 XML-RPC 服務(wù)器端的 URL 和端口:
$this->xmlrpc->server('http://www.sometimes.com/pings.php', 80);
支持基本的 HTTP 身份認(rèn)證,只需簡(jiǎn)單的將其添加到 URL中:
$this->xmlrpc->server('http://user:pass@localhost/', 80);
timeout($seconds = 5)
參數(shù):
返回類型: void
設(shè)置一個(gè)超時(shí)時(shí)間(單位為秒),超過(guò)該時(shí)間,請(qǐng)求將被取消:
$this->xmlrpc->timeout(6);
method($function)
參數(shù):
返回類型: void
設(shè)置 XML-RPC 服務(wù)器接受的請(qǐng)求方法:
$this->xmlrpc->method('method');
其中 method 參數(shù)為請(qǐng)求方法名。
request($incoming)
參數(shù):
返回類型: void
接受一個(gè)數(shù)組參數(shù),并創(chuàng)建一個(gè)發(fā)送到 XML-RPC 服務(wù)器的請(qǐng)求:
$request = array(array('My Photoblog', 'string'), 'http://www.yoursite.com/photoblog/');
$this->xmlrpc->request($request);
send_request()
返回: TRUE on success, FALSE on failure
返回類型: bool
發(fā)送請(qǐng)求的方法,成功返回 TRUE,失敗返回 FALSE ,可以用在條件判斷里。
display_error()
返回: Error message string
返回類型: string
當(dāng)請(qǐng)求失敗后,返回錯(cuò)誤信息。
echo $this->xmlrpc->display_error();
display_response()
返回: Response
返回類型: mixed
遠(yuǎn)程服務(wù)器接收請(qǐng)求后返回的響應(yīng),返回的數(shù)據(jù)通常是一個(gè)關(guān)聯(lián)數(shù)組。
$this->xmlrpc->display_response();
send_error_message($number, $message)
參數(shù):
返回: XML_RPC_Response instance
返回類型: XML_RPC_Response
這個(gè)方法允許你從服務(wù)器發(fā)送一個(gè)錯(cuò)誤消息到客戶端。 第一個(gè)參數(shù)是錯(cuò)誤編號(hào),第二個(gè)參數(shù)是錯(cuò)誤信息。
return $this->xmlrpc->send_error_message(123, 'Requested data not available');
更多建議: