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的更多相关文章

  1. php精粹-编写高效的php代码 --- php设计模式

    1.选择一个最合适的设计模式 没有任何事物是完美的,也没有人说过设计模式一个严格的放之四海而皆准的解决方法.因此你可以改变这些模式,使它们更适合手头的工作.对于某些设计模式而言,他们就是所属程序固有的 ...

  2. 编写高效的Android代码

    编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...

  3. 编写高效的jQuery代码

    http://www.css88.com/jqapi-1.9/ 编写高效的jQuery代码 最近写了很多的js,虽然效果都实现了,但是总感觉自己写的js在性能上还能有很大的提升.本文我计划总结一些网上 ...

  4. 如何在Android上编写高效的Java代码

    转自:http://www.ituring.com.cn/article/177180 作者/ Erik Hellman Factor10咨询公司资深移动开发顾问,曾任索尼公司Android团队首席架 ...

  5. 如何编写高效的jQuery代码

    jQuery的编写原则: 一.不要过度使用jQuery 1. jQuery速度再快,也无法与原生的javascript方法相比,而且建立的jQuery对象包含的信息量很庞大.所以有原生方法可以使用的场 ...

  6. 如何编写高效的jQuery代码(转载)

    jQuery的编写原则: 一.不要过度使用jQuery 1. jQuery速度再快,也无法与原生的javascript方法相比,而且建立的jQuery对象包含的信息量很庞大.所以有原生方法可以使用的场 ...

  7. 利用on和off方法编写高效的js代码

    先说下将这个话题的起因:最近发现公司的功能代码,很多在dom对象删除以后,其声明的绑定在window上的resize事件还一直存在,导致相同的功能代码执行了几次.对于我这种轻微代码洁癖的人来说,简直是 ...

  8. (转载)编写高效的jQuery代码

    原文地址:http://www.cnblogs.com/ppforever/p/4084232.html 最近写了很多的js,虽然效果都实现了,但是总感觉自己写的js在性能上还能有很大的提升.本文我计 ...

  9. js学习笔记-编写高效、规范的js代码-Tom

    编写高效.规范的js代码: 1.变量命名空间问题,尽量使用局部变量,防止命名冲突(污染作用域中的全局变量):全局空间命名的变量可以在对应的文档域任意位置中使用window调用. 2.尽量使用单var定 ...

随机推荐

  1. Windows性能计数器--磁盘性能分析Disk

    Physical Disk: 单次IO大小 Avg.Disk Bytes/Read Avg.Disk Bytes/Write IO响应时间 Avg.Disk sec/Read Avg.Disk sec ...

  2. 【05】了解C++默默编写并调用那些函数

    1.如果没有声明copy构造方法,copy赋值操作符,和析构方法,编译器会自动生成这些方法,且是inline. 2.如果没有声明任何构造方法,编译器会自动生成一个default构造方法,且是inlin ...

  3. Palindrome(poj3974)(manacher算法)

    http://poj.org/problem?id=3974 Palindrome Time Limit: 15000MSMemory Limit: 65536K Total Submissions: ...

  4. C++ Combobox输入时自动完成

    Combobox 在输入时自动完成 关键点 实现过程 BOOL m_bAuto; BOOL CProject02Dlg::PreTranslateMessage(MSG* pMsg)  {     i ...

  5. cocos2dx 3.1创建工 mac

    1.下载cocos2dx 3.1版本号 2.打开终端,cd 进入 cocos2d-x-3.1.1/tools/cocos2d-console/bin 3.cocos new game -p com.t ...

  6. android 模拟器定在了任务栏出不来了

    系统 任务栏上显示了正在运行的模拟器,但是点击它,始终看不到模拟器显示出来.用Alt + Tab 切换也不行 按照网上的说法 1.重新建一个模拟器,名字变一下 2.找到模拟器对应的配置文件,路径不管, ...

  7. Apache【第一篇】安装

    一.简介 Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广泛使用,是最流行的Web ...

  8. 需要设置jdk的三处位置:

    需要设置jdk的三处位置:1.tomcat需要一个JDK : Windows--->Preferences--->MyEclipse--->Servers--->Tomcat- ...

  9. 转:ORACLE制造方法的比较

    转自:http://blog.itpub.net/133041/viewspace-438549/ 1.离散制造. 2.重复制造 3.流式制造 Oracle Applications 支持离散.项目. ...

  10. Java 十六进制转十进制

    public static int hexToDecimal(String hex) { int decimalValue = 0; for (int i = 0; i < hex.length ...