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定 ...
随机推荐
- JNI 技术与 Android 应用
1. 什么是 JNI JNI是Java Native Interface的缩写.从Java 1.1开始,JNI标准成为java平台的一部分,它允许Java和其他语言进行交互.JNI一开始为C和C++而 ...
- 我这个IOS渣渣又来写随笔了
我这个渣渣又来写了,哎,今天看了一篇大神面试别人的文章,感觉还有很遥远的路要走,不过没关系,还年轻,才入ios两个月,我相信自己的学习能力,加油! 博客园会是我成长的见证!
- 职责链模式vs状态模式区别
状态模式在具体状态里设置了下一状态. 而职责链模式是在客户端代码里设置了下一状态的处理对象. 如果状态模式里的任何一环缺失,将导致事情无法进行下去.职责链模式的链式在客户端连接的,也就是说,如果我们请 ...
- Edit显示行号
Edit显示代码行号 关键点 使用这个类然后关联Edit的变量为 LineNumberEdit类型的 实现过程 //////////////////////////////////////////// ...
- 我的Android开发相关文章
Pro Android学习笔记: Pro Android学习笔记(一零七):2D动画(2):layout渐变动画 2014.7.25 Pro Android学习笔记(一零六):2D动画(1):fram ...
- 对Jsp提交input标签空格和回车的处理
今天做增加的时候发现一个问题,在js中去掉空格的时候如果这么写 var stage_name = document.getElementById("stage_name").val ...
- [HTTP] Origins, CROS, Preflight
Origins made up of three parts the data scheme, the hostname and the prot. It is important to know t ...
- [React] React Fundamentals: Mixins
Mixins will allow you to apply behaviors to multiple React components. Components are the best way t ...
- Java基础知识强化之IO流笔记37:FileReader/FileWriter(转换流的子类)复制文本文件案例
1. 转换流的简化写法: 由于我们常见的操作都是使用本地默认编码,所以,不用指定编码.而转换流的名称有点长,所以,Java就提供了其子类供我们使用:FileReader / FileWriterOut ...
- 写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增长的ID作为主键,注意:ID可能不是连续的。
答:解1: select top 10 * from A where id not in (select top 30 id from A) 解2: select top 10 * from A ...