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定 ...
随机推荐
- C#性能优化的一些技巧
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:C#性能优化的一些技巧.
- c++虚表的使用 通过虚表调用虚函数的演示代码
//演示一下c++如何找到虚表地址vptr以及如何通过虚表调用虚函数 //zhangpeng@myhexin.com 20130811 #include <iostream> using ...
- windows API 实现截图
參考:http://bbs.csdn.net/topics/330154355 #include "stdio.h" #include "windows.h" ...
- Linux下用来获取各种系统信息的C++类
#include <vector> #include "sys/config.h" SYS_NAMESPACE_BEGIN /*** * 用来获取系统.内核和进程的各类 ...
- c#中cookies的存取操作
在客户端创建一个username的cookies,其值为gjy,有效期为1天. 方法1: Response.Cookies["username"].Value="zxf& ...
- 用Python和FFmpeg查找大码率的视频文件
用Python和FFmpeg查找大码率的视频文件 本文使用Python2.7, 这个工作分两步 遍历目录下的视频文件 用ffprobe获取是视频文件的码率信息 用ffprobe 获取json格式的视频 ...
- insert例子
11.20 使用insert代替下标操作. #include<iostream> #include<map> #include<string> #include&l ...
- C++ ORM ODB 入门介绍(一)
C++的语言特性决定了在C++中的ORM框架不可能像Java,C#那没有那么灵活. C++的ORM框架一般都是基于模板,编译时,因此其效率比起Java中的ORM框架更高. ODB是一个比较独立,成熟的 ...
- cocos2dx下最大纹理大小取决于平台
原文:http://www.cocos2d-x.org/wiki/Max_size_of_textures_in_cocos2d-x_depends_on_each_platform 在理论上,coc ...
- 【转】Cocos2d-x纹理优化的一些方案——2013-08-26 22
http://wap.oschina.net/question/565065_79814 在目前的移动平台游戏开发过程中,很多朋友会遇到开发出来的DEMO占用内存过大,导致渲染效率低下的问题.究其原因 ...