PHP — php精粹-编写高效的php代码 --- API
1.数据格式
(1)json
示例代码:
$jsonData = '[{"title":"The Magic Flute","time":1329636600}, {"title":"Vivaldi Four Seasons","time":1329291000},{"title":"Mozart\'s Requiem","time":1330196400}]';
$concerts = json_decode($jsonData, true);
print_r($concerts);
/*
Output:
Array
(
[0] => Array
(
[title] => The Magic Flute
[time] => 1329636600
)
[1] => Array
(
[title] => Vivaldi Four Seasons
[time] => 1329291000
)
[2] => Array
(
[title] => Mozart's Requiem
[time] => 1330196400
)
)
*/
(2)xml
示例代码:
$simplexml = new SimpleXMLElement(
'<?xml version="1.0"?><concerts />');
$concert1 = $simplexml->addChild('concert');
$concert1->addChild("title", "The Magic Flute");
$concert1->addChild("time", 1329636600);
$concert2 = $simplexml->addChild('concert');
$concert2->addChild("title", "Vivaldi Four Seasons");
$concert2->addChild("time", 1329291000);
$concert3 = $simplexml->addChild('concert');
$concert3->addChild("title", "Mozart's Requiem");
$concert3->addChild("time", 1330196400);
echo $simplexml->asXML();
/* output:
<concerts><concert><title>The Magic Flute</title><time>1329636600</time></concert><concert>
<title>Vivaldi Four Seasons</title><time>1329291000</time></concert><concert><title>Mozart's Requiem</title>
<time>1330196400</time></concert></concerts>
2.HTTP协议
(1)发送HTTP请求
①cURL
用于请求URL的简单命令行工具
curl http://www.lys.com
②PHP cURL扩展
代码:
$ch = curl_init('http://api.bitly.com/v3/shorten'
. '?login=user&apiKey=secret'
. '&longUrl=http%3A%2F%2Fsitepoint.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
print_r(json_decode($result));
/* output:
stdClass Object
(
[status_code] => 200
[status_txt] => OK
[data] => stdClass Object
(
[long_url] => http://sitepoint.com/
[url] => http://bit.ly/qmcGU2
[hash] => qmcGU2
[global_hash] => 3mWynL
[new_hash] => 0
)
)
*/
③使用pecl_http扩展
示例代码:
$request = new HttpRequest('http://api.bitly.com/v3/shorten'
. '?login=user&apiKey=secret'
. '&longUrl=http%3A%2F%2Fsitepoint.com');
$request->send();
$result = $request->getResponseBody();
print_r(json_decode($result));
/* output:
stdClass Object
(
[status_code] => 200
[status_txt] => OK
[data] => stdClass Object
(
[long_url] => http://sitepoint.com/
[url] => http://bit.ly/qmcGU2
[hash] => qmcGU2
[global_hash] => 3mWynL
[new_hash] => 0
)
)
*/
④PHP流
配置php.ini,启用allow_url_fopen选项
示例代码:
$post_data['password'] = implode('', $password);
$context = stream_context_create(array('http' => array(
'method' => 'POST',
'follow_location' => false,
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => http_build_query($post_data)
)));
$response = file_get_contents($url, false, $context);
(2)HTTP状态码

(3)HTTP文件头
在php应用程序中返回文件头信息:
代码:
header(‘Content-Type:text/html;charset=utf8’); header(‘HTTP/1.1 404 Not Found’);

3.理解并选择服务类型
(1)、一些术语
RPC 是Remote ProcedureCall(远程调用过程)的缩写。(XML-RPC JSON-RPC)
SOAP (Simple Object Access Protocol),我们通过使用WSDL(Web Service Description Language,Web服务描述语言),这是用来描述Web服务的一组定义。
REST REST将每个项目都视为一个资源,我们通过发送正确的动词为这个资源执行动作。
(2)、使用SOAP
①非SOAP模式
代码:
class ServiceFunctions
{
public function getDisplayName($first_name, $last_name) {
$name = '';
$name .= strtoupper(substr($first_name, 0, 1));
$name .= ' ' . ucfirst($last_name);
return $name;
}
public function countWords($paragraph) {
$words = preg_split('/[. ,!?;]+/',$paragraph);
return count($words);
}
}
//创建SOAP服务
include 'ServiceFunctions.php';
$options = array('uri'=>'http://localhost/');
$server = new SoapServer(NULL, $options);
$server->setClass('ServiceFunctions');
$server->handle();
//使用这个服务
$options = array(
'uri'=>'http://localhost',
'location'=>'http://localhost/php_lib/oop/spbooks/chapter_03/SoapServer.php',
'trace'=>1
);
$client = new SoapClient(NULL, $options);
echo $client->getDisplayName('luoyunshu','moushu');
//调试代码
$functions = $client->__getFunctions();
var_dump($functions);
$request = $client->__getLastRequest();
var_dump($request);
$headers = $client->__getLastRequestHeaders();
var_dump($headers);
②使用WSDL描述SOAP服务
可用phpclasses.org中带有的WSDL生成器生成WSDL
创建SOAP客户端
示例代码:
ini_set('soap.wsdl_cache_enabled',0);
$client = new SoapClient('http://localhost/php_lib/oop/spbooks/chapter_03/wsdl.xml');
$functions = $client->__getFunctions();
var_dump($functions);
(3)RPC服务
①建立RPC服务
示例代码:
class ServiceFunctions
{
public function getDisplayName($first_name, $last_name) {
$name = '';
$name .= strtoupper(substr($first_name, 0, 1));
$name .= ' ' . ucfirst($last_name);
return $name;
}
public function countWords($paragraph) {
$words = preg_split('/[. ,!?;]+/',$paragraph);
return count($words);
}
}
json_rpc.php:
require 'servicefunctions.php';
if(isset($_GET['method'])) {
switch($_GET['method']) {
case 'countWords':
$response = ServiceFunctions::countWords($_GET['words']);
break;
case 'getDisplayName':
$response = ServiceFunctions::getdisplayName($_GET['first_name'], $_GET['last_name']);
break;
default:
$response = "Unknown Method";
break;
}
} else {
$response = "Unknown Method";
}
header('Content-Type: application/json');
echo json_encode($response);
要使用API中的这些方法,我们仅仅需发送如下的URL的请求:
http://localhost/json_rpc.php?method=getDisplayName&first_name=ms&last_name=lys
==>一个好的API将会支持不同的输出和类似这样的结构, 甚至错误消息也通过相同的过程输出,我们可用不同方式灵活地对输出就行解码。
(4)开发和使用RESTful服务
①建立一个RESTful服务(mvc模式)
a.使用重写规则重定向到index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
b.收集传过来的数据
index.php:
/* vim: set shiftwidth=2:*/
function __autoload($classname) {
require strtolower($classname) . '.php';
}
// initialise the request object and store the requested URL
$request = new Request();
$request->url_elements = array();
if(isset($_SERVER['PATH_INFO'])) {
$request->url_elements = explode('/', $_SERVER['PATH_INFO']);
//var_dump($request->url_elements);
//exit();
}
// figure out the verb and grab the incoming data
$request->verb = $_SERVER['REQUEST_METHOD'];
//echo $request->verb;
switch($request->verb) {
case 'GET':
$request->parameters = $_GET;
break;
case 'POST':
case 'PUT':
$request->parameters = json_decode(file_get_contents('php://input'), 1);
break;
case 'DELETE':
default:
// we won't set any parameters in these cases
$request->parameters = array();
}
//var_dump($request->url_elements);
//exit();
// route the request
if($request->url_elements) {
$controller_name = ucfirst($request->url_elements[1]) . 'Controller';
if(class_exists($controller_name)) {
$controller = new $controller_name();
$action_name = ucfirst($request->verb) . "Action";
$response = $controller->$action_name($request);
} else {
header('HTTP/1.0 400 Bad Request');
$response = "Unknown Request for " . $request->url_elements[1];
}
} else {
header('HTTP/1.0 400 Bad Request');
$response = "Unknown Request";
}
echo json_encode($response);
c.新建一个控制器(eventscontroller.php)
/* vim: set shiftwidth=2:*/
class EventsController
{
protected $events_file = 'events-list.txt';
public function GETAction($request) { //处理get请求
$events = $this->readEvents();
//var_dump($events);
//exit();
if(isset($request->url_elements[2]) && is_numeric($request->url_elements[2])) {
if(isset($events[$request->url_elements[2]])) {
return $events[$request->url_elements[2]];
}else {
return array();
}
} else {
return $events;
}
}
public function POSTAction($request) { //处理post请求
// error checking and filtering input MUST go here
$events = $this->readEvents();
$event = array();
$event['title'] = $request->parameters['title'];
$event['date'] = $request->parameters['date'];
$event['capacity'] = $request->parameters['capacity'];
$events[] = $event;
$this->writeEvents($events);
$id = max(array_keys($events));
header('HTTP/1.1 201 Created');
header('Location:/events/'. $id);
return '';
}
public function PUTAction($request) { //处理put请求
// error checking and filtering input MUST go here
$events = $this->readEvents();
$event = array();
$event['title'] = $request->parameters['title'];
$event['date'] = $request->parameters['date'];
$event['capacity'] = $request->parameters['capacity'];
$id = $request->url_elements[2];
$events[$id] = $event;
$this->writeEvents($events);
header('HTTP/1.1 204 No Content');
header('Location: /events/'. $id);
return '';
}
public function DELETEAction($request) { //处理delete请求
$events = $this->readEvents();
if(isset($request->url_elements[2]) && is_numeric($request->url_elements[2])) {
unset($events[$request->url_elements[2]]);
$this->writeEvents($events);
header('HTTP/1.1 204 No Content');
header('Location: /events');
}
return '';
}
protected function readEvents() {
$events = unserialize(file_get_contents($this->events_file));
if(empty($events)) {
// invent some event data
$events[] = array('title' => 'Summer Concert',
'date' => date('U', mktime(0,0,0,7,1,2012)),
'capacity' => '150');
$events[] = array('title' => 'Valentine Dinner',
'date' => date('U', mktime(0,0,0,2,14,2012)),
'capacity' => '48');
$this->writeEvents($events);
}
return $events;
}
protected function writeEvents($events) {
file_put_contents($this->events_file, serialize($events));
return true;
}
}
需要加载的Request类
request.php:
class Request { }
4.选择一个web服务
决定你将采用哪种服务形式,如果你的服务和表述数据结合很紧密,你可能会选择RESTful服务。对于计算机之间的数据交换,你可能选择XML-RPC或SOAP,特别是在确信SOAP已被人们透彻理解的企业环境下。当我们从JavaScript传输异步或者传输到移动设备时,JSON也许是一个更好的选择。
一个健壮性和可靠性的服务将对非破坏性的服务将对非破坏性的失败做出反应。而且把哪里发生错误的信息反馈给用户。错误信息应该以同样的格式返回,如同一个成功的输出将会到达。
有一个设计原则我们陈其为KISS(Keep it Simple,stupid 保持简单、无趣),就API设计而言少即是多。要当心避免创建一个广泛的、不规则的、不稳定的API。只有我们真正需要的时候才添加功能,并且要确保新功能和其他API实现的方式一致。
PHP — php精粹-编写高效的php代码 --- API的更多相关文章
- php精粹-编写高效的php代码 --- php设计模式
1.选择一个最合适的设计模式 没有任何事物是完美的,也没有人说过设计模式一个严格的放之四海而皆准的解决方法.因此你可以改变这些模式,使它们更适合手头的工作.对于某些设计模式而言,他们就是所属程序固有的 ...
- 编写高效的Android代码
编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...
- 编写高效的jQuery代码
http://www.css88.com/jqapi-1.9/ 编写高效的jQuery代码 最近写了很多的js,虽然效果都实现了,但是总感觉自己写的js在性能上还能有很大的提升.本文我计划总结一些网上 ...
- 如何在Android上编写高效的Java代码
转自:http://www.ituring.com.cn/article/177180 作者/ Erik Hellman Factor10咨询公司资深移动开发顾问,曾任索尼公司Android团队首席架 ...
- 如何编写高效的jQuery代码
jQuery的编写原则: 一.不要过度使用jQuery 1. jQuery速度再快,也无法与原生的javascript方法相比,而且建立的jQuery对象包含的信息量很庞大.所以有原生方法可以使用的场 ...
- 如何编写高效的jQuery代码(转载)
jQuery的编写原则: 一.不要过度使用jQuery 1. jQuery速度再快,也无法与原生的javascript方法相比,而且建立的jQuery对象包含的信息量很庞大.所以有原生方法可以使用的场 ...
- 利用on和off方法编写高效的js代码
先说下将这个话题的起因:最近发现公司的功能代码,很多在dom对象删除以后,其声明的绑定在window上的resize事件还一直存在,导致相同的功能代码执行了几次.对于我这种轻微代码洁癖的人来说,简直是 ...
- (转载)编写高效的jQuery代码
原文地址:http://www.cnblogs.com/ppforever/p/4084232.html 最近写了很多的js,虽然效果都实现了,但是总感觉自己写的js在性能上还能有很大的提升.本文我计 ...
- js学习笔记-编写高效、规范的js代码-Tom
编写高效.规范的js代码: 1.变量命名空间问题,尽量使用局部变量,防止命名冲突(污染作用域中的全局变量):全局空间命名的变量可以在对应的文档域任意位置中使用window调用. 2.尽量使用单var定 ...
随机推荐
- Oracle学习过程(随时更新)
1.入门 实用的一些查询语句: 查询用户所有表注释 select * from user_tab_comments 条件查询 根据两个值查询 select*from table where 字段 in ...
- navicate恢复数据
恢复psc文件,出现记录数为0 不要使用事务,选用遇到错误继续
- Sql Server2005 Transact-SQL 窗口函数(OVER)
1.简介: SQL Server 2005中的窗口函数帮助你迅速查看不同级别的聚合,通过它可以非常方便地累计总数.移动平均值.以及执行其它计算.窗口函数功能非常强大,使用起来也十分容易.可以使用这个技 ...
- 在Apache Tomcat 7设置redis作为session store
在Apache Tomcat 7设置redis作为session store //输出tomcat控制台日志 root@ubuntu:~# cd /usr/tomcat/apache-tomcat- ...
- 【Heritrix基础教程之1】在Eclipse中配置Heritrix
一.新建项目并将Heritrix源代码导入 1.下载heritrix-1.14.4-src.zip和heritrix-1.14.4.zip两个压缩包,并解压,以后分别简称SRC包和ZIP包: 2.在E ...
- 解析XML文件时做得修改
在.h文件中找到需要在Build Settings中设置的东西,查找Header Search Paths,然后添加/usr/include/libxml2
- 从数组中随机取n条不重复的数据
工作中经常遇到有关数组的一些操作 1. 从数据中随机取n条不重复的数据 (PS:下面的S.each是KISSY.each方法,大家可以改为for循环) /* 1 从数组arr中随机取n条不重复的数据 ...
- oracle EBS 基于Host并发程序的开发(转)
参考此编文章 http://www.doc88.com/p-0972680953307.html http://www.cnblogs.com/benio/archive/2011/06/10/207 ...
- 推荐几个对Asp.Net开发者比较实用的工具 2
推荐几个对Asp.Net开发者比较实用的工具.大家有相关工具也可以在评论区留言,一起努力学习. 作为程序员要有挑战精神,大家可以尝试一下这些工具. 已经有篇文章写到了vs的扩展工具,这里不再累赘,请查 ...
- (转载)重温SQL——行转列,列转行
原文地址:http://www.cnblogs.com/kerrycode/archive/2010/07/28/1786547.html 行转列,列转行是我们在开发过程中经常碰到的问题.行转列一般通 ...