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定 ...
随机推荐
- android 控件花屏问题
发现自己的手机上某个界面出现了花屏,某些控件背景被拉伸过多遮住了其他控件,很难看.这种现象高概率出现,分析了下发现:一旦发生这种现象,必然 会打印下面这种log,google了下,这种log应该是硬件 ...
- Log4E
工具地址:http://marketplace.eclipse.org/content/log4e Log4E插件能够帮助你在Java项目中轻松地创建记录器.它可以在以下几个任务中提供帮助:记录器声明 ...
- C++中的类访问控制
C++中 public,protected, private 访问标号小结 第一:private, public, protected 访问标号的访问范围. private:只能由1.该类中的函数.2 ...
- linux gnome 安装
首先先下载x-window的内核:apt-get -u install x-window-system-core:下载登录管理界面gdm或kdm:apt-get -u install gdm gdm- ...
- html笔记04:在html之中导入css两种常见方法
1.导入式: <html> <head> <title></title> <style type="text/css"> ...
- css图片垂直居中
css图片垂直居中一.style代码 .case-pic{ height: 125px; position: relative; text-align: center } .case-pic span ...
- Storm集群扩容——从单机模式拓展到集群模式,以此类推
Storm是分布式的实时流处理系统,单机模式肯本不能体现其强大特点,尤其是当需要处理的数据很大很快的 时候,Storm可以随时扩容,而且操作非常简单,编写的应用程序自动负载均衡. 前面已经介绍了如何安 ...
- §12 循环101-while循环
§12 循环101-while循环 While和for具有一定的可替换性.语法如下: while test body continue终止当次循环,break退出整个循环. 注意while之后要用 ...
- tomcat7.0 的配置
一.安装JDK 1.7 1.添加环境变量:在 我的电脑->属性->高级->环境变量 2.新建系统变量,变量名:JAVA_HOME 变量值:C:\Program Files\Java\ ...
- jquery知识 内部 外部插入元素
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...